diff --git a/sleekxmpp/plugins/stanza_pubsub.py b/sleekxmpp/plugins/stanza_pubsub.py
index 1334594..6ed84f1 100644
--- a/sleekxmpp/plugins/stanza_pubsub.py
+++ b/sleekxmpp/plugins/stanza_pubsub.py
@@ -45,7 +45,7 @@ class Affiliations(ElementBase):
interfaces = set(tuple())
plugin_attrib_map = {}
plugin_tag_map = {}
- subitem = Affiliation
+ subitem = (Affiliation,)
def append(self, affiliation):
if not isinstance(affiliation, Affiliation):
@@ -64,11 +64,11 @@ class Subscription(ElementBase):
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'))
stanzaPlugin(Pubsub, Subscription)
@@ -79,7 +79,7 @@ class Subscriptions(ElementBase):
interfaces = set(tuple())
plugin_attrib_map = {}
plugin_tag_map = {}
- subitem = Subscription
+ subitem = (Subscription,)
def __init__(self, *args, **kwargs):
ElementBase.__init__(self, *args, **kwargs)
@@ -176,7 +176,7 @@ class Items(ElementBase):
interfaces = set(tuple())
plugin_attrib_map = {}
plugin_tag_map = {}
- subitem = Item
+ subitem = (Item,)
stanzaPlugin(Pubsub, Items)
@@ -212,7 +212,7 @@ class Publish(Items):
interfaces = set(('node',))
plugin_attrib_map = {}
plugin_tag_map = {}
- subitem = Item
+ subitem = (Item,)
stanzaPlugin(Pubsub, Publish)
@@ -238,7 +238,7 @@ class Unsubscribe(ElementBase):
self._setAttr('jid', str(value))
def getJid(self):
- return JID(self._getAttr('from'))
+ return JID(self._getAttr('jid'))
class Subscribe(ElementBase):
namespace = 'http://jabber.org/protocol/pubsub'
@@ -433,7 +433,7 @@ class OwnerRedirect(ElementBase):
self._setAttr('jid', str(value))
def getJid(self):
- return JID(self._getAttr('from'))
+ return JID(self._getAttr('jid'))
stanzaPlugin(OwnerDelete, OwnerRedirect)
@@ -475,22 +475,123 @@ class Event(ElementBase):
stanzaPlugin(Message, Event)
-class EventItems(ElementBase):
- namespace = 'http://jabber.org/protocol/pubsub#event'
- name = 'items'
- plugin_attrib = 'items'
- interfaces = set(tuple())
- plugin_attrib_map = {}
- plugin_tag_map = {}
-
-stanzaPlugin(Event, EventItems)
-
class EventItem(ElementBase):
namespace = 'http://jabber.org/protocol/pubsub#event'
name = 'item'
plugin_attrib = 'item'
- interfaces = set(tuple())
+ interfaces = set(('id', 'payload'))
plugin_attrib_map = {}
plugin_tag_map = {}
+ def setPayload(self, value):
+ self.xml.append(value)
+
+ 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)
+
+
+class EventRetract(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'retract'
+ plugin_attrib = 'retract'
+ interfaces = set(('id',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+class EventItems(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'items'
+ plugin_attrib = 'items'
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+ subitem = (EventItem, EventRetract)
+
stanzaPlugin(Event, EventItems)
+
+class EventCollection(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'collection'
+ plugin_attrib = name
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+stanzaPlugin(Event, EventCollection)
+
+class EventAssociate(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'associate'
+ plugin_attrib = name
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+stanzaPlugin(EventCollection, EventAssociate)
+
+class EventDisassociate(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'disassociate'
+ plugin_attrib = name
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+stanzaPlugin(EventCollection, EventDisassociate)
+
+class EventConfiguration(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'configuration'
+ plugin_attrib = name
+ interfaces = set(('node', 'config'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def getConfig(self):
+ config = self.xml.find('{jabber:x:data}x')
+ form = xep_0004.Form()
+ if config is not None:
+ form.fromXML(config)
+ return form
+
+ def setConfig(self, value):
+ self.xml.append(value.getXML())
+ return self
+
+ def delConfig(self):
+ config = self.xml.find('{jabber:x:data}x')
+ self.xml.remove(config)
+
+stanzaPlugin(Event, EventConfiguration)
+
+class EventPurge(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'purge'
+ plugin_attrib = name
+ interfaces = set(('node',))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+stanzaPlugin(Event, EventPurge)
+
+class EventSubscription(ElementBase):
+ namespace = 'http://jabber.org/protocol/pubsub#event'
+ name = 'subscription'
+ plugin_attrib = name
+ interfaces = set(('node','expiry', 'jid', 'subid', 'subscription'))
+ plugin_attrib_map = {}
+ plugin_tag_map = {}
+
+ def setJid(self, value):
+ self._setAttr('jid', str(value))
+
+ def getJid(self):
+ return JID(self._getAttr('jid'))
+
+stanzaPlugin(Event, EventSubscription)
diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py
index f72aa6e..ae9e9df 100644
--- a/sleekxmpp/xmlstream/stanzabase.py
+++ b/sleekxmpp/xmlstream/stanzabase.py
@@ -60,8 +60,11 @@ class ElementBase(tostring.ToString):
for child in self.xml.getchildren():
if child.tag in self.plugin_tag_map:
self.plugins[self.plugin_tag_map[child.tag].plugin_attrib] = self.plugin_tag_map[child.tag](xml=child, parent=self)
- if self.subitem is not None and child.tag == "{%s}%s" % (self.subitem.namespace, self.subitem.name):
- self.iterables.append(self.subitem(xml=child, parent=self))
+ if self.subitem is not None:
+ for sub in self.subitem:
+ if child.tag == "{%s}%s" % (sub.namespace, sub.name):
+ self.iterables.append(sub(xml=child, parent=self))
+ break
@property
@@ -263,7 +266,10 @@ class ElementBase(tostring.ToString):
for pluginkey in self.plugins:
out[pluginkey] = self.plugins[pluginkey].getValues()
if self.iterables:
- iterables = [x.getValues() for x in self.iterables]
+ iterables = []
+ for stanza in self.iterables:
+ iterables.append(stanza.getValues())
+ iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)})
out['substanzas'] = iterables
return out
@@ -271,9 +277,13 @@ class ElementBase(tostring.ToString):
for interface in attrib:
if interface == 'substanzas':
for subdict in attrib['substanzas']:
- sub = self.subitem(parent=self)
- sub.setValues(subdict)
- self.iterables.append(sub)
+ if '__childtag__' in subdict:
+ for subclass in self.subitem:
+ if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name):
+ sub = subclass(parent=self)
+ sub.setValues(subdict)
+ self.iterables.append(sub)
+ break
elif interface in self.interfaces:
self[interface] = attrib[interface]
elif interface in self.plugin_attrib_map and interface not in self.plugins:
diff --git a/tests/test_pubsubstanzas.py b/tests/test_pubsubstanzas.py
index 2d1bf3b..5353f90 100644
--- a/tests/test_pubsubstanzas.py
+++ b/tests/test_pubsubstanzas.py
@@ -1,6 +1,7 @@
import unittest
from xml.etree import cElementTree as ET
from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath
+from . import xmlcompare
class testpubsubstanzas(unittest.TestCase):
@@ -169,4 +170,130 @@ class testpubsubstanzas(unittest.TestCase):
config = iq['pubsub']['configure']['config']
self.failUnless(config.getValues() != {})
+ def testItemEvent(self):
+ """Testing message/pubsub_event/items/item"""
+ msg = self.ps.Message()
+ item = self.ps.EventItem()
+ pl = ET.Element('{http://netflint.net/protocol/test}test', {'failed':'3', 'passed':'24'})
+ item['payload'] = pl
+ item['id'] = 'abc123'
+ msg['pubsub_event']['items'].append(item)
+ msg['pubsub_event']['items']['node'] = 'cheese'
+ msg['type'] = 'normal'
+ xmlstring = """ """
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testItemsEvent(self):
+ """Testing multiple message/pubsub_event/items/item"""
+ msg = self.ps.Message()
+ item = self.ps.EventItem()
+ item2 = self.ps.EventItem()
+ pl = ET.Element('{http://netflint.net/protocol/test}test', {'failed':'3', 'passed':'24'})
+ pl2 = ET.Element('{http://netflint.net/protocol/test-other}test', {'total':'27', 'failed':'3'})
+ item2['payload'] = pl2
+ item['payload'] = pl
+ item['id'] = 'abc123'
+ item2['id'] = '123abc'
+ msg['pubsub_event']['items'].append(item)
+ msg['pubsub_event']['items'].append(item2)
+ msg['pubsub_event']['items']['node'] = 'cheese'
+ msg['type'] = 'normal'
+ xmlstring = """ """
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testItemsEvent(self):
+ """Testing message/pubsub_event/items/item & retract mix"""
+ msg = self.ps.Message()
+ item = self.ps.EventItem()
+ item2 = self.ps.EventItem()
+ pl = ET.Element('{http://netflint.net/protocol/test}test', {'failed':'3', 'passed':'24'})
+ pl2 = ET.Element('{http://netflint.net/protocol/test-other}test', {'total':'27', 'failed':'3'})
+ item2['payload'] = pl2
+ retract = self.ps.EventRetract()
+ retract['id'] = 'aabbcc'
+ item['payload'] = pl
+ item['id'] = 'abc123'
+ item2['id'] = '123abc'
+ msg['pubsub_event']['items'].append(item)
+ msg['pubsub_event']['items'].append(retract)
+ msg['pubsub_event']['items'].append(item2)
+ msg['pubsub_event']['items']['node'] = 'cheese'
+ msg['type'] = 'normal'
+ xmlstring = """ """
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testCollectionAssociate(self):
+ """Testing message/pubsub_event/collection/associate"""
+ msg = self.ps.Message()
+ msg['pubsub_event']['collection']['associate']['node'] = 'cheese'
+ msg['pubsub_event']['collection']['node'] = 'cheeseburger'
+ msg['type'] = 'headline'
+ xmlstring = """"""
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testCollectionDisassociate(self):
+ """Testing message/pubsub_event/collection/disassociate"""
+ msg = self.ps.Message()
+ msg['pubsub_event']['collection']['disassociate']['node'] = 'cheese'
+ msg['pubsub_event']['collection']['node'] = 'cheeseburger'
+ msg['type'] = 'headline'
+ xmlstring = """"""
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testEventConfiguration(self):
+ """Testing message/pubsub_event/configuration/config"""
+ msg = self.ps.Message()
+ from sleekxmpp.plugins import xep_0004
+ form = xep_0004.Form()
+ form.addField('pubsub#title', ftype='text-single', value='This thing is awesome')
+ msg['pubsub_event']['configuration']['node'] = 'cheese'
+ msg['pubsub_event']['configuration']['config'] = form
+ msg['type'] = 'headline'
+ xmlstring = """This thing is awesome"""
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testEventPurge(self):
+ """Testing message/pubsub_event/purge"""
+ msg = self.ps.Message()
+ msg['pubsub_event']['purge']['node'] = 'pickles'
+ msg['type'] = 'headline'
+ xmlstring = """"""
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlstring == str(msg) == str(msg2) == str(msg3))
+
+ def testEventSubscription(self):
+ """Testing message/pubsub_event/subscription"""
+ msg = self.ps.Message()
+ msg['pubsub_event']['subscription']['node'] = 'pickles'
+ msg['pubsub_event']['subscription']['jid'] = 'fritzy@netflint.net/test'
+ msg['pubsub_event']['subscription']['subid'] = 'aabb1122'
+ msg['pubsub_event']['subscription']['subscription'] = 'subscribed'
+ msg['pubsub_event']['subscription']['expiry'] = 'presence'
+ msg['type'] = 'headline'
+ xmlstring = """"""
+ msg2 = self.ps.Message(None, self.ps.ET.fromstring(xmlstring))
+ msg3 = self.ps.Message()
+ msg3.setValues(msg2.getValues())
+ self.failUnless(xmlcompare.comparemany([xmlstring, str(msg), str(msg2), str(msg3)]))
+
suite = unittest.TestLoader().loadTestsFromTestCase(testpubsubstanzas)