From 9962f1a664cfe72b88d78d8541f269f290de8643 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Sun, 6 Jun 2010 23:12:54 -0400 Subject: Added a __copy__ method to both ElementBase and StanzaBase. Stanzas may now be copied using copy.copy(), which will be useful to prevent stanza objects from being shared between event handlers. --- sleekxmpp/xmlstream/stanzabase.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 64020c8f..a0d8f5d0 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -10,6 +10,7 @@ import logging import traceback import sys import weakref +import copy if sys.version_info < (3,0): from . import tostring26 as tostring @@ -308,6 +309,9 @@ class ElementBase(tostring.ToString): def appendxml(self, xml): self.xml.append(xml) return self + + def __copy__(self): + return self.__class__(xml=copy.copy(self.xml), parent=self.parent) #def __del__(self): #prevents garbage collection of reference cycle # if self.parent is not None: @@ -386,3 +390,6 @@ class StanzaBase(ElementBase): def send(self): self.stream.sendRaw(self.__str__()) + def __copy__(self): + return self.__class__(xml=copy.copy(self.xml), stream=self.stream) + -- cgit v1.2.3 From 8bb0f5e34c443a9efc05dadb2a77a95ac94c2c98 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 7 Jun 2010 19:55:39 -0400 Subject: Needed to use copy.deepcopy() to copy XML objects to make sure that the entire tree is copied. --- sleekxmpp/xmlstream/stanzabase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index a0d8f5d0..024fe6cf 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -311,7 +311,7 @@ class ElementBase(tostring.ToString): return self def __copy__(self): - return self.__class__(xml=copy.copy(self.xml), parent=self.parent) + return self.__class__(xml=copy.deepcopy(self.xml), parent=self.parent) #def __del__(self): #prevents garbage collection of reference cycle # if self.parent is not None: @@ -391,5 +391,5 @@ class StanzaBase(ElementBase): self.stream.sendRaw(self.__str__()) def __copy__(self): - return self.__class__(xml=copy.copy(self.xml), stream=self.stream) + return self.__class__(xml=copy.deepcopy(self.xml), stream=self.stream) -- cgit v1.2.3 From d5e42ac0e7282500583bf17f21eb2f944600ce76 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 19 Jul 2010 13:58:53 -0400 Subject: Condensed all of the stanzaPlugin functions into a single registerStanzaPlugin function. Updated plugins and tests to use new function. --- sleekxmpp/xmlstream/stanzabase.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 024fe6cf..7592e1f6 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -19,6 +19,16 @@ else: xmltester = type(ET.Element('xml')) + +def registerStanzaPlugin(stanza, plugin): + """ + Associate a stanza object as a plugin for another stanza. + """ + tag = "{%s}%s" % (plugin.namespace, plugin.name) + stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin + stanza.plugin_tag_map[tag] = plugin + + class JID(object): def __init__(self, jid): self.jid = jid @@ -392,4 +402,4 @@ class StanzaBase(ElementBase): def __copy__(self): return self.__class__(xml=copy.deepcopy(self.xml), stream=self.stream) - + -- cgit v1.2.3 From f80b3285d49a2ca395369a98cb0f7cf1fda4e218 Mon Sep 17 00:00:00 2001 From: Nathan Fritz Date: Mon, 19 Jul 2010 14:57:21 -0700 Subject: indent problem on stanzabase --- sleekxmpp/xmlstream/stanzabase.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 7592e1f6..6508c0af 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -21,10 +21,10 @@ xmltester = type(ET.Element('xml')) def registerStanzaPlugin(stanza, plugin): - """ - Associate a stanza object as a plugin for another stanza. - """ - tag = "{%s}%s" % (plugin.namespace, plugin.name) + """ + Associate a stanza object as a plugin for another stanza. + """ + tag = "{%s}%s" % (plugin.namespace, plugin.name) stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin stanza.plugin_tag_map[tag] = plugin -- cgit v1.2.3 From fec8578cf61696d8ca85a6fe85a55be71d7109fd Mon Sep 17 00:00:00 2001 From: Nathan Fritz Date: Mon, 19 Jul 2010 15:38:48 -0700 Subject: stanza should not have setValues/getValues because that conflicts with attribute accessors --- sleekxmpp/xmlstream/stanzabase.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 6508c0af..4e6afee4 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -241,7 +241,7 @@ class ElementBase(tostring.ToString): def __eq__(self, other): if not isinstance(other, ElementBase): return False - values = self.getValues() + values = self.getStanzaValues() for key in other: if key not in values or values[key] != other[key]: return False @@ -283,21 +283,21 @@ class ElementBase(tostring.ToString): if child.tag == "{%s}%s" % (self.namespace, name): self.xml.remove(child) - def getValues(self): + def getStanzaValues(self): out = {} for interface in self.interfaces: out[interface] = self[interface] for pluginkey in self.plugins: - out[pluginkey] = self.plugins[pluginkey].getValues() + out[pluginkey] = self.plugins[pluginkey].getStanzaValues() if self.iterables: iterables = [] for stanza in self.iterables: - iterables.append(stanza.getValues()) + iterables.append(stanza.getStanzaValues()) iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) out['substanzas'] = iterables return out - def setValues(self, attrib): + def setStanzaValues(self, attrib): for interface in attrib: if interface == 'substanzas': for subdict in attrib['substanzas']: @@ -305,7 +305,7 @@ class ElementBase(tostring.ToString): for subclass in self.subitem: if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name): sub = subclass(parent=self) - sub.setValues(subdict) + sub.setStanzaValues(subdict) self.iterables.append(sub) break elif interface in self.interfaces: @@ -313,7 +313,7 @@ class ElementBase(tostring.ToString): elif interface in self.plugin_attrib_map and interface not in self.plugins: self.initPlugin(interface) if interface in self.plugins: - self.plugins[interface].setValues(attrib[interface]) + self.plugins[interface].setStanzaValues(attrib[interface]) return self def appendxml(self, xml): -- cgit v1.2.3 From 690eaf8d3c3856c6242612da22e6c6d323f193ed Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Tue, 20 Jul 2010 11:19:49 -0400 Subject: Updated license notices to use the correct MIT format. Also corrected references to nonexistant license.txt to LICENSE. --- sleekxmpp/xmlstream/stanzabase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 4e6afee4..6436fc55 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -3,7 +3,7 @@ Copyright (C) 2010 Nathanael C. Fritz This file is part of SleekXMPP. - See the file license.txt for copying permission. + See the file LICENSE for copying permission. """ from xml.etree import cElementTree as ET import logging -- cgit v1.2.3 From d70a6e6f32d5d5f9bd4d4d97f987f1667f6eab40 Mon Sep 17 00:00:00 2001 From: Joe Hildebrand Date: Tue, 20 Jul 2010 13:55:48 -0700 Subject: Issue 26. Only set from address in reply() for components --- sleekxmpp/xmlstream/stanzabase.py | 733 +++++++++++++++++++------------------- 1 file changed, 369 insertions(+), 364 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 6436fc55..66a08e49 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -13,393 +13,398 @@ import weakref import copy if sys.version_info < (3,0): - from . import tostring26 as tostring + from . import tostring26 as tostring else: - from . import tostring + from . import tostring xmltester = type(ET.Element('xml')) def registerStanzaPlugin(stanza, plugin): - """ - Associate a stanza object as a plugin for another stanza. - """ - tag = "{%s}%s" % (plugin.namespace, plugin.name) - stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin - stanza.plugin_tag_map[tag] = plugin + """ + Associate a stanza object as a plugin for another stanza. + """ + tag = "{%s}%s" % (plugin.namespace, plugin.name) + stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin + stanza.plugin_tag_map[tag] = plugin class JID(object): - def __init__(self, jid): - self.jid = jid - - def __getattr__(self, name): - if name == 'resource': - return self.jid.split('/', 1)[-1] - elif name == 'user': - if '@' in self.jid: - return self.jid.split('@', 1)[0] - else: - return '' - elif name == 'server': - return self.jid.split('@', 1)[-1].split('/', 1)[0] - elif name == 'full': - return self.jid - elif name == 'bare': - return self.jid.split('/', 1)[0] - - def __str__(self): - return self.jid + def __init__(self, jid): + self.jid = jid + + def __getattr__(self, name): + if name == 'resource': + return self.jid.split('/', 1)[-1] + elif name == 'user': + if '@' in self.jid: + return self.jid.split('@', 1)[0] + else: + return '' + elif name == 'server': + return self.jid.split('@', 1)[-1].split('/', 1)[0] + elif name == 'full': + return self.jid + elif name == 'bare': + return self.jid.split('/', 1)[0] + + def __str__(self): + return self.jid class ElementBase(tostring.ToString): - name = 'stanza' - plugin_attrib = 'plugin' - namespace = 'jabber:client' - interfaces = set(('type', 'to', 'from', 'id', 'payload')) - types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat')) - sub_interfaces = tuple() - plugin_attrib_map = {} - plugin_tag_map = {} - subitem = None + name = 'stanza' + plugin_attrib = 'plugin' + namespace = 'jabber:client' + interfaces = set(('type', 'to', 'from', 'id', 'payload')) + types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat')) + sub_interfaces = tuple() + plugin_attrib_map = {} + plugin_tag_map = {} + subitem = None - def __init__(self, xml=None, parent=None): - if parent is None: - self.parent = None - else: - self.parent = weakref.ref(parent) - self.xml = xml - self.plugins = {} - self.iterables = [] - self.idx = 0 - if not self.setup(xml): - 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: - for sub in self.subitem: - if child.tag == "{%s}%s" % (sub.namespace, sub.name): - self.iterables.append(sub(xml=child, parent=self)) - break + def __init__(self, xml=None, parent=None): + if parent is None: + self.parent = None + else: + self.parent = weakref.ref(parent) + self.xml = xml + self.plugins = {} + self.iterables = [] + self.idx = 0 + if not self.setup(xml): + 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: + for sub in self.subitem: + if child.tag == "{%s}%s" % (sub.namespace, sub.name): + self.iterables.append(sub(xml=child, parent=self)) + break - @property - def attrib(self): #backwards compatibility - return self + @property + def attrib(self): #backwards compatibility + return self - def __iter__(self): - self.idx = 0 - return self + def __iter__(self): + self.idx = 0 + return self - def __bool__(self): - return True - - def __next__(self): - self.idx += 1 - if self.idx > len(self.iterables): - self.idx = 0 - raise StopIteration - return self.iterables[self.idx - 1] - - def next(self): - return self.__next__() + def __bool__(self): + return True + + def __next__(self): + self.idx += 1 + if self.idx > len(self.iterables): + self.idx = 0 + raise StopIteration + return self.iterables[self.idx - 1] + + def next(self): + return self.__next__() - def __len__(self): - return len(self.iterables) - - def append(self, item): - if not isinstance(item, ElementBase): - if type(item) == xmltester: - return self.appendxml(item) - else: - raise TypeError - self.xml.append(item.xml) - self.iterables.append(item) - return self - - def pop(self, idx=0): - aff = self.iterables.pop(idx) - self.xml.remove(aff.xml) - return aff - - def get(self, key, defaultvalue=None): - value = self[key] - if value is None or value == '': - return defaultvalue - return value - - def keys(self): - out = [] - out += [x for x in self.interfaces] - out += [x for x in self.plugins] - if self.iterables: - out.append('substanzas') - return tuple(out) - - def match(self, matchstring): - if isinstance(matchstring, str): - nodes = matchstring.split('/') - else: - nodes = matchstring - tagargs = nodes[0].split('@') - if tagargs[0] not in (self.plugins, self.plugin_attrib): return False - founditerable = False - for iterable in self.iterables: - if nodes[1:] == []: - break - founditerable = iterable.match(nodes[1:]) - if founditerable: break; - for evals in tagargs[1:]: - x,y = evals.split('=') - if self[x] != y: return False - if not founditerable and len(nodes) > 1: - next = nodes[1].split('@')[0] - if next in self.plugins: - return self.plugins[next].match(nodes[1:]) - else: - return False - return True - - def find(self, xpath): # for backwards compatiblity, expose elementtree interface - return self.xml.find(xpath) + def __len__(self): + return len(self.iterables) + + def append(self, item): + if not isinstance(item, ElementBase): + if type(item) == xmltester: + return self.appendxml(item) + else: + raise TypeError + self.xml.append(item.xml) + self.iterables.append(item) + return self + + def pop(self, idx=0): + aff = self.iterables.pop(idx) + self.xml.remove(aff.xml) + return aff + + def get(self, key, defaultvalue=None): + value = self[key] + if value is None or value == '': + return defaultvalue + return value + + def keys(self): + out = [] + out += [x for x in self.interfaces] + out += [x for x in self.plugins] + if self.iterables: + out.append('substanzas') + return tuple(out) + + def match(self, matchstring): + if isinstance(matchstring, str): + nodes = matchstring.split('/') + else: + nodes = matchstring + tagargs = nodes[0].split('@') + if tagargs[0] not in (self.plugins, self.plugin_attrib): return False + founditerable = False + for iterable in self.iterables: + if nodes[1:] == []: + break + founditerable = iterable.match(nodes[1:]) + if founditerable: break; + for evals in tagargs[1:]: + x,y = evals.split('=') + if self[x] != y: return False + if not founditerable and len(nodes) > 1: + next = nodes[1].split('@')[0] + if next in self.plugins: + return self.plugins[next].match(nodes[1:]) + else: + return False + return True + + def find(self, xpath): # for backwards compatiblity, expose elementtree interface + return self.xml.find(xpath) - def findall(self, xpath): - return self.xml.findall(xpath) - - def setup(self, xml=None): - if self.xml is None: - self.xml = xml - if self.xml is None: - for ename in self.name.split('/'): - new = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace}) - if self.xml is None: - self.xml = new - else: - self.xml.append(new) - if self.parent is not None: - self.parent().xml.append(self.xml) - return True #had to generate XML - else: - return False + def findall(self, xpath): + return self.xml.findall(xpath) + + def setup(self, xml=None): + if self.xml is None: + self.xml = xml + if self.xml is None: + for ename in self.name.split('/'): + new = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace}) + if self.xml is None: + self.xml = new + else: + self.xml.append(new) + if self.parent is not None: + self.parent().xml.append(self.xml) + return True #had to generate XML + else: + return False - def enable(self, attrib): - self.initPlugin(attrib) - return self - - def initPlugin(self, attrib): - if attrib not in self.plugins: - self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self) - - def __getitem__(self, attrib): - if attrib == 'substanzas': - return self.iterables - elif attrib in self.interfaces: - if hasattr(self, "get%s" % attrib.title()): - return getattr(self, "get%s" % attrib.title())() - else: - if attrib in self.sub_interfaces: - return self._getSubText(attrib) - else: - return self._getAttr(attrib) - elif attrib in self.plugin_attrib_map: - if attrib not in self.plugins: self.initPlugin(attrib) - return self.plugins[attrib] - else: - return '' - - def __setitem__(self, attrib, value): - if attrib in self.interfaces: - if value is not None: - if hasattr(self, "set%s" % attrib.title()): - getattr(self, "set%s" % attrib.title())(value,) - else: - if attrib in self.sub_interfaces: - return self._setSubText(attrib, text=value) - else: - self._setAttr(attrib, value) - else: - self.__delitem__(attrib) - elif attrib in self.plugin_attrib_map: - if attrib not in self.plugins: self.initPlugin(attrib) - self.initPlugin(attrib) - self.plugins[attrib][attrib] = value - return self - - def __delitem__(self, attrib): - if attrib.lower() in self.interfaces: - if hasattr(self, "del%s" % attrib.title()): - getattr(self, "del%s" % attrib.title())() - else: - if attrib in self.sub_interfaces: - return self._delSub(attrib) - else: - self._delAttr(attrib) - elif attrib in self.plugin_attrib_map: - if attrib in self.plugins: - del self.plugins[attrib] - return self - - def __eq__(self, other): - if not isinstance(other, ElementBase): - return False - values = self.getStanzaValues() - for key in other: - if key not in values or values[key] != other[key]: - return False - return True - - def _setAttr(self, name, value): - if value is None or value == '': - self.__delitem__(name) - else: - self.xml.attrib[name] = value - - def _delAttr(self, name): - if name in self.xml.attrib: - del self.xml.attrib[name] - - def _getAttr(self, name): - return self.xml.attrib.get(name, '') - - def _getSubText(self, name): - stanza = self.xml.find("{%s}%s" % (self.namespace, name)) - if stanza is None or stanza.text is None: - return '' - else: - return stanza.text - - def _setSubText(self, name, attrib={}, text=None): - if text is None or text == '': - return self.__delitem__(name) - stanza = self.xml.find("{%s}%s" % (self.namespace, name)) - if stanza is None: - #self.xml.append(ET.Element("{%s}%s" % (self.namespace, name), attrib)) - stanza = ET.Element("{%s}%s" % (self.namespace, name)) - self.xml.append(stanza) - stanza.text = text - return stanza - - def _delSub(self, name): - for child in self.xml.getchildren(): - if child.tag == "{%s}%s" % (self.namespace, name): - self.xml.remove(child) - - def getStanzaValues(self): - out = {} - for interface in self.interfaces: - out[interface] = self[interface] - for pluginkey in self.plugins: - out[pluginkey] = self.plugins[pluginkey].getStanzaValues() - if self.iterables: - iterables = [] - for stanza in self.iterables: - iterables.append(stanza.getStanzaValues()) - iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) - out['substanzas'] = iterables - return out - - def setStanzaValues(self, attrib): - for interface in attrib: - if interface == 'substanzas': - for subdict in attrib['substanzas']: - if '__childtag__' in subdict: - for subclass in self.subitem: - if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name): - sub = subclass(parent=self) - sub.setStanzaValues(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: - self.initPlugin(interface) - if interface in self.plugins: - self.plugins[interface].setStanzaValues(attrib[interface]) - return self - - def appendxml(self, xml): - self.xml.append(xml) - return self + def enable(self, attrib): + self.initPlugin(attrib) + return self + + def initPlugin(self, attrib): + if attrib not in self.plugins: + self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self) + + def __getitem__(self, attrib): + if attrib == 'substanzas': + return self.iterables + elif attrib in self.interfaces: + if hasattr(self, "get%s" % attrib.title()): + return getattr(self, "get%s" % attrib.title())() + else: + if attrib in self.sub_interfaces: + return self._getSubText(attrib) + else: + return self._getAttr(attrib) + elif attrib in self.plugin_attrib_map: + if attrib not in self.plugins: self.initPlugin(attrib) + return self.plugins[attrib] + else: + return '' + + def __setitem__(self, attrib, value): + if attrib in self.interfaces: + if value is not None: + if hasattr(self, "set%s" % attrib.title()): + getattr(self, "set%s" % attrib.title())(value,) + else: + if attrib in self.sub_interfaces: + return self._setSubText(attrib, text=value) + else: + self._setAttr(attrib, value) + else: + self.__delitem__(attrib) + elif attrib in self.plugin_attrib_map: + if attrib not in self.plugins: self.initPlugin(attrib) + self.initPlugin(attrib) + self.plugins[attrib][attrib] = value + return self + + def __delitem__(self, attrib): + if attrib.lower() in self.interfaces: + if hasattr(self, "del%s" % attrib.title()): + getattr(self, "del%s" % attrib.title())() + else: + if attrib in self.sub_interfaces: + return self._delSub(attrib) + else: + self._delAttr(attrib) + elif attrib in self.plugin_attrib_map: + if attrib in self.plugins: + del self.plugins[attrib] + return self + + def __eq__(self, other): + if not isinstance(other, ElementBase): + return False + values = self.getStanzaValues() + for key in other: + if key not in values or values[key] != other[key]: + return False + return True + + def _setAttr(self, name, value): + if value is None or value == '': + self.__delitem__(name) + else: + self.xml.attrib[name] = value + + def _delAttr(self, name): + if name in self.xml.attrib: + del self.xml.attrib[name] + + def _getAttr(self, name): + return self.xml.attrib.get(name, '') + + def _getSubText(self, name): + stanza = self.xml.find("{%s}%s" % (self.namespace, name)) + if stanza is None or stanza.text is None: + return '' + else: + return stanza.text + + def _setSubText(self, name, attrib={}, text=None): + if text is None or text == '': + return self.__delitem__(name) + stanza = self.xml.find("{%s}%s" % (self.namespace, name)) + if stanza is None: + #self.xml.append(ET.Element("{%s}%s" % (self.namespace, name), attrib)) + stanza = ET.Element("{%s}%s" % (self.namespace, name)) + self.xml.append(stanza) + stanza.text = text + return stanza + + def _delSub(self, name): + for child in self.xml.getchildren(): + if child.tag == "{%s}%s" % (self.namespace, name): + self.xml.remove(child) + + def getStanzaValues(self): + out = {} + for interface in self.interfaces: + out[interface] = self[interface] + for pluginkey in self.plugins: + out[pluginkey] = self.plugins[pluginkey].getStanzaValues() + if self.iterables: + iterables = [] + for stanza in self.iterables: + iterables.append(stanza.getStanzaValues()) + iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) + out['substanzas'] = iterables + return out + + def setStanzaValues(self, attrib): + for interface in attrib: + if interface == 'substanzas': + for subdict in attrib['substanzas']: + if '__childtag__' in subdict: + for subclass in self.subitem: + if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name): + sub = subclass(parent=self) + sub.setStanzaValues(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: + self.initPlugin(interface) + if interface in self.plugins: + self.plugins[interface].setStanzaValues(attrib[interface]) + return self + + def appendxml(self, xml): + self.xml.append(xml) + return self - def __copy__(self): - return self.__class__(xml=copy.deepcopy(self.xml), parent=self.parent) - - #def __del__(self): #prevents garbage collection of reference cycle - # if self.parent is not None: - # self.parent.xml.remove(self.xml) + def __copy__(self): + return self.__class__(xml=copy.deepcopy(self.xml), parent=self.parent) + + #def __del__(self): #prevents garbage collection of reference cycle + # if self.parent is not None: + # self.parent.xml.remove(self.xml) class StanzaBase(ElementBase): - name = 'stanza' - namespace = 'jabber:client' - interfaces = set(('type', 'to', 'from', 'id', 'payload')) - types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat')) - sub_interfaces = tuple() + name = 'stanza' + namespace = 'jabber:client' + interfaces = set(('type', 'to', 'from', 'id', 'payload')) + types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat')) + sub_interfaces = tuple() - def __init__(self, stream=None, xml=None, stype=None, sto=None, sfrom=None, sid=None): - self.stream = stream - if stream is not None: - self.namespace = stream.default_ns - ElementBase.__init__(self, xml) - if stype is not None: - self['type'] = stype - if sto is not None: - self['to'] = sto - if sfrom is not None: - self['from'] = sfrom - self.tag = "{%s}%s" % (self.namespace, self.name) - - def setType(self, value): - if value in self.types: - self.xml.attrib['type'] = value - return self + def __init__(self, stream=None, xml=None, stype=None, sto=None, sfrom=None, sid=None): + self.stream = stream + if stream is not None: + self.namespace = stream.default_ns + ElementBase.__init__(self, xml) + if stype is not None: + self['type'] = stype + if sto is not None: + self['to'] = sto + if sfrom is not None: + self['from'] = sfrom + self.tag = "{%s}%s" % (self.namespace, self.name) + + def setType(self, value): + if value in self.types: + self.xml.attrib['type'] = value + return self - def getPayload(self): - return self.xml.getchildren() - - def setPayload(self, value): - self.xml.append(value) - return self - - def delPayload(self): - self.clear() - return self - - def clear(self): - for child in self.xml.getchildren(): - self.xml.remove(child) - for plugin in list(self.plugins.keys()): - del self.plugins[plugin] - return self - - def reply(self): - self['from'], self['to'] = self['to'], self['from'] - self.clear() - return self - - def error(self): - self['type'] = 'error' - return self - - def getTo(self): - return JID(self._getAttr('to')) - - def setTo(self, value): - return self._setAttr('to', str(value)) - - def getFrom(self): - return JID(self._getAttr('from')) - - def setFrom(self, value): - return self._setAttr('from', str(value)) - - def unhandled(self): - pass - - def exception(self, e): - logging.error(traceback.format_tb(e)) - - def send(self): - self.stream.sendRaw(self.__str__()) + def getPayload(self): + return self.xml.getchildren() + + def setPayload(self, value): + self.xml.append(value) + return self + + def delPayload(self): + self.clear() + return self + + def clear(self): + for child in self.xml.getchildren(): + self.xml.remove(child) + for plugin in list(self.plugins.keys()): + del self.plugins[plugin] + return self + + def reply(self): + # if it's a component, use from + if self.stream and hasattr(self.stream, "is_component") and self.stream.is_component: + self['from'], self['to'] = self['to'], self['from'] + else: + self['to'] = self['from'] + del self['from'] + self.clear() + return self + + def error(self): + self['type'] = 'error' + return self + + def getTo(self): + return JID(self._getAttr('to')) + + def setTo(self, value): + return self._setAttr('to', str(value)) + + def getFrom(self): + return JID(self._getAttr('from')) + + def setFrom(self, value): + return self._setAttr('from', str(value)) + + def unhandled(self): + pass + + def exception(self, e): + logging.error(traceback.format_tb(e)) + + def send(self): + self.stream.sendRaw(self.__str__()) - def __copy__(self): - return self.__class__(xml=copy.deepcopy(self.xml), stream=self.stream) + def __copy__(self): + return self.__class__(xml=copy.deepcopy(self.xml), stream=self.stream) -- cgit v1.2.3 From c8989c04f3675235e3ae730cb240e2154b5d9e76 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 26 Jul 2010 21:02:25 -0400 Subject: Replaced traceback calls to use logging.exception where applicable. --- sleekxmpp/xmlstream/stanzabase.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 66a08e49..ab054073 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -7,7 +7,6 @@ """ from xml.etree import cElementTree as ET import logging -import traceback import sys import weakref import copy @@ -400,7 +399,7 @@ class StanzaBase(ElementBase): pass def exception(self, e): - logging.error(traceback.format_tb(e)) + logging.exception('Error handling {%s}%s stanza' % (self.namespace, self.name)) def send(self): self.stream.sendRaw(self.__str__()) -- cgit v1.2.3 From a349a2a317a6ca7152e0adb21d5fabbfd632ebaf Mon Sep 17 00:00:00 2001 From: Nathan Fritz Date: Mon, 26 Jul 2010 18:13:34 -0700 Subject: removed jid from stanzabase to external file --- sleekxmpp/xmlstream/stanzabase.py | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 66a08e49..8af90a0f 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -11,6 +11,7 @@ import traceback import sys import weakref import copy +from . jid import JID if sys.version_info < (3,0): from . import tostring26 as tostring @@ -29,28 +30,6 @@ def registerStanzaPlugin(stanza, plugin): stanza.plugin_tag_map[tag] = plugin -class JID(object): - def __init__(self, jid): - self.jid = jid - - def __getattr__(self, name): - if name == 'resource': - return self.jid.split('/', 1)[-1] - elif name == 'user': - if '@' in self.jid: - return self.jid.split('@', 1)[0] - else: - return '' - elif name == 'server': - return self.jid.split('@', 1)[-1].split('/', 1)[0] - elif name == 'full': - return self.jid - elif name == 'bare': - return self.jid.split('/', 1)[0] - - def __str__(self): - return self.jid - class ElementBase(tostring.ToString): name = 'stanza' plugin_attrib = 'plugin' -- cgit v1.2.3 From d148f633f3771c43c94229bfcd2104b65396f5e1 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Thu, 29 Jul 2010 11:04:21 -0400 Subject: Modified ElementBase _getSubText, _setSubText, and _delSubText to use the namespace in a tag name if one is given and to use self.namespace otherwise. --- sleekxmpp/xmlstream/stanzabase.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index b8c80ffa..5b41a406 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -239,26 +239,31 @@ class ElementBase(tostring.ToString): return self.xml.attrib.get(name, '') def _getSubText(self, name): - stanza = self.xml.find("{%s}%s" % (self.namespace, name)) + if '}' not in name: + name = "{%s}%s" % (self.namespace, name) + stanza = self.xml.find(name) if stanza is None or stanza.text is None: return '' else: return stanza.text def _setSubText(self, name, attrib={}, text=None): + if '}' not in name: + name = "{%s}%s" % (self.namespace, name) if text is None or text == '': return self.__delitem__(name) - stanza = self.xml.find("{%s}%s" % (self.namespace, name)) + stanza = self.xml.find(name) if stanza is None: - #self.xml.append(ET.Element("{%s}%s" % (self.namespace, name), attrib)) - stanza = ET.Element("{%s}%s" % (self.namespace, name)) + stanza = ET.Element(name) self.xml.append(stanza) stanza.text = text return stanza def _delSub(self, name): + if '}' not in name: + name = "{%s}%s" % (self.namespace, name) for child in self.xml.getchildren(): - if child.tag == "{%s}%s" % (self.namespace, name): + if child.tag == name: self.xml.remove(child) def getStanzaValues(self): -- cgit v1.2.3 From 1cedea280499c0b7f7debb6c95442038d8f2d89c Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 30 Jul 2010 14:11:24 -0400 Subject: Added optional default value to _getAttr. --- sleekxmpp/xmlstream/stanzabase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 5b41a406..94ff958c 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -235,8 +235,8 @@ class ElementBase(tostring.ToString): if name in self.xml.attrib: del self.xml.attrib[name] - def _getAttr(self, name): - return self.xml.attrib.get(name, '') + def _getAttr(self, name, default=''): + return self.xml.attrib.get(name, default) def _getSubText(self, name): if '}' not in name: -- cgit v1.2.3 From e077204a16c76df4af90ba067e94c31af3d9e372 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Thu, 5 Aug 2010 20:26:41 -0400 Subject: Replaced the ToString class with a tostring function. The sleekxmpp.xmlstream.tostring and sleekxmpp.xmlstream.tostring26 packages have been merged to sleekxmpp.xmlstream.tostring. The __init__.py file will import the appropriate tostring function depending on the Python version. The setup.py file has been updated with the package changes. ElementBase is now a direct descendent of object and does not subclass ToString. Stanza objects now return their XML contents for __repr__. --- sleekxmpp/xmlstream/stanzabase.py | 91 +++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 43 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 94ff958c..3b5f0bf4 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -12,10 +12,7 @@ import weakref import copy from . jid import JID -if sys.version_info < (3,0): - from . import tostring26 as tostring -else: - from . import tostring +from sleekxmpp.xmlstream.tostring import tostring xmltester = type(ET.Element('xml')) @@ -29,7 +26,7 @@ def registerStanzaPlugin(stanza, plugin): stanza.plugin_tag_map[tag] = plugin -class ElementBase(tostring.ToString): +class ElementBase(object): name = 'stanza' plugin_attrib = 'plugin' namespace = 'jabber:client' @@ -70,20 +67,20 @@ class ElementBase(tostring.ToString): def __bool__(self): return True - + def __next__(self): self.idx += 1 if self.idx > len(self.iterables): self.idx = 0 raise StopIteration return self.iterables[self.idx - 1] - + def next(self): return self.__next__() def __len__(self): return len(self.iterables) - + def append(self, item): if not isinstance(item, ElementBase): if type(item) == xmltester: @@ -93,18 +90,18 @@ class ElementBase(tostring.ToString): self.xml.append(item.xml) self.iterables.append(item) return self - + def pop(self, idx=0): aff = self.iterables.pop(idx) self.xml.remove(aff.xml) return aff - + def get(self, key, defaultvalue=None): value = self[key] if value is None or value == '': return defaultvalue return value - + def keys(self): out = [] out += [x for x in self.interfaces] @@ -112,7 +109,7 @@ class ElementBase(tostring.ToString): if self.iterables: out.append('substanzas') return tuple(out) - + def match(self, matchstring): if isinstance(matchstring, str): nodes = matchstring.split('/') @@ -136,13 +133,13 @@ class ElementBase(tostring.ToString): else: return False return True - + def find(self, xpath): # for backwards compatiblity, expose elementtree interface return self.xml.find(xpath) def findall(self, xpath): return self.xml.findall(xpath) - + def setup(self, xml=None): if self.xml is None: self.xml = xml @@ -162,11 +159,11 @@ class ElementBase(tostring.ToString): def enable(self, attrib): self.initPlugin(attrib) return self - + def initPlugin(self, attrib): if attrib not in self.plugins: self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self) - + def __getitem__(self, attrib): if attrib == 'substanzas': return self.iterables @@ -183,7 +180,7 @@ class ElementBase(tostring.ToString): return self.plugins[attrib] else: return '' - + def __setitem__(self, attrib, value): if attrib in self.interfaces: if value is not None: @@ -201,7 +198,7 @@ class ElementBase(tostring.ToString): self.initPlugin(attrib) self.plugins[attrib][attrib] = value return self - + def __delitem__(self, attrib): if attrib.lower() in self.interfaces: if hasattr(self, "del%s" % attrib.title()): @@ -215,7 +212,7 @@ class ElementBase(tostring.ToString): if attrib in self.plugins: del self.plugins[attrib] return self - + def __eq__(self, other): if not isinstance(other, ElementBase): return False @@ -224,20 +221,20 @@ class ElementBase(tostring.ToString): if key not in values or values[key] != other[key]: return False return True - + def _setAttr(self, name, value): if value is None or value == '': self.__delitem__(name) else: self.xml.attrib[name] = value - + def _delAttr(self, name): if name in self.xml.attrib: del self.xml.attrib[name] - + def _getAttr(self, name, default=''): return self.xml.attrib.get(name, default) - + def _getSubText(self, name): if '}' not in name: name = "{%s}%s" % (self.namespace, name) @@ -246,7 +243,7 @@ class ElementBase(tostring.ToString): return '' else: return stanza.text - + def _setSubText(self, name, attrib={}, text=None): if '}' not in name: name = "{%s}%s" % (self.namespace, name) @@ -258,14 +255,14 @@ class ElementBase(tostring.ToString): self.xml.append(stanza) stanza.text = text return stanza - + def _delSub(self, name): if '}' not in name: name = "{%s}%s" % (self.namespace, name) for child in self.xml.getchildren(): if child.tag == name: self.xml.remove(child) - + def getStanzaValues(self): out = {} for interface in self.interfaces: @@ -279,7 +276,7 @@ class ElementBase(tostring.ToString): iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) out['substanzas'] = iterables return out - + def setStanzaValues(self, attrib): for interface in attrib: if interface == 'substanzas': @@ -298,14 +295,20 @@ class ElementBase(tostring.ToString): if interface in self.plugins: self.plugins[interface].setStanzaValues(attrib[interface]) return self - + def appendxml(self, xml): self.xml.append(xml) return self def __copy__(self): return self.__class__(xml=copy.deepcopy(self.xml), parent=self.parent) - + + def __str__(self): + return tostring(self.xml, xmlns='', stanza_ns=self.namespace) + + def __repr__(self): + return self.__str__() + #def __del__(self): #prevents garbage collection of reference cycle # if self.parent is not None: # self.parent.xml.remove(self.xml) @@ -329,7 +332,7 @@ class StanzaBase(ElementBase): if sfrom is not None: self['from'] = sfrom self.tag = "{%s}%s" % (self.namespace, self.name) - + def setType(self, value): if value in self.types: self.xml.attrib['type'] = value @@ -337,22 +340,22 @@ class StanzaBase(ElementBase): def getPayload(self): return self.xml.getchildren() - + def setPayload(self, value): self.xml.append(value) return self - + def delPayload(self): self.clear() return self - + def clear(self): for child in self.xml.getchildren(): self.xml.remove(child) for plugin in list(self.plugins.keys()): del self.plugins[plugin] return self - + def reply(self): # if it's a component, use from if self.stream and hasattr(self.stream, "is_component") and self.stream.is_component: @@ -362,32 +365,34 @@ class StanzaBase(ElementBase): del self['from'] self.clear() return self - + def error(self): self['type'] = 'error' return self - + def getTo(self): return JID(self._getAttr('to')) - + def setTo(self, value): return self._setAttr('to', str(value)) - + def getFrom(self): return JID(self._getAttr('from')) - + def setFrom(self, value): return self._setAttr('from', str(value)) - + def unhandled(self): pass - + def exception(self, e): logging.exception('Error handling {%s}%s stanza' % (self.namespace, self.name)) - + def send(self): self.stream.sendRaw(self.__str__()) def __copy__(self): return self.__class__(xml=copy.deepcopy(self.xml), stream=self.stream) - + + def __str__(self): + return tostring(self.xml, xmlns='', stanza_ns=self.namespace, stream=self.stream) -- cgit v1.2.3 From 4b52007e8c39566bb2083a2e4041de4b294c4948 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Thu, 12 Aug 2010 23:24:09 -0400 Subject: Cleaned stanzabase imports. --- sleekxmpp/xmlstream/stanzabase.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 3b5f0bf4..687fc4f7 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -5,13 +5,14 @@ See the file LICENSE for copying permission. """ -from xml.etree import cElementTree as ET + +import copy import logging import sys import weakref -import copy -from . jid import JID +from xml.etree import cElementTree as ET +from sleekxmpp.xmlstream import JID from sleekxmpp.xmlstream.tostring import tostring xmltester = type(ET.Element('xml')) -- cgit v1.2.3 From b0fb205c165311b3b66d36b87a2632dcd70d018a Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 10:12:51 -0400 Subject: Updated registerStanzaPlugin and the XML test type. --- sleekxmpp/xmlstream/stanzabase.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 687fc4f7..feadbd47 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -15,16 +15,22 @@ from xml.etree import cElementTree as ET from sleekxmpp.xmlstream import JID from sleekxmpp.xmlstream.tostring import tostring -xmltester = type(ET.Element('xml')) + +# Used to check if an argument is an XML object. +XML_TYPE = type(ET.Element('xml')) def registerStanzaPlugin(stanza, plugin): - """ - Associate a stanza object as a plugin for another stanza. - """ - tag = "{%s}%s" % (plugin.namespace, plugin.name) - stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin - stanza.plugin_tag_map[tag] = plugin + """ + Associate a stanza object as a plugin for another stanza. + + Arguments: + stanza -- The class of the parent stanza. + plugin -- The class of the plugin stanza. + """ + tag = "{%s}%s" % (plugin.namespace, plugin.name) + stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin + stanza.plugin_tag_map[tag] = plugin class ElementBase(object): @@ -84,7 +90,7 @@ class ElementBase(object): def append(self, item): if not isinstance(item, ElementBase): - if type(item) == xmltester: + if type(item) == XML_TYPE: return self.appendxml(item) else: raise TypeError -- cgit v1.2.3 From 747001d33c87dbd644b369f9e41da9ba16927561 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 10:15:52 -0400 Subject: Adjust first level indenting in ElementBase to prepare for cleanup. --- sleekxmpp/xmlstream/stanzabase.py | 570 +++++++++++++++++++------------------- 1 file changed, 285 insertions(+), 285 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index feadbd47..a6425b80 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -34,291 +34,291 @@ def registerStanzaPlugin(stanza, plugin): class ElementBase(object): - name = 'stanza' - plugin_attrib = 'plugin' - namespace = 'jabber:client' - interfaces = set(('type', 'to', 'from', 'id', 'payload')) - types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat')) - sub_interfaces = tuple() - plugin_attrib_map = {} - plugin_tag_map = {} - subitem = None - - def __init__(self, xml=None, parent=None): - if parent is None: - self.parent = None - else: - self.parent = weakref.ref(parent) - self.xml = xml - self.plugins = {} - self.iterables = [] - self.idx = 0 - if not self.setup(xml): - 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: - for sub in self.subitem: - if child.tag == "{%s}%s" % (sub.namespace, sub.name): - self.iterables.append(sub(xml=child, parent=self)) - break - - - @property - def attrib(self): #backwards compatibility - return self - - def __iter__(self): - self.idx = 0 - return self - - def __bool__(self): - return True - - def __next__(self): - self.idx += 1 - if self.idx > len(self.iterables): - self.idx = 0 - raise StopIteration - return self.iterables[self.idx - 1] - - def next(self): - return self.__next__() - - def __len__(self): - return len(self.iterables) - - def append(self, item): - if not isinstance(item, ElementBase): - if type(item) == XML_TYPE: - return self.appendxml(item) - else: - raise TypeError - self.xml.append(item.xml) - self.iterables.append(item) - return self - - def pop(self, idx=0): - aff = self.iterables.pop(idx) - self.xml.remove(aff.xml) - return aff - - def get(self, key, defaultvalue=None): - value = self[key] - if value is None or value == '': - return defaultvalue - return value - - def keys(self): - out = [] - out += [x for x in self.interfaces] - out += [x for x in self.plugins] - if self.iterables: - out.append('substanzas') - return tuple(out) - - def match(self, matchstring): - if isinstance(matchstring, str): - nodes = matchstring.split('/') - else: - nodes = matchstring - tagargs = nodes[0].split('@') - if tagargs[0] not in (self.plugins, self.plugin_attrib): return False - founditerable = False - for iterable in self.iterables: - if nodes[1:] == []: - break - founditerable = iterable.match(nodes[1:]) - if founditerable: break; - for evals in tagargs[1:]: - x,y = evals.split('=') - if self[x] != y: return False - if not founditerable and len(nodes) > 1: - next = nodes[1].split('@')[0] - if next in self.plugins: - return self.plugins[next].match(nodes[1:]) - else: - return False - return True - - def find(self, xpath): # for backwards compatiblity, expose elementtree interface - return self.xml.find(xpath) - - def findall(self, xpath): - return self.xml.findall(xpath) - - def setup(self, xml=None): - if self.xml is None: - self.xml = xml - if self.xml is None: - for ename in self.name.split('/'): - new = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace}) - if self.xml is None: - self.xml = new - else: - self.xml.append(new) - if self.parent is not None: - self.parent().xml.append(self.xml) - return True #had to generate XML - else: - return False - - def enable(self, attrib): - self.initPlugin(attrib) - return self - - def initPlugin(self, attrib): - if attrib not in self.plugins: - self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self) - - def __getitem__(self, attrib): - if attrib == 'substanzas': - return self.iterables - elif attrib in self.interfaces: - if hasattr(self, "get%s" % attrib.title()): - return getattr(self, "get%s" % attrib.title())() - else: - if attrib in self.sub_interfaces: - return self._getSubText(attrib) - else: - return self._getAttr(attrib) - elif attrib in self.plugin_attrib_map: - if attrib not in self.plugins: self.initPlugin(attrib) - return self.plugins[attrib] - else: - return '' - - def __setitem__(self, attrib, value): - if attrib in self.interfaces: - if value is not None: - if hasattr(self, "set%s" % attrib.title()): - getattr(self, "set%s" % attrib.title())(value,) - else: - if attrib in self.sub_interfaces: - return self._setSubText(attrib, text=value) - else: - self._setAttr(attrib, value) - else: - self.__delitem__(attrib) - elif attrib in self.plugin_attrib_map: - if attrib not in self.plugins: self.initPlugin(attrib) - self.initPlugin(attrib) - self.plugins[attrib][attrib] = value - return self - - def __delitem__(self, attrib): - if attrib.lower() in self.interfaces: - if hasattr(self, "del%s" % attrib.title()): - getattr(self, "del%s" % attrib.title())() - else: - if attrib in self.sub_interfaces: - return self._delSub(attrib) - else: - self._delAttr(attrib) - elif attrib in self.plugin_attrib_map: - if attrib in self.plugins: - del self.plugins[attrib] - return self - - def __eq__(self, other): - if not isinstance(other, ElementBase): - return False - values = self.getStanzaValues() - for key in other: - if key not in values or values[key] != other[key]: - return False - return True - - def _setAttr(self, name, value): - if value is None or value == '': - self.__delitem__(name) - else: - self.xml.attrib[name] = value - - def _delAttr(self, name): - if name in self.xml.attrib: - del self.xml.attrib[name] - - def _getAttr(self, name, default=''): - return self.xml.attrib.get(name, default) - - def _getSubText(self, name): - if '}' not in name: - name = "{%s}%s" % (self.namespace, name) - stanza = self.xml.find(name) - if stanza is None or stanza.text is None: - return '' - else: - return stanza.text - - def _setSubText(self, name, attrib={}, text=None): - if '}' not in name: - name = "{%s}%s" % (self.namespace, name) - if text is None or text == '': - return self.__delitem__(name) - stanza = self.xml.find(name) - if stanza is None: - stanza = ET.Element(name) - self.xml.append(stanza) - stanza.text = text - return stanza - - def _delSub(self, name): - if '}' not in name: - name = "{%s}%s" % (self.namespace, name) - for child in self.xml.getchildren(): - if child.tag == name: - self.xml.remove(child) - - def getStanzaValues(self): - out = {} - for interface in self.interfaces: - out[interface] = self[interface] - for pluginkey in self.plugins: - out[pluginkey] = self.plugins[pluginkey].getStanzaValues() - if self.iterables: - iterables = [] - for stanza in self.iterables: - iterables.append(stanza.getStanzaValues()) - iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) - out['substanzas'] = iterables - return out - - def setStanzaValues(self, attrib): - for interface in attrib: - if interface == 'substanzas': - for subdict in attrib['substanzas']: - if '__childtag__' in subdict: - for subclass in self.subitem: - if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name): - sub = subclass(parent=self) - sub.setStanzaValues(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: - self.initPlugin(interface) - if interface in self.plugins: - self.plugins[interface].setStanzaValues(attrib[interface]) - return self - - def appendxml(self, xml): - self.xml.append(xml) - return self - - def __copy__(self): - return self.__class__(xml=copy.deepcopy(self.xml), parent=self.parent) - - def __str__(self): - return tostring(self.xml, xmlns='', stanza_ns=self.namespace) - - def __repr__(self): - return self.__str__() - - #def __del__(self): #prevents garbage collection of reference cycle - # if self.parent is not None: - # self.parent.xml.remove(self.xml) + name = 'stanza' + plugin_attrib = 'plugin' + namespace = 'jabber:client' + interfaces = set(('type', 'to', 'from', 'id', 'payload')) + types = set(('get', 'set', 'error', None, 'unavailable', 'normal', 'chat')) + sub_interfaces = tuple() + plugin_attrib_map = {} + plugin_tag_map = {} + subitem = None + + def __init__(self, xml=None, parent=None): + if parent is None: + self.parent = None + else: + self.parent = weakref.ref(parent) + self.xml = xml + self.plugins = {} + self.iterables = [] + self.idx = 0 + if not self.setup(xml): + 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: + for sub in self.subitem: + if child.tag == "{%s}%s" % (sub.namespace, sub.name): + self.iterables.append(sub(xml=child, parent=self)) + break + + + @property + def attrib(self): #backwards compatibility + return self + + def __iter__(self): + self.idx = 0 + return self + + def __bool__(self): + return True + + def __next__(self): + self.idx += 1 + if self.idx > len(self.iterables): + self.idx = 0 + raise StopIteration + return self.iterables[self.idx - 1] + + def next(self): + return self.__next__() + + def __len__(self): + return len(self.iterables) + + def append(self, item): + if not isinstance(item, ElementBase): + if type(item) == XML_TYPE: + return self.appendxml(item) + else: + raise TypeError + self.xml.append(item.xml) + self.iterables.append(item) + return self + + def pop(self, idx=0): + aff = self.iterables.pop(idx) + self.xml.remove(aff.xml) + return aff + + def get(self, key, defaultvalue=None): + value = self[key] + if value is None or value == '': + return defaultvalue + return value + + def keys(self): + out = [] + out += [x for x in self.interfaces] + out += [x for x in self.plugins] + if self.iterables: + out.append('substanzas') + return tuple(out) + + def match(self, matchstring): + if isinstance(matchstring, str): + nodes = matchstring.split('/') + else: + nodes = matchstring + tagargs = nodes[0].split('@') + if tagargs[0] not in (self.plugins, self.plugin_attrib): return False + founditerable = False + for iterable in self.iterables: + if nodes[1:] == []: + break + founditerable = iterable.match(nodes[1:]) + if founditerable: break; + for evals in tagargs[1:]: + x,y = evals.split('=') + if self[x] != y: return False + if not founditerable and len(nodes) > 1: + next = nodes[1].split('@')[0] + if next in self.plugins: + return self.plugins[next].match(nodes[1:]) + else: + return False + return True + + def find(self, xpath): # for backwards compatiblity, expose elementtree interface + return self.xml.find(xpath) + + def findall(self, xpath): + return self.xml.findall(xpath) + + def setup(self, xml=None): + if self.xml is None: + self.xml = xml + if self.xml is None: + for ename in self.name.split('/'): + new = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace}) + if self.xml is None: + self.xml = new + else: + self.xml.append(new) + if self.parent is not None: + self.parent().xml.append(self.xml) + return True #had to generate XML + else: + return False + + def enable(self, attrib): + self.initPlugin(attrib) + return self + + def initPlugin(self, attrib): + if attrib not in self.plugins: + self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self) + + def __getitem__(self, attrib): + if attrib == 'substanzas': + return self.iterables + elif attrib in self.interfaces: + if hasattr(self, "get%s" % attrib.title()): + return getattr(self, "get%s" % attrib.title())() + else: + if attrib in self.sub_interfaces: + return self._getSubText(attrib) + else: + return self._getAttr(attrib) + elif attrib in self.plugin_attrib_map: + if attrib not in self.plugins: self.initPlugin(attrib) + return self.plugins[attrib] + else: + return '' + + def __setitem__(self, attrib, value): + if attrib in self.interfaces: + if value is not None: + if hasattr(self, "set%s" % attrib.title()): + getattr(self, "set%s" % attrib.title())(value,) + else: + if attrib in self.sub_interfaces: + return self._setSubText(attrib, text=value) + else: + self._setAttr(attrib, value) + else: + self.__delitem__(attrib) + elif attrib in self.plugin_attrib_map: + if attrib not in self.plugins: self.initPlugin(attrib) + self.initPlugin(attrib) + self.plugins[attrib][attrib] = value + return self + + def __delitem__(self, attrib): + if attrib.lower() in self.interfaces: + if hasattr(self, "del%s" % attrib.title()): + getattr(self, "del%s" % attrib.title())() + else: + if attrib in self.sub_interfaces: + return self._delSub(attrib) + else: + self._delAttr(attrib) + elif attrib in self.plugin_attrib_map: + if attrib in self.plugins: + del self.plugins[attrib] + return self + + def __eq__(self, other): + if not isinstance(other, ElementBase): + return False + values = self.getStanzaValues() + for key in other: + if key not in values or values[key] != other[key]: + return False + return True + + def _setAttr(self, name, value): + if value is None or value == '': + self.__delitem__(name) + else: + self.xml.attrib[name] = value + + def _delAttr(self, name): + if name in self.xml.attrib: + del self.xml.attrib[name] + + def _getAttr(self, name, default=''): + return self.xml.attrib.get(name, default) + + def _getSubText(self, name): + if '}' not in name: + name = "{%s}%s" % (self.namespace, name) + stanza = self.xml.find(name) + if stanza is None or stanza.text is None: + return '' + else: + return stanza.text + + def _setSubText(self, name, attrib={}, text=None): + if '}' not in name: + name = "{%s}%s" % (self.namespace, name) + if text is None or text == '': + return self.__delitem__(name) + stanza = self.xml.find(name) + if stanza is None: + stanza = ET.Element(name) + self.xml.append(stanza) + stanza.text = text + return stanza + + def _delSub(self, name): + if '}' not in name: + name = "{%s}%s" % (self.namespace, name) + for child in self.xml.getchildren(): + if child.tag == name: + self.xml.remove(child) + + def getStanzaValues(self): + out = {} + for interface in self.interfaces: + out[interface] = self[interface] + for pluginkey in self.plugins: + out[pluginkey] = self.plugins[pluginkey].getStanzaValues() + if self.iterables: + iterables = [] + for stanza in self.iterables: + iterables.append(stanza.getStanzaValues()) + iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) + out['substanzas'] = iterables + return out + + def setStanzaValues(self, attrib): + for interface in attrib: + if interface == 'substanzas': + for subdict in attrib['substanzas']: + if '__childtag__' in subdict: + for subclass in self.subitem: + if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name): + sub = subclass(parent=self) + sub.setStanzaValues(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: + self.initPlugin(interface) + if interface in self.plugins: + self.plugins[interface].setStanzaValues(attrib[interface]) + return self + + def appendxml(self, xml): + self.xml.append(xml) + return self + + def __copy__(self): + return self.__class__(xml=copy.deepcopy(self.xml), parent=self.parent) + + def __str__(self): + return tostring(self.xml, xmlns='', stanza_ns=self.namespace) + + def __repr__(self): + return self.__str__() + +#def __del__(self): #prevents garbage collection of reference cycle +# if self.parent is not None: +# self.parent.xml.remove(self.xml) class StanzaBase(ElementBase): name = 'stanza' -- cgit v1.2.3 From 415520200efbc6f8a93d1e667f2b7d43b7994667 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 10:26:33 -0400 Subject: Updated ElementBase.__init__ --- sleekxmpp/xmlstream/stanzabase.py | 48 ++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index a6425b80..6762792f 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -45,24 +45,36 @@ class ElementBase(object): subitem = None def __init__(self, xml=None, parent=None): - if parent is None: - self.parent = None - else: - self.parent = weakref.ref(parent) - self.xml = xml - self.plugins = {} - self.iterables = [] - self.idx = 0 - if not self.setup(xml): - 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: - for sub in self.subitem: - if child.tag == "{%s}%s" % (sub.namespace, sub.name): - self.iterables.append(sub(xml=child, parent=self)) - break - + """ + Create a new stanza object. + + Arguments: + xml -- Initialize the stanza with optional existing XML. + parent -- Optional stanza object that contains this stanza. + """ + self.xml = xml + self.plugins = {} + self.iterables = [] + self.idx = 0 + if parent is None: + self.parent = None + else: + self.parent = weakref.ref(parent) + + if self.setup(xml): + # If we generated our own XML, then everything is ready. + return + + # Initialize values using provided XML + for child in self.xml.getchildren(): + if child.tag in self.plugin_tag_map: + plugin = self.plugin_tag_map[child.tag] + self.plugins[plugin.plugin_attrib] = plugin(child, 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(child, self)) + break @property def attrib(self): #backwards compatibility -- cgit v1.2.3 From c20fab0f6c28bcbfbe54db687be056a9b5088ad4 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 12:24:47 -0400 Subject: Updated ElementBase.setup, and added unit tests. --- sleekxmpp/xmlstream/stanzabase.py | 48 ++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 6762792f..b11d59ee 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -76,6 +76,38 @@ class ElementBase(object): self.iterables.append(sub(child, self)) break + def setup(self, xml=None): + """ + Initialize the stanza's XML contents. + + Will return True if XML was generated according to the stanza's + definition. + + Arguments: + xml -- Optional XML object to use for the stanza's content + instead of generating XML. + """ + if self.xml is None: + self.xml = xml + + if self.xml is None: + # Generate XML from the stanza definition + for ename in self.name.split('/'): + new = ET.Element("{%s}%s" % (self.namespace, ename)) + if self.xml is None: + self.xml = new + else: + last_xml.append(new) + last_xml = new + if self.parent is not None: + self.parent().xml.append(self.xml) + + # We had to generate XML + return True + else: + # We did not generate XML + return False + @property def attrib(self): #backwards compatibility return self @@ -159,22 +191,6 @@ class ElementBase(object): def findall(self, xpath): return self.xml.findall(xpath) - def setup(self, xml=None): - if self.xml is None: - self.xml = xml - if self.xml is None: - for ename in self.name.split('/'): - new = ET.Element("{%(namespace)s}%(name)s" % {'name': self.name, 'namespace': self.namespace}) - if self.xml is None: - self.xml = new - else: - self.xml.append(new) - if self.parent is not None: - self.parent().xml.append(self.xml) - return True #had to generate XML - else: - return False - def enable(self, attrib): self.initPlugin(attrib) return self -- cgit v1.2.3 From b580a3138d46933331cd9829c7dcb3f4135a194f Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 12:51:07 -0400 Subject: Updated ElementBase.enable and ElementBase.initPlugin --- sleekxmpp/xmlstream/stanzabase.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index b11d59ee..aba63331 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -108,6 +108,29 @@ class ElementBase(object): # We did not generate XML return False + def enable(self, attrib): + """ + Enable and initialize a stanza plugin. + + Alias for initPlugin. + + Arguments: + attrib -- The stanza interface for the plugin. + """ + return self.initPlugin(attrib) + + def initPlugin(self, attrib): + """ + Enable and initialize a stanza plugin. + + Arguments: + attrib -- The stanza interface for the plugin. + """ + if attrib not in self.plugins: + plugin_class = self.plugin_attrib_map[attrib] + self.plugins[attrib] = plugin_class(parent=self) + return self + @property def attrib(self): #backwards compatibility return self @@ -191,14 +214,6 @@ class ElementBase(object): def findall(self, xpath): return self.xml.findall(xpath) - def enable(self, attrib): - self.initPlugin(attrib) - return self - - def initPlugin(self, attrib): - if attrib not in self.plugins: - self.plugins[attrib] = self.plugin_attrib_map[attrib](parent=self) - def __getitem__(self, attrib): if attrib == 'substanzas': return self.iterables -- cgit v1.2.3 From fe49b8c377b8491ec5fd5bc74d44834bd384f6a8 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 20:05:24 -0400 Subject: Updated getStanzaValues and setStanzaValues with docs and unit tests. --- sleekxmpp/xmlstream/stanzabase.py | 85 ++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 33 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index aba63331..3e280d61 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -131,6 +131,58 @@ class ElementBase(object): self.plugins[attrib] = plugin_class(parent=self) return self + def getStanzaValues(self): + """ + Return a dictionary of the stanza's interface values. + + Stanza plugin values are included as nested dictionaries. + """ + values = {} + for interface in self.interfaces: + values[interface] = self[interface] + for plugin, stanza in self.plugins.items(): + values[plugin] = stanza.getStanzaValues() + if self.iterables: + iterables = [] + for stanza in self.iterables: + iterables.append(stanza.getStanzaValues()) + iterables[-1].update({ + '__childtag__': "{%s}%s" % (stanza.namespace, stanza.name) + }) + values['substanzas'] = iterables + return values + + def setStanzaValues(self, values): + """ + Set multiple stanza interface values using a dictionary. + + Stanza plugin values may be set using nested dictionaries. + + Arguments: + values -- A dictionary mapping stanza interface with values. + Plugin interfaces may accept a nested dictionary that + will be used recursively. + """ + for interface, value in values.items(): + if interface == 'substanzas': + for subdict in value: + if '__childtag__' in subdict: + for subclass in self.subitem: + child_tag = "{%s}%s" % (subclass.namespace, + subclass.name) + if subdict['__childtag__'] == child_tag: + sub = subclass(parent=self) + sub.setStanzaValues(subdict) + self.iterables.append(sub) + break + elif interface in self.interfaces: + self[interface] = value + elif interface in self.plugin_attrib_map: + if interface not in self.plugins: + self.initPlugin(interface) + self.plugins[interface].setStanzaValues(value) + return self + @property def attrib(self): #backwards compatibility return self @@ -313,39 +365,6 @@ class ElementBase(object): if child.tag == name: self.xml.remove(child) - def getStanzaValues(self): - out = {} - for interface in self.interfaces: - out[interface] = self[interface] - for pluginkey in self.plugins: - out[pluginkey] = self.plugins[pluginkey].getStanzaValues() - if self.iterables: - iterables = [] - for stanza in self.iterables: - iterables.append(stanza.getStanzaValues()) - iterables[-1].update({'__childtag__': "{%s}%s" % (stanza.namespace, stanza.name)}) - out['substanzas'] = iterables - return out - - def setStanzaValues(self, attrib): - for interface in attrib: - if interface == 'substanzas': - for subdict in attrib['substanzas']: - if '__childtag__' in subdict: - for subclass in self.subitem: - if subdict['__childtag__'] == "{%s}%s" % (subclass.namespace, subclass.name): - sub = subclass(parent=self) - sub.setStanzaValues(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: - self.initPlugin(interface) - if interface in self.plugins: - self.plugins[interface].setStanzaValues(attrib[interface]) - return self - def appendxml(self, xml): self.xml.append(xml) return self -- cgit v1.2.3 From 2f6f4fc16d81fd01bc5a4569e0a1bc4ede4a3af8 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Fri, 13 Aug 2010 21:33:11 -0400 Subject: Updated ElementBase.__getitem__ with docs and unit tests. --- sleekxmpp/xmlstream/stanzabase.py | 59 ++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 3e280d61..962cf8ed 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -183,6 +183,48 @@ class ElementBase(object): self.plugins[interface].setStanzaValues(value) return self + def __getitem__(self, attrib): + """ + Return the value of a stanza interface using dictionary-like syntax. + + Example: + >>> msg['body'] + 'Message contents' + + Stanza interfaces are typically mapped directly to the underlying XML + object, but can be overridden by the presence of a getAttrib method + (or getFoo where the interface is named foo, etc). + + The search order for interface value retrieval for an interface + named 'foo' is: + 1. The list of substanzas. + 2. The result of calling getFoo. + 3. The contents of the foo subelement, if foo is a sub interface. + 4. The value of the foo attribute of the XML object. + 5. The plugin named 'foo' + 6. An empty string. + + Arguments: + attrib -- The name of the requested stanza interface. + """ + if attrib == 'substanzas': + return self.iterables + elif attrib in self.interfaces: + get_method = "get%s" % attrib.title() + if hasattr(self, get_method): + return getattr(self, get_method)() + else: + if attrib in self.sub_interfaces: + return self._getSubText(attrib) + else: + return self._getAttr(attrib) + elif attrib in self.plugin_attrib_map: + if attrib not in self.plugins: + self.initPlugin(attrib) + return self.plugins[attrib] + else: + return '' + @property def attrib(self): #backwards compatibility return self @@ -266,23 +308,6 @@ class ElementBase(object): def findall(self, xpath): return self.xml.findall(xpath) - def __getitem__(self, attrib): - if attrib == 'substanzas': - return self.iterables - elif attrib in self.interfaces: - if hasattr(self, "get%s" % attrib.title()): - return getattr(self, "get%s" % attrib.title())() - else: - if attrib in self.sub_interfaces: - return self._getSubText(attrib) - else: - return self._getAttr(attrib) - elif attrib in self.plugin_attrib_map: - if attrib not in self.plugins: self.initPlugin(attrib) - return self.plugins[attrib] - else: - return '' - def __setitem__(self, attrib, value): if attrib in self.interfaces: if value is not None: -- cgit v1.2.3 From e4240dd593207a5912de996c42451b3946f113b2 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Thu, 19 Aug 2010 14:21:58 -0400 Subject: Updated ElementBase.__setitem__ and added unit tests. --- sleekxmpp/xmlstream/stanzabase.py | 62 +++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 18 deletions(-) (limited to 'sleekxmpp/xmlstream/stanzabase.py') diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 962cf8ed..83a8ddfc 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -225,6 +225,50 @@ class ElementBase(object): else: return '' + def __setitem__(self, attrib, value): + """ + Set the value of a stanza interface using dictionary-like syntax. + + Example: + >>> msg['body'] = "Hi!" + >>> msg['body'] + 'Hi!' + + Stanza interfaces are typically mapped directly to the underlying XML + object, but can be overridden by the presence of a setAttrib method + (or setFoo where the interface is named foo, etc). + + The effect of interface value assignment for an interface + named 'foo' will be one of: + 1. Delete the interface's contents if the value is None. + 2. Call setFoo, if it exists. + 3. Set the text of a foo element, if foo is in sub_interfaces. + 4. Set the value of a top level XML attribute name foo. + 5. Attempt to pass value to a plugin named foo using the plugin's + foo interface. + 6. Do nothing. + + Arguments: + attrib -- The name of the stanza interface to modify. + value -- The new value of the stanza interface. + """ + if attrib in self.interfaces: + if value is not None: + if hasattr(self, "set%s" % attrib.title()): + getattr(self, "set%s" % attrib.title())(value,) + else: + if attrib in self.sub_interfaces: + return self._setSubText(attrib, text=value) + else: + self._setAttr(attrib, value) + else: + self.__delitem__(attrib) + elif attrib in self.plugin_attrib_map: + if attrib not in self.plugins: + self.initPlugin(attrib) + self.plugins[attrib][attrib] = value + return self + @property def attrib(self): #backwards compatibility return self @@ -308,24 +352,6 @@ class ElementBase(object): def findall(self, xpath): return self.xml.findall(xpath) - def __setitem__(self, attrib, value): - if attrib in self.interfaces: - if value is not None: - if hasattr(self, "set%s" % attrib.title()): - getattr(self, "set%s" % attrib.title())(value,) - else: - if attrib in self.sub_interfaces: - return self._setSubText(attrib, text=value) - else: - self._setAttr(attrib, value) - else: - self.__delitem__(attrib) - elif attrib in self.plugin_attrib_map: - if attrib not in self.plugins: self.initPlugin(attrib) - self.initPlugin(attrib) - self.plugins[attrib][attrib] = value - return self - def __delitem__(self, attrib): if attrib.lower() in self.interfaces: if hasattr(self, "del%s" % attrib.title()): -- cgit v1.2.3