summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLance Stout <lancestout@gmail.com>2011-01-19 19:49:13 -0500
committerLance Stout <lancestout@gmail.com>2011-01-19 19:49:13 -0500
commitda332365d4e97720ac182e0f66b73919d764a555 (patch)
tree7cf55e9711a96b649cd12b9be62d52b43d5bb9de
parentf7e7bf601e6bd65cdb85f44c67e05b9ba66b0aeb (diff)
downloadslixmpp-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.py30
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):