summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sleekxmpp/clientxmpp.py11
-rw-r--r--sleekxmpp/exceptions.py21
-rw-r--r--sleekxmpp/plugins/xep_0060/pubsub.py415
-rw-r--r--sleekxmpp/plugins/xep_0060/stanza/pubsub.py320
-rw-r--r--sleekxmpp/plugins/xep_0060/stanza/pubsub_owner.py187
-rw-r--r--sleekxmpp/stanza/iq.py8
-rw-r--r--sleekxmpp/test/sleektest.py1
-rw-r--r--tests/test_stream_handlers.py5
-rw-r--r--tests/test_stream_roster.py15
9 files changed, 410 insertions, 573 deletions
diff --git a/sleekxmpp/clientxmpp.py b/sleekxmpp/clientxmpp.py
index ad127726..366066de 100644
--- a/sleekxmpp/clientxmpp.py
+++ b/sleekxmpp/clientxmpp.py
@@ -227,8 +227,8 @@ class ClientXMPP(BaseXMPP):
'subscription': subscription,
'groups': groups}}
response = iq.send(block, timeout, callback)
- if response in [False, None] or not isinstance(response, Iq):
- return response
+ if response is None:
+ return None
return response['type'] == 'result'
def del_roster_item(self, jid):
@@ -261,12 +261,7 @@ class ClientXMPP(BaseXMPP):
iq.enable('roster')
response = iq.send(block, timeout, callback)
- if response == False:
- self.event('roster_timeout')
-
- if response in [False, None] or not isinstance(response, Iq):
- return response
- else:
+ if callback is None:
return self._handle_roster(response, request=True)
def _handle_connected(self, event=None):
diff --git a/sleekxmpp/exceptions.py b/sleekxmpp/exceptions.py
index 4727f0c6..8329a3c3 100644
--- a/sleekxmpp/exceptions.py
+++ b/sleekxmpp/exceptions.py
@@ -52,3 +52,24 @@ class XMPPError(Exception):
self.extension = extension
self.extension_ns = extension_ns
self.extension_args = extension_args
+
+
+class IqTimeout(Exception):
+
+ """
+ An exception which indicates that an IQ request response has not been
+ received within the alloted time window.
+ """
+
+ def __init__(self, iq):
+ self.iq = iq
+
+class IqError(Exception):
+
+ """
+ An exception raised when an Iq stanza of type 'error' is received
+ after making a blocking send call.
+ """
+
+ def __init__(self, iq):
+ self.iq = iq
diff --git a/sleekxmpp/plugins/xep_0060/pubsub.py b/sleekxmpp/plugins/xep_0060/pubsub.py
index e199be07..55362068 100644
--- a/sleekxmpp/plugins/xep_0060/pubsub.py
+++ b/sleekxmpp/plugins/xep_0060/pubsub.py
@@ -11,303 +11,118 @@ log = logging.getLogger(__name__)
class xep_0060(base.base_plugin):
- """
- XEP-0060 Publish Subscribe
- """
-
- def plugin_init(self):
- self.xep = '0060'
- self.description = 'Publish-Subscribe'
-
- def create_node(self, jid, node, config=None, collection=False, ntype=None):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
- create = ET.Element('create')
- create.set('node', node)
- pubsub.append(create)
- configure = ET.Element('configure')
- if collection:
- ntype = 'collection'
- #if config is None:
- # submitform = self.xmpp.plugin['xep_0004'].makeForm('submit')
- #else:
- if config is not None:
- submitform = config
- if 'FORM_TYPE' in submitform.field:
- submitform.field['FORM_TYPE'].setValue('http://jabber.org/protocol/pubsub#node_config')
- else:
- submitform.addField('FORM_TYPE', 'hidden', value='http://jabber.org/protocol/pubsub#node_config')
- if ntype:
- if 'pubsub#node_type' in submitform.field:
- submitform.field['pubsub#node_type'].setValue(ntype)
- else:
- submitform.addField('pubsub#node_type', value=ntype)
- else:
- if 'pubsub#node_type' in submitform.field:
- submitform.field['pubsub#node_type'].setValue('leaf')
- else:
- submitform.addField('pubsub#node_type', value='leaf')
- submitform['type'] = 'submit'
- configure.append(submitform.xml)
- pubsub.append(configure)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is False or result is None or result['type'] == 'error': return False
- return True
-
- def subscribe(self, jid, node, bare=True, subscribee=None):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
- subscribe = ET.Element('subscribe')
- subscribe.attrib['node'] = node
- if subscribee is None:
- if bare:
- subscribe.attrib['jid'] = self.xmpp.boundjid.bare
- else:
- subscribe.attrib['jid'] = self.xmpp.boundjid.full
- else:
- subscribe.attrib['jid'] = subscribee
- pubsub.append(subscribe)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is False or result is None or result['type'] == 'error': return False
- return True
-
- def unsubscribe(self, jid, node, bare=True, subscribee=None):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
- unsubscribe = ET.Element('unsubscribe')
- unsubscribe.attrib['node'] = node
- if subscribee is None:
- if bare:
- unsubscribe.attrib['jid'] = self.xmpp.boundjid.bare
- else:
- unsubscribe.attrib['jid'] = self.xmpp.boundjid.full
- else:
- unsubscribe.attrib['jid'] = subscribee
- pubsub.append(unsubscribe)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is False or result is None or result['type'] == 'error': return False
- return True
-
- def getNodeConfig(self, jid, node=None): # if no node, then grab default
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
- if node is not None:
- configure = ET.Element('configure')
- configure.attrib['node'] = node
- else:
- configure = ET.Element('default')
- pubsub.append(configure)
- #TODO: Add configure support.
- iq = self.xmpp.makeIqGet()
- iq.append(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- #self.xmpp.add_handler("<iq id='%s'/>" % id, self.handlerCreateNodeResponse)
- result = iq.send()
- if result is None or result == False or result['type'] == 'error':
- log.warning("got error instead of config")
- return False
- if node is not None:
- form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}configure/{jabber:x:data}x')
- else:
- form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}default/{jabber:x:data}x')
- if not form or form is None:
- log.error("No form found.")
- return False
- return Form(xml=form)
-
- def getNodeSubscriptions(self, jid, node):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
- subscriptions = ET.Element('subscriptions')
- subscriptions.attrib['node'] = node
- pubsub.append(subscriptions)
- iq = self.xmpp.makeIqGet()
- iq.append(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is None or result == False or result['type'] == 'error':
- log.warning("got error instead of config")
- return False
- else:
- results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}subscriptions/{http://jabber.org/protocol/pubsub#owner}subscription')
- if results is None:
- return False
- subs = {}
- for sub in results:
- subs[sub.get('jid')] = sub.get('subscription')
- return subs
-
- def getNodeAffiliations(self, jid, node):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
- affiliations = ET.Element('affiliations')
- affiliations.attrib['node'] = node
- pubsub.append(affiliations)
- iq = self.xmpp.makeIqGet()
- iq.append(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is None or result == False or result['type'] == 'error':
- log.warning("got error instead of config")
- return False
- else:
- results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}affiliations/{http://jabber.org/protocol/pubsub#owner}affiliation')
- if results is None:
- return False
- subs = {}
- for sub in results:
- subs[sub.get('jid')] = sub.get('affiliation')
- return subs
-
- def deleteNode(self, jid, node):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
- iq = self.xmpp.makeIqSet()
- delete = ET.Element('delete')
- delete.attrib['node'] = node
- pubsub.append(delete)
- iq.append(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- result = iq.send()
- if result is not None and result is not False and result['type'] != 'error':
- return True
- else:
- return False
-
-
- def setNodeConfig(self, jid, node, config):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
- configure = ET.Element('configure')
- configure.attrib['node'] = node
- config = config.getXML('submit')
- configure.append(config)
- pubsub.append(configure)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is None or result['type'] == 'error':
- return False
- return True
-
- def setItem(self, jid, node, items=[]):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
- publish = ET.Element('publish')
- publish.attrib['node'] = node
- for pub_item in items:
- id, payload = pub_item
- item = ET.Element('item')
- if id is not None:
- item.attrib['id'] = id
- item.append(payload)
- publish.append(item)
- pubsub.append(publish)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is None or result is False or result['type'] == 'error': return False
- return True
-
- def addItem(self, jid, node, items=[]):
- return self.setItem(jid, node, items)
-
- def deleteItem(self, jid, node, item):
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
- retract = ET.Element('retract')
- retract.attrib['node'] = node
- itemn = ET.Element('item')
- itemn.attrib['id'] = item
- retract.append(itemn)
- pubsub.append(retract)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is None or result is False or result['type'] == 'error': return False
- return True
-
- def getNodes(self, jid):
- response = self.xmpp.plugin['xep_0030'].getItems(jid)
- items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
- nodes = {}
- if items is not None and items is not False:
- for item in items:
- nodes[item.get('node')] = item.get('name')
- return nodes
-
- def getItems(self, jid, node):
- response = self.xmpp.plugin['xep_0030'].getItems(jid, node)
- items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
- nodeitems = []
- if items is not None and items is not False:
- for item in items:
- nodeitems.append(item.get('node'))
- return nodeitems
-
- def addNodeToCollection(self, jid, child, parent=''):
- config = self.getNodeConfig(jid, child)
- if not config or config is None:
- self.lasterror = "Config Error"
- return False
- try:
- config.field['pubsub#collection'].setValue(parent)
- except KeyError:
- log.warning("pubsub#collection doesn't exist in config, trying to add it")
- config.addField('pubsub#collection', value=parent)
- if not self.setNodeConfig(jid, child, config):
- return False
- return True
-
- def modifyAffiliation(self, ps_jid, node, user_jid, affiliation):
- if affiliation not in ('owner', 'publisher', 'member', 'none', 'outcast'):
- raise TypeError
- pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
- affs = ET.Element('affiliations')
- affs.attrib['node'] = node
- aff = ET.Element('affiliation')
- aff.attrib['jid'] = user_jid
- aff.attrib['affiliation'] = affiliation
- affs.append(aff)
- pubsub.append(affs)
- iq = self.xmpp.makeIqSet(pubsub)
- iq.attrib['to'] = ps_jid
- iq.attrib['from'] = self.xmpp.boundjid.full
- id = iq['id']
- result = iq.send()
- if result is None or result is False or result['type'] == 'error':
- return False
- return True
-
- def addNodeToCollection(self, jid, child, parent=''):
- config = self.getNodeConfig(jid, child)
- if not config or config is None:
- self.lasterror = "Config Error"
- return False
- try:
- config.field['pubsub#collection'].setValue(parent)
- except KeyError:
- log.warning("pubsub#collection doesn't exist in config, trying to add it")
- config.addField('pubsub#collection', value=parent)
- if not self.setNodeConfig(jid, child, config):
- return False
- return True
-
- def removeNodeFromCollection(self, jid, child):
- self.addNodeToCollection(jid, child, '')
-
+ """
+ XEP-0060 Publish Subscribe
+ """
+
+ def plugin_init(self):
+ self.xep = '0060'
+ self.description = 'Publish-Subscribe'
+
+ def create_node(self, jid, node, config=None, ntype=None):
+ iq = IQ(sto=jid, stype='set', sfrom=self.xmpp.jid)
+ iq['pubsub']['create']['node'] = node
+ if ntype is None:
+ ntype = 'leaf'
+ if config is not None:
+ if 'FORM_TYPE' in submitform.field:
+ config.field['FORM_TYPE'].setValue('http://jabber.org/protocol/pubsub#node_config')
+ else:
+ config.addField('FORM_TYPE', 'hidden', value='http://jabber.org/protocol/pubsub#node_config')
+ if 'pubsub#node_type' in submitform.field:
+ config.field['pubsub#node_type'].setValue(ntype)
+ else:
+ config.addField('pubsub#node_type', value=ntype)
+ iq['pubsub']['configure']['form'] = config
+ return iq.send()
+
+ def subscribe(self, jid, node, bare=True, subscribee=None):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='set')
+ iq['pubsub']['subscribe']['node'] = node
+ if subscribee is None:
+ if bare:
+ iq['pubsub']['subscribe']['jid'] = self.xmpp.jid.bare
+ else:
+ iq['pubsub']['subscribe']['jid'] = self.xmpp.jid.full
+ else:
+ iq['pubsub']['subscribe']['jid'] = subscribee
+ return iq.send()
+
+ def unsubscribe(self, jid, node, subid=None, bare=True, subscribee=None):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='set')
+ iq['pubsub']['unsubscribe']['node'] = node
+ if subscribee is None:
+ if bare:
+ iq['pubsub']['unsubscribe']['jid'] = self.xmpp.jid.bare
+ else:
+ iq['pubsub']['unsubscribe']['jid'] = self.xmpp.jid.full
+ else:
+ iq['pubsub']['unsubscribe']['jid'] = subscribee
+ if subid is not None:
+ iq['pubsub']['unsubscribe']['subid'] = subid
+ return iq.send()
+
+ def get_node_config(self, jid, node=None): # if no node, then grab default
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='get')
+ if node is None:
+ iq['pubsub_owner']['default']
+ else:
+ iq['pubsub_owner']['configure']['node'] = node
+ return iq.send()
+
+ def get_node_subscriptions(self, jid, node):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='get')
+ iq['pubsub_owner']['subscriptions']['node'] = node
+ return iq.send()
+
+ def get_node_affiliations(self, jid, node):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='get')
+ iq['pubsub_owner']['affiliations']['node'] = node
+ return iq.send()
+
+ def delete_node(self, jid, node):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='get')
+ iq['pubsub_owner']['delete']['node'] = node
+ return iq.send()
+
+ def set_node_config(self, jid, node, config):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='set')
+ iq['pubsub_owner']['configure']['node'] = node
+ iq['pubsub_owner']['configure']['config'] = config
+ return iq.send()
+
+ def publish(self, jid, node, items=[]):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='set')
+ iq['pubsub']['publish']['node'] = node
+ for id, payload in items:
+ item = stanza.pubsub.Item()
+ if id is not None:
+ item['id'] = id
+ item['payload'] = payload
+ iq['pubsub']['publish'].append(item)
+ return iq.send()
+
+ def retract(self, jid, node, item):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='set')
+ iq['pubsub']['retract']['node'] = node
+ item = stanza.pubsub.Item()
+ item['id'] = item
+ iq['pubsub']['retract'].append(item)
+ return iq.send()
+
+ def get_nodes(self, jid):
+ return self.xmpp.plugin['xep_0030'].get_items(jid)
+
+ def getItems(self, jid, node):
+ return self.xmpp.plugin['xep_0030'].get_items(jid, node)
+
+ def modify_affiliation(self, jid, node, affiliation, user_jid=None):
+ iq = IQ(sto=jid, sfrom=self.xmpp.jid, stype='set')
+ iq['pubsub_owner']['affiliations']
+ aff = stanza.pubsub.Affiliation()
+ aff['node'] = node
+ if user_jid is not None:
+ aff['jid'] = user_jid
+ aff['affiliation'] = affiliation
+ iq['pubsub_owner']['affiliations'].append(aff)
+ return iq.send()
diff --git a/sleekxmpp/plugins/xep_0060/stanza/pubsub.py b/sleekxmpp/plugins/xep_0060/stanza/pubsub.py
index 96655942..d9e55052 100644
--- a/sleekxmpp/plugins/xep_0060/stanza/pubsub.py
+++ b/sleekxmpp/plugins/xep_0060/stanza/pubsub.py
@@ -9,236 +9,236 @@ from sleekxmpp.plugins.xep_0060.stanza.base import OptionalSetting
class Pubsub(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'pubsub'
- plugin_attrib = 'pubsub'
- interfaces = set(tuple())
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'pubsub'
+ plugin_attrib = 'pubsub'
+ interfaces = set(tuple())
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
registerStanzaPlugin(Iq, Pubsub)
class Affiliation(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'affiliation'
- plugin_attrib = name
- interfaces = set(('node', 'affiliation'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'affiliation'
+ plugin_attrib = name
+ interfaces = set(('node', 'affiliation', 'jid'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
+
+ def getJid(self):
+ return JID(self._getAttr('jid'))
class Affiliations(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'affiliations'
- plugin_attrib = 'affiliations'
- interfaces = set(tuple())
- plugin_attrib_map = {}
- plugin_tag_map = {}
- subitem = (Affiliation,)
-
- def append(self, affiliation):
- if not isinstance(affiliation, Affiliation):
- raise TypeError
- self.xml.append(affiliation.xml)
- return self.iterables.append(affiliation)
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'affiliations'
+ plugin_attrib = 'affiliations'
+ interfaces = set(tuple())
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ subitem = (Affiliation,)
registerStanzaPlugin(Pubsub, Affiliations)
class Subscription(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'subscription'
- plugin_attrib = name
- interfaces = set(('jid', 'node', 'subscription', 'subid'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'subscription'
+ plugin_attrib = name
+ interfaces = set(('jid', 'node', 'subscription', 'subid'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def setjid(self, value):
- self._setattr('jid', str(value))
+ def setjid(self, value):
+ self._setattr('jid', str(value))
- def getjid(self):
- return jid(self._getattr('jid'))
+ def getjid(self):
+ return jid(self._getattr('jid'))
registerStanzaPlugin(Pubsub, Subscription)
class Subscriptions(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'subscriptions'
- plugin_attrib = 'subscriptions'
- interfaces = set(tuple())
- plugin_attrib_map = {}
- plugin_tag_map = {}
- subitem = (Subscription,)
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'subscriptions'
+ plugin_attrib = 'subscriptions'
+ interfaces = set(tuple())
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ subitem = (Subscription,)
registerStanzaPlugin(Pubsub, Subscriptions)
class SubscribeOptions(ElementBase, OptionalSetting):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'subscribe-options'
- plugin_attrib = 'suboptions'
- plugin_attrib_map = {}
- plugin_tag_map = {}
- interfaces = set(('required',))
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'subscribe-options'
+ plugin_attrib = 'suboptions'
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ interfaces = set(('required',))
registerStanzaPlugin(Subscription, SubscribeOptions)
class Item(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'item'
- plugin_attrib = name
- interfaces = set(('id', 'payload'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'item'
+ plugin_attrib = name
+ interfaces = set(('id', 'payload'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def setPayload(self, value):
- self.xml.append(value)
+ def setPayload(self, value):
+ self.xml.append(value)
- def getPayload(self):
- childs = self.xml.getchildren()
- if len(childs) > 0:
- return childs[0]
+ def getPayload(self):
+ childs = self.xml.getchildren()
+ if len(childs) > 0:
+ return childs[0]
- def delPayload(self):
- for child in self.xml.getchildren():
- self.xml.remove(child)
+ def delPayload(self):
+ for child in self.xml.getchildren():
+ self.xml.remove(child)
class Items(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'items'
- plugin_attrib = 'items'
- interfaces = set(('node',))
- plugin_attrib_map = {}
- plugin_tag_map = {}
- subitem = (Item,)
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'items'
+ plugin_attrib = 'items'
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ subitem = (Item,)
registerStanzaPlugin(Pubsub, Items)
class Create(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'create'
- plugin_attrib = name
- interfaces = set(('node',))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'create'
+ plugin_attrib = name
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
registerStanzaPlugin(Pubsub, Create)
#class Default(ElementBase):
-# namespace = 'http://jabber.org/protocol/pubsub'
-# name = 'default'
-# plugin_attrib = name
-# interfaces = set(('node', 'type'))
-# plugin_attrib_map = {}
-# plugin_tag_map = {}
+# namespace = 'http://jabber.org/protocol/pubsub'
+# name = 'default'
+# plugin_attrib = name
+# interfaces = set(('node', 'type'))
+# plugin_attrib_map = {}
+# plugin_tag_map = {}
#
-# def getType(self):
-# t = self._getAttr('type')
-# if not t: t == 'leaf'
-# return t
+# def getType(self):
+# t = self._getAttr('type')
+# if not t: t == 'leaf'
+# return t
#
#registerStanzaPlugin(Pubsub, Default)
class Publish(Items):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'publish'
- plugin_attrib = name
- interfaces = set(('node',))
- plugin_attrib_map = {}
- plugin_tag_map = {}
- subitem = (Item,)
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'publish'
+ plugin_attrib = name
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ subitem = (Item,)
registerStanzaPlugin(Pubsub, Publish)
class Retract(Items):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'retract'
- plugin_attrib = name
- interfaces = set(('node', 'notify'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'retract'
+ plugin_attrib = name
+ interfaces = set(('node', 'notify'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
registerStanzaPlugin(Pubsub, Retract)
class Unsubscribe(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'unsubscribe'
- plugin_attrib = name
- interfaces = set(('node', 'jid'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'unsubscribe'
+ plugin_attrib = name
+ interfaces = set(('node', 'jid', 'subid'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def setJid(self, value):
- self._setAttr('jid', str(value))
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
- def getJid(self):
- return JID(self._getAttr('jid'))
+ def getJid(self):
+ return JID(self._getAttr('jid'))
registerStanzaPlugin(Pubsub, Unsubscribe)
class Subscribe(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'subscribe'
- plugin_attrib = name
- interfaces = set(('node', 'jid'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'subscribe'
+ plugin_attrib = name
+ interfaces = set(('node', 'jid'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def setJid(self, value):
- self._setAttr('jid', str(value))
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
- def getJid(self):
- return JID(self._getAttr('jid'))
+ def getJid(self):
+ return JID(self._getAttr('jid'))
registerStanzaPlugin(Pubsub, Subscribe)
class Configure(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'configure'
- plugin_attrib = name
- interfaces = set(('node', 'type'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
-
- def getType(self):
- t = self._getAttr('type')
- if not t: t == 'leaf'
- return t
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'configure'
+ plugin_attrib = name
+ interfaces = set(('node', 'type'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def getType(self):
+ t = self._getAttr('type')
+ if not t: t == 'leaf'
+ return t
registerStanzaPlugin(Pubsub, Configure)
registerStanzaPlugin(Configure, xep_0004.Form)
class Options(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub'
- name = 'options'
- plugin_attrib = 'options'
- interfaces = set(('jid', 'node', 'options'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
-
- def __init__(self, *args, **kwargs):
- ElementBase.__init__(self, *args, **kwargs)
-
- def getOptions(self):
- config = self.xml.find('{jabber:x:data}x')
- form = xep_0004.Form()
- if config is not None:
- form.fromXML(config)
- return form
-
- def setOptions(self, value):
- self.xml.append(value.getXML())
- return self
-
- def delOptions(self):
- config = self.xml.find('{jabber:x:data}x')
- self.xml.remove(config)
-
- def setJid(self, value):
- self._setAttr('jid', str(value))
-
- def getJid(self):
- return JID(self._getAttr('jid'))
+ namespace = 'http://jabber.org/protocol/pubsub'
+ name = 'options'
+ plugin_attrib = 'options'
+ interfaces = set(('jid', 'node', 'options'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def __init__(self, *args, **kwargs):
+ ElementBase.__init__(self, *args, **kwargs)
+
+ def getOptions(self):
+ config = self.xml.find('{jabber:x:data}x')
+ form = xep_0004.Form()
+ if config is not None:
+ form.fromXML(config)
+ return form
+
+ def setOptions(self, value):
+ self.xml.append(value.getXML())
+ return self
+
+ def delOptions(self):
+ config = self.xml.find('{jabber:x:data}x')
+ self.xml.remove(config)
+
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
+
+ def getJid(self):
+ return JID(self._getAttr('jid'))
registerStanzaPlugin(Pubsub, Options)
registerStanzaPlugin(Subscribe, Options)
diff --git a/sleekxmpp/plugins/xep_0060/stanza/pubsub_owner.py b/sleekxmpp/plugins/xep_0060/stanza/pubsub_owner.py
index a90780cc..201dc909 100644
--- a/sleekxmpp/plugins/xep_0060/stanza/pubsub_owner.py
+++ b/sleekxmpp/plugins/xep_0060/stanza/pubsub_owner.py
@@ -9,144 +9,147 @@ from sleekxmpp.plugins.xep_0060.stanza.base import OptionalSetting
from sleekxmpp.plugins.xep_0060.stanza.pubsub import Affiliations, Affiliation, Configure, Subscriptions
class PubsubOwner(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- name = 'pubsub'
- plugin_attrib = 'pubsub_owner'
- interfaces = set(tuple())
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ name = 'pubsub'
+ plugin_attrib = 'pubsub_owner'
+ interfaces = set(tuple())
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
registerStanzaPlugin(Iq, PubsubOwner)
class DefaultConfig(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- name = 'default'
- plugin_attrib = 'default'
- interfaces = set(('node', 'type', 'config'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ name = 'default'
+ plugin_attrib = 'default'
+ interfaces = set(('node', 'type', 'config'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def __init__(self, *args, **kwargs):
- ElementBase.__init__(self, *args, **kwargs)
+ def __init__(self, *args, **kwargs):
+ ElementBase.__init__(self, *args, **kwargs)
- def getType(self):
- t = self._getAttr('type')
- if not t: t = 'leaf'
- return t
+ def getType(self):
+ t = self._getAttr('type')
+ if not t: t = 'leaf'
+ return t
- def getConfig(self):
- return self['form']
+ def getConfig(self):
+ return self['form']
- def setConfig(self, value):
- self['form'].setStanzaValues(value.getStanzaValues())
- return self
+ def setConfig(self, value):
+ self['form'].setStanzaValues(value.getStanzaValues())
+ return self
registerStanzaPlugin(PubsubOwner, DefaultConfig)
registerStanzaPlugin(DefaultConfig, xep_0004.Form)
class OwnerAffiliations(Affiliations):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- interfaces = set(('node'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ interfaces = set(('node'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def append(self, affiliation):
- if not isinstance(affiliation, OwnerAffiliation):
- raise TypeError
- self.xml.append(affiliation.xml)
- return self.affiliations.append(affiliation)
+ def append(self, affiliation):
+ if not isinstance(affiliation, OwnerAffiliation):
+ raise TypeError
+ self.xml.append(affiliation.xml)
+ return self.affiliations.append(affiliation)
registerStanzaPlugin(PubsubOwner, OwnerAffiliations)
class OwnerAffiliation(Affiliation):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- interfaces = set(('affiliation', 'jid'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ interfaces = set(('affiliation', 'jid'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
class OwnerConfigure(Configure):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- interfaces = set(('node', 'config'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ name = 'configure'
+ plugin_attrib = 'configure'
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ interfaces = set(('node', 'config'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def getConfig(self):
+ return self['form']
+
+ def setConfig(self, value):
+ self['form'].setStanzaValues(value.getStanzaValues())
+ return self
registerStanzaPlugin(PubsubOwner, OwnerConfigure)
class OwnerDefault(OwnerConfigure):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- interfaces = set(('node', 'config'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ interfaces = set(('node', 'config'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def getConfig(self):
- return self['form']
-
- def setConfig(self, value):
- self['form'].setStanzaValues(value.getStanzaValues())
- return self
registerStanzaPlugin(PubsubOwner, OwnerDefault)
registerStanzaPlugin(OwnerDefault, xep_0004.Form)
class OwnerDelete(ElementBase, OptionalSetting):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- name = 'delete'
- plugin_attrib = 'delete'
- plugin_attrib_map = {}
- plugin_tag_map = {}
- interfaces = set(('node',))
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ name = 'delete'
+ plugin_attrib = 'delete'
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ interfaces = set(('node',))
registerStanzaPlugin(PubsubOwner, OwnerDelete)
class OwnerPurge(ElementBase, OptionalSetting):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- name = 'purge'
- plugin_attrib = name
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ name = 'purge'
+ plugin_attrib = name
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
registerStanzaPlugin(PubsubOwner, OwnerPurge)
class OwnerRedirect(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- name = 'redirect'
- plugin_attrib = name
- interfaces = set(('node', 'jid'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ name = 'redirect'
+ plugin_attrib = name
+ interfaces = set(('node', 'jid'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def setJid(self, value):
- self._setAttr('jid', str(value))
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
- def getJid(self):
- return JID(self._getAttr('jid'))
+ def getJid(self):
+ return JID(self._getAttr('jid'))
registerStanzaPlugin(OwnerDelete, OwnerRedirect)
class OwnerSubscriptions(Subscriptions):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- interfaces = set(('node',))
- plugin_attrib_map = {}
- plugin_tag_map = {}
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
- def append(self, subscription):
- if not isinstance(subscription, OwnerSubscription):
- raise TypeError
- self.xml.append(subscription.xml)
- return self.subscriptions.append(subscription)
+ def append(self, subscription):
+ if not isinstance(subscription, OwnerSubscription):
+ raise TypeError
+ self.xml.append(subscription.xml)
+ return self.subscriptions.append(subscription)
registerStanzaPlugin(PubsubOwner, OwnerSubscriptions)
class OwnerSubscription(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub#owner'
- name = 'subscription'
- plugin_attrib = name
- interfaces = set(('jid', 'subscription'))
- plugin_attrib_map = {}
- plugin_tag_map = {}
-
- def setJid(self, value):
- self._setAttr('jid', str(value))
-
- def getJid(self):
- return JID(self._getAttr('from'))
+ namespace = 'http://jabber.org/protocol/pubsub#owner'
+ name = 'subscription'
+ plugin_attrib = name
+ interfaces = set(('jid', 'subscription'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
+
+ def getJid(self):
+ return JID(self._getAttr('from'))
diff --git a/sleekxmpp/stanza/iq.py b/sleekxmpp/stanza/iq.py
index 4a12a87e..f05dad17 100644
--- a/sleekxmpp/stanza/iq.py
+++ b/sleekxmpp/stanza/iq.py
@@ -11,6 +11,7 @@ from sleekxmpp.stanza.rootstanza import RootStanza
from sleekxmpp.xmlstream import StanzaBase, ET
from sleekxmpp.xmlstream.handler import Waiter, Callback
from sleekxmpp.xmlstream.matcher import MatcherId
+from sleekxmpp.exceptions import IqTimeout, IqError
class Iq(RootStanza):
@@ -197,7 +198,12 @@ class Iq(RootStanza):
waitfor = Waiter('IqWait_%s' % self['id'], MatcherId(self['id']))
self.stream.register_handler(waitfor)
StanzaBase.send(self, now=now)
- return waitfor.wait(timeout)
+ result = waitfor.wait(timeout)
+ if not result:
+ raise IqTimeout(self)
+ if result['type'] == 'error':
+ raise IqError(result)
+ return result
else:
return StanzaBase.send(self, now=now)
diff --git a/sleekxmpp/test/sleektest.py b/sleekxmpp/test/sleektest.py
index cb5031f7..d28ffd5d 100644
--- a/sleekxmpp/test/sleektest.py
+++ b/sleekxmpp/test/sleektest.py
@@ -16,6 +16,7 @@ import sleekxmpp
from sleekxmpp import ClientXMPP, ComponentXMPP
from sleekxmpp.stanza import Message, Iq, Presence
from sleekxmpp.test import TestSocket, TestLiveSocket
+from sleekxmpp.exceptions import XMPPError, IqTimeout, IqError
from sleekxmpp.xmlstream import ET, register_stanza_plugin
from sleekxmpp.xmlstream import ElementBase, StanzaBase
from sleekxmpp.xmlstream.tostring import tostring
diff --git a/tests/test_stream_handlers.py b/tests/test_stream_handlers.py
index dae4456d..1b831e21 100644
--- a/tests/test_stream_handlers.py
+++ b/tests/test_stream_handlers.py
@@ -90,7 +90,10 @@ class TestHandlers(SleekTest):
iq['id'] = 'test2'
iq['type'] = 'set'
iq['query'] = 'test2'
- reply = iq.send(block=True, timeout=0)
+ try:
+ reply = iq.send(block=True, timeout=0)
+ except IqTimeout:
+ pass
self.xmpp.add_event_handler('message', waiter_handler, threaded=True)
diff --git a/tests/test_stream_roster.py b/tests/test_stream_roster.py
index e1aa1766..95163744 100644
--- a/tests/test_stream_roster.py
+++ b/tests/test_stream_roster.py
@@ -111,19 +111,12 @@ class TestStreamRoster(SleekTest):
def testRosterTimeout(self):
"""Test handling a timed out roster request."""
self.stream_start()
- events = []
-
- def roster_timeout(event):
- events.append('roster_timeout')
-
- self.xmpp.add_event_handler('roster_timeout', roster_timeout)
- self.xmpp.get_roster(timeout=0)
- # Give the event queue time to process.
- time.sleep(.1)
+ def do_test():
+ self.xmpp.get_roster(timeout=0)
+ time.sleep(.1)
- self.failUnless(events == ['roster_timeout'],
- "Roster timeout event not triggered: %s." % events)
+ self.assertRaises(IqTimeout, do_test)
def testRosterCallback(self):
"""Test handling a roster request callback."""