diff options
author | Lance Stout <lancestout@gmail.com> | 2011-01-19 19:49:13 -0500 |
---|---|---|
committer | Lance Stout <lancestout@gmail.com> | 2011-01-19 19:49:13 -0500 |
commit | da332365d4e97720ac182e0f66b73919d764a555 (patch) | |
tree | 7cf55e9711a96b649cd12b9be62d52b43d5bb9de | |
parent | f7e7bf601e6bd65cdb85f44c67e05b9ba66b0aeb (diff) | |
download | slixmpp-da332365d4e97720ac182e0f66b73919d764a555.tar.gz slixmpp-da332365d4e97720ac182e0f66b73919d764a555.tar.bz2 slixmpp-da332365d4e97720ac182e0f66b73919d764a555.tar.xz slixmpp-da332365d4e97720ac182e0f66b73919d764a555.zip |
Make extending stanza objects nicer.
A stanza object may add is_extension = True to its class definition
to provide a single new interface to a parent stanza.
For example:
import sleekxmpp
from sleekxmpp import Iq
from sleekxmpp.xmlstream import ElementBase, register_stanza_plugin, ET
class Foo(ElementBase):
"""
Test adding just an attribute to a parent stanza.
Adding subelements works as expected.
"""
is_extension = True
interfaces = set(('foo',))
plugin_attrib = 'foo'
def setup(self, xml):
# Don't include an XML element in the parent stanza
# since we're adding just an attribute.
# If adding a regular subelement, no need to do this.
self.xml = ET.Element('')
def set_foo(self, val):
self.parent()._set_attr('foo', val)
def get_foo(self):
return self.parent()._get_attr('foo')
def del_foo(self):
self.parent()._del_attr('foo')
register_stanza_plugin(Iq, Foo)
i1 = Iq()
i2 = Iq(xml=ET.fromstring("<iq xmlns='jabber:client' foo='bar' />"))
>>> i1['foo'] = '3'
>>> i1
'3'
>>> i1
'<iq id="0" foo="3" />'
>>> i2
'<iq id="0" foo="bar" />'
>>> i2['foo']
'bar'
>>> del i2['foo']
>>> i2
'<iq id="0" />'
-rw-r--r-- | sleekxmpp/xmlstream/stanzabase.py | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 5551d439..2c008668 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -95,10 +95,22 @@ class ElementBase(object): >>> message['custom']['useful_thing'] = 'foo' If a plugin provides an interface that is the same as the plugin's - plugin_attrib value, then the plugin's interface may be accessed - directly from the parent stanza, as so: + plugin_attrib value, then the plugin's interface may be assigned + directly from the parent stanza, as shown below, but retrieving + information will require all interfaces to be used, as so: >>> message['custom'] = 'bar' # Same as using message['custom']['custom'] + >>> message['custom']['custom'] # Must use all interfaces + 'bar' + + If the plugin sets the value is_extension = True, then both setting + and getting an interface value that is the same as the plugin's + plugin_attrib value will work, as so: + + >>> message['custom'] = 'bar' # Using is_extension=True + >>> message['custom'] + 'bar' + Class Attributes: name -- The name of the stanza's main element. @@ -116,6 +128,10 @@ class ElementBase(object): associated plugin stanza classes. plugin_tag_map -- A mapping of plugin stanza tag names with the associated plugin stanza classes. + is_extension -- When True, allows the stanza to provide one + additional interface to the parent stanza, + extending the interfaces supported by the + parent. Defaults to False. xml_ns -- The XML namespace, http://www.w3.org/XML/1998/namespace, for use with xml:lang values. @@ -173,6 +189,7 @@ class ElementBase(object): plugin_attrib_map = {} plugin_tag_map = {} subitem = None + is_extension = False xml_ns = 'http://www.w3.org/XML/1998/namespace' def __init__(self, xml=None, parent=None): @@ -371,6 +388,8 @@ class ElementBase(object): elif attrib in self.plugin_attrib_map: if attrib not in self.plugins: self.init_plugin(attrib) + if self.plugins[attrib].is_extension: + return self.plugins[attrib][attrib] return self.plugins[attrib] else: return '' @@ -467,8 +486,13 @@ class ElementBase(object): elif attrib in self.plugin_attrib_map: if attrib in self.plugins: xml = self.plugins[attrib].xml + if self.plugins[attrib].is_extension: + del self.plugins[attrib][attrib] del self.plugins[attrib] - self.xml.remove(xml) + try: + self.xml.remove(xml) + except: + pass return self def _set_attr(self, name, value): |