added pubsub#event stanzas, multi-subtypes iterable stanzas, pubsub#event test coverage

This commit is contained in:
Nathan Fritz 2010-04-21 23:51:37 -07:00
parent 2a30e3fe0c
commit 37b571c55a
3 changed files with 265 additions and 27 deletions

View file

@ -45,7 +45,7 @@ class Affiliations(ElementBase):
interfaces = set(tuple()) interfaces = set(tuple())
plugin_attrib_map = {} plugin_attrib_map = {}
plugin_tag_map = {} plugin_tag_map = {}
subitem = Affiliation subitem = (Affiliation,)
def append(self, affiliation): def append(self, affiliation):
if not isinstance(affiliation, Affiliation): if not isinstance(affiliation, Affiliation):
@ -64,11 +64,11 @@ class Subscription(ElementBase):
plugin_attrib_map = {} plugin_attrib_map = {}
plugin_tag_map = {} plugin_tag_map = {}
def setJid(self, value): def setjid(self, value):
self._setAttr('jid', str(value)) self._setattr('jid', str(value))
def getJid(self): def getjid(self):
return JID(self._getAttr('jid')) return jid(self._getattr('jid'))
stanzaPlugin(Pubsub, Subscription) stanzaPlugin(Pubsub, Subscription)
@ -79,7 +79,7 @@ class Subscriptions(ElementBase):
interfaces = set(tuple()) interfaces = set(tuple())
plugin_attrib_map = {} plugin_attrib_map = {}
plugin_tag_map = {} plugin_tag_map = {}
subitem = Subscription subitem = (Subscription,)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
ElementBase.__init__(self, *args, **kwargs) ElementBase.__init__(self, *args, **kwargs)
@ -176,7 +176,7 @@ class Items(ElementBase):
interfaces = set(tuple()) interfaces = set(tuple())
plugin_attrib_map = {} plugin_attrib_map = {}
plugin_tag_map = {} plugin_tag_map = {}
subitem = Item subitem = (Item,)
stanzaPlugin(Pubsub, Items) stanzaPlugin(Pubsub, Items)
@ -212,7 +212,7 @@ class Publish(Items):
interfaces = set(('node',)) interfaces = set(('node',))
plugin_attrib_map = {} plugin_attrib_map = {}
plugin_tag_map = {} plugin_tag_map = {}
subitem = Item subitem = (Item,)
stanzaPlugin(Pubsub, Publish) stanzaPlugin(Pubsub, Publish)
@ -238,7 +238,7 @@ class Unsubscribe(ElementBase):
self._setAttr('jid', str(value)) self._setAttr('jid', str(value))
def getJid(self): def getJid(self):
return JID(self._getAttr('from')) return JID(self._getAttr('jid'))
class Subscribe(ElementBase): class Subscribe(ElementBase):
namespace = 'http://jabber.org/protocol/pubsub' namespace = 'http://jabber.org/protocol/pubsub'
@ -433,7 +433,7 @@ class OwnerRedirect(ElementBase):
self._setAttr('jid', str(value)) self._setAttr('jid', str(value))
def getJid(self): def getJid(self):
return JID(self._getAttr('from')) return JID(self._getAttr('jid'))
stanzaPlugin(OwnerDelete, OwnerRedirect) stanzaPlugin(OwnerDelete, OwnerRedirect)
@ -475,22 +475,123 @@ class Event(ElementBase):
stanzaPlugin(Message, Event) 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): class EventItem(ElementBase):
namespace = 'http://jabber.org/protocol/pubsub#event' namespace = 'http://jabber.org/protocol/pubsub#event'
name = 'item' name = 'item'
plugin_attrib = 'item' plugin_attrib = 'item'
interfaces = set(tuple()) interfaces = set(('id', 'payload'))
plugin_attrib_map = {} plugin_attrib_map = {}
plugin_tag_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) 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)

View file

@ -60,8 +60,11 @@ class ElementBase(tostring.ToString):
for child in self.xml.getchildren(): for child in self.xml.getchildren():
if child.tag in self.plugin_tag_map: 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) 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): if self.subitem is not None:
self.iterables.append(self.subitem(xml=child, parent=self)) for sub in self.subitem:
if child.tag == "{%s}%s" % (sub.namespace, sub.name):
self.iterables.append(sub(xml=child, parent=self))
break
@property @property
@ -263,7 +266,10 @@ class ElementBase(tostring.ToString):
for pluginkey in self.plugins: for pluginkey in self.plugins:
out[pluginkey] = self.plugins[pluginkey].getValues() out[pluginkey] = self.plugins[pluginkey].getValues()
if self.iterables: 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 out['substanzas'] = iterables
return out return out
@ -271,9 +277,13 @@ class ElementBase(tostring.ToString):
for interface in attrib: for interface in attrib:
if interface == 'substanzas': if interface == 'substanzas':
for subdict in attrib['substanzas']: for subdict in attrib['substanzas']:
sub = self.subitem(parent=self) 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) sub.setValues(subdict)
self.iterables.append(sub) self.iterables.append(sub)
break
elif interface in self.interfaces: elif interface in self.interfaces:
self[interface] = attrib[interface] self[interface] = attrib[interface]
elif interface in self.plugin_attrib_map and interface not in self.plugins: elif interface in self.plugin_attrib_map and interface not in self.plugins:

View file

@ -1,6 +1,7 @@
import unittest import unittest
from xml.etree import cElementTree as ET from xml.etree import cElementTree as ET
from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath
from . import xmlcompare
class testpubsubstanzas(unittest.TestCase): class testpubsubstanzas(unittest.TestCase):
@ -169,4 +170,130 @@ class testpubsubstanzas(unittest.TestCase):
config = iq['pubsub']['configure']['config'] config = iq['pubsub']['configure']['config']
self.failUnless(config.getValues() != {}) 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 = """<message type="normal"><event xmlns="http://jabber.org/protocol/pubsub#event"><items node="cheese"><item id="abc123"><test xmlns="http://netflint.net/protocol/test" failed="3" passed="24" /></item></items></event></message>"""
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 = """<message type="normal"><event xmlns="http://jabber.org/protocol/pubsub#event"><items node="cheese"><item id="abc123"><test xmlns="http://netflint.net/protocol/test" failed="3" passed="24" /></item><item id="123abc"><test xmlns="http://netflint.net/protocol/test-other" failed="3" total="27" /></item></items></event></message>"""
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 = """<message type="normal"><event xmlns="http://jabber.org/protocol/pubsub#event"><items node="cheese"><item id="abc123"><test xmlns="http://netflint.net/protocol/test" failed="3" passed="24" /></item><retract id="aabbcc" /><item id="123abc"><test xmlns="http://netflint.net/protocol/test-other" failed="3" total="27" /></item></items></event></message>"""
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 = """<message type="headline"><event xmlns="http://jabber.org/protocol/pubsub#event"><collection node="cheeseburger"><associate node="cheese" /></collection></event></message>"""
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 = """<message type="headline"><event xmlns="http://jabber.org/protocol/pubsub#event"><collection node="cheeseburger"><disassociate node="cheese" /></collection></event></message>"""
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 = """<message type="headline"><event xmlns="http://jabber.org/protocol/pubsub#event"><configuration node="cheese"><x xmlns="jabber:x:data" type="form"><field var="pubsub#title" type="text-single"><value>This thing is awesome</value></field></x></configuration></event></message>"""
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 = """<message type="headline"><event xmlns="http://jabber.org/protocol/pubsub#event"><purge node="pickles" /></event></message>"""
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 = """<message type="headline"><event xmlns="http://jabber.org/protocol/pubsub#event"><subscription node="pickles" subid="aabb1122" jid="fritzy@netflint.net/test" subscription="subscribed" expiry="presence" /></event></message>"""
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) suite = unittest.TestLoader().loadTestsFromTestCase(testpubsubstanzas)