Add support for a new type of stanza interface: bool

The set of bool_interfaces provides default behaviour for
checking/setting the presence of empty subelements.

The prime example of this would be:

    bool_interfaces = set(['required'])

This would mean that ``stanza['required']`` would return ``True`` for:

    <stanza>
       <required />
    </stanza>

and ``False`` for:

    <stanza />

Likewise, assigning ``stanza['required'] = True`` would add an empty
``<required />`` element, and setting it to ``False`` would remove
such an element if it exists.
This commit is contained in:
Lance Stout 2012-03-27 21:05:50 -07:00
parent ee6a9b981a
commit a1ddd88208

View file

@ -228,6 +228,13 @@ class ElementBase(object):
#: needing to define custom methods.
sub_interfaces = tuple()
#: A subset of :attr:`interfaces` which maps the presence of
#: subelements to boolean values. Using this set allows for quickly
#: checking for the existence of empty subelements like ``<required />``.
#:
#: .. versionadded:: 1.1
bool_interfaces = tuple()
#: In some cases you may wish to override the behaviour of one of the
#: parent stanza's interfaces. The ``overrides`` list specifies the
#: interface name and access method to be overridden. For example,
@ -489,9 +496,11 @@ class ElementBase(object):
4. The result of calling ``getFoo``.
5. The contents of the ``foo`` subelement, if ``foo`` is listed
in :attr:`sub_interfaces`.
6. The value of the ``foo`` attribute of the XML object.
7. The plugin named ``'foo'``
8. An empty string.
6. True or False depending on the existence of a ``foo``
subelement and ``foo`` is in :attr:`bool_interfaces`.
7. The value of the ``foo`` attribute of the XML object.
8. The plugin named ``'foo'``
9. An empty string.
:param string attrib: The name of the requested stanza interface.
"""
@ -517,6 +526,9 @@ class ElementBase(object):
else:
if attrib in self.sub_interfaces:
return self._get_sub_text(attrib)
elif attrib in self.bool_interfaces:
elem = self.xml.find('{%s}%s' % (self.namespace, attrib))
return elem is not None
else:
return self._get_attr(attrib)
elif attrib in self.plugin_attrib_map:
@ -550,10 +562,12 @@ class ElementBase(object):
4. Call ``setFoo``, if it exists.
5. Set the text of a ``foo`` element, if ``'foo'`` is
in :attr:`sub_interfaces`.
6. Set the value of a top level XML attribute named ``foo``.
7. Attempt to pass the value to a plugin named ``'foo'`` using
6. Add or remove an empty subelement ``foo``
if ``foo`` is in :attr:`bool_interfaces`.
7. Set the value of a top level XML attribute named ``foo``.
8. Attempt to pass the value to a plugin named ``'foo'`` using
the plugin's ``'foo'`` interface.
8. Do nothing.
9. Do nothing.
:param string attrib: The name of the stanza interface to modify.
:param value: The new value of the stanza interface.
@ -580,6 +594,11 @@ class ElementBase(object):
else:
if attrib in self.sub_interfaces:
return self._set_sub_text(attrib, text=value)
elif attrib in self.bool_interfaces:
if value:
return self._set_sub_text(attrib, '', keep=True)
else:
return self._set_sub_text(attrib, '', keep=False)
else:
self._set_attr(attrib, value)
else:
@ -614,9 +633,11 @@ class ElementBase(object):
3. Call ``delFoo``, if it exists.
4. Delete ``foo`` element, if ``'foo'`` is in
:attr:`sub_interfaces`.
5. Delete top level XML attribute named ``foo``.
6. Remove the ``foo`` plugin, if it was loaded.
7. Do nothing.
5. Remove ``foo`` element if ``'foo'`` is in
:attr:`bool_interfaces`.
6. Delete top level XML attribute named ``foo``.
7. Remove the ``foo`` plugin, if it was loaded.
8. Do nothing.
:param attrib: The name of the affected stanza interface.
"""
@ -640,6 +661,8 @@ class ElementBase(object):
else:
if attrib in self.sub_interfaces:
return self._del_sub(attrib)
elif attrib in self.bool_interfaces:
return self._del_sub(attrib)
else:
self._del_attr(attrib)
elif attrib in self.plugin_attrib_map: