mirror of
https://github.com/correl/SleekXMPP.git
synced 2025-01-12 11:08:16 +00:00
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" />'
This commit is contained in:
parent
f7e7bf601e
commit
da332365d4
1 changed files with 27 additions and 3 deletions
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue