From 4498e992a2b082917a6b6cc855ed1e38cf905867 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 21 Nov 2011 23:17:39 -0800 Subject: [PATCH] Add more stanzabase docs --- docs/api/stanzabase.rst | 120 ++++++++++++++++++++++++++++++ sleekxmpp/xmlstream/stanzabase.py | 14 ++-- 2 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 docs/api/stanzabase.rst diff --git a/docs/api/stanzabase.rst b/docs/api/stanzabase.rst new file mode 100644 index 0000000..e31fb26 --- /dev/null +++ b/docs/api/stanzabase.rst @@ -0,0 +1,120 @@ +========== +stanzabase +========== + +.. module:: sleekxmpp.xmlstream.stanzabase + +The :mod:`sleekmxpp.xmlstream.stanzabase` module provides a wrapper for the +standard :mod:`xml.etree.cElementTree` module that makes working with XML +less painful. Instead of having to manually move up and down an element +tree and insert subelements and attributes, you can interact with an object +that behaves like a normal dictionary or JSON object, which silently maps +keys to XML attributes and elements behind the scenes. + +Overview +-------- + +The usefulness of this layer grows as the XML you have to work with +becomes nested. The base unit here, :class:`ElementBase`, can map to a +single XML element, or several depending on how advanced of a mapping +is desired from interface keys to XML structures. For example, a single +:class:`ElementBase` derived class could easily describe: + +.. code-block:: xml + + + Hi! + + Custom item 1 + Custom item 2 + Custom item 3 + + + +If that chunk of XML were put in the :class:`ElementBase` instance +``msg``, we could extract the data from the XML using:: + + >>> msg['extra'] + ['Custom item 1', 'Custom item 2', 'Custom item 3'] + +Provided we set up the handler for the ``'extra'`` interface to load the +```` element content into a list. + +The key concept is that given an XML structure that will be repeatedly +used, we can define a set of :term:`interfaces` which when we read from, +write to, or delete, will automatically manipulate the underlying XML +as needed. In addition, some of these interfaces may in turn reference +child objects which expose interfaces for particularly complex child +elements of the original XML chunk. + +.. seealso:: + :ref:`create-stanza-interfaces`. + +Because the :mod:`sleekxmpp.xmlstream.stanzabase` module was developed +as part of an `XMPP `_ library, these chunks of XML are +referred to as :term:`stanzas `, and in SleekXMPP we refer to a +subclass of :class:`ElementBase` which defines the interfaces needed for +interacting with a given :term:`stanza` a :term:`stanza object`. + +To make dealing with more complicated and nested :term:`stanzas ` +or XML chunks easier, :term:`stanza objects ` can be +composed in two ways: as iterable child objects or as plugins. Iterable +child stanzas, or :term:`substanzas`, are accessible through a special +``'substanzas'`` interface. This option is useful for stanzas which +may contain more than one of the same kind of element. When there is +only one child element, the plugin method is more useful. For plugins, +a parent stanza object delegates one of its XML child elements to the +plugin stanza object. Here is an example: + +.. code-block:: xml + + + + + + + +We can can arrange this stanza into two objects: an outer, wrapper object for +dealing with the ```` element and its attributes, and a plugin object to +control the ```` payload element. If we give the plugin object the +name ``'disco_info'`` (using its :attr:`ElementBase.plugin_attrib` value), then +we can access the plugin as so:: + + >>> iq['disco_info'] + ' + + ' + +We can then drill down through the plugin object's interfaces as desired:: + + >>> iq['disco_info']['identities'] + [('client', 'bot', 'SleekXMPP Bot')] + +Plugins may also add new interfaces to the parent stanza object as if they +had been defined by the parent directly, and can also override the behaviour +of an interface defined by the parent. + +.. seealso:: + + - :ref:`creating-extension-plugins` + - :ref:`overriding-parent-interfaces` + + +Registering Stanza Plugins +-------------------------- + +.. autofunction:: register_stanza_plugin + +ElementBase +----------- + +.. autoclass:: ElementBase + :members: + :private-members: + :special-members: + +StanzaBase +---------- + +.. autoclass:: StanzaBase + :members: diff --git a/sleekxmpp/xmlstream/stanzabase.py b/sleekxmpp/xmlstream/stanzabase.py index 3c5cf8d..2af5ec3 100644 --- a/sleekxmpp/xmlstream/stanzabase.py +++ b/sleekxmpp/xmlstream/stanzabase.py @@ -140,7 +140,7 @@ class ElementBase(object): >>> message['custom']['custom'] # Must use all interfaces 'bar' - If the plugin sets the value is_extension = True, then both setting + If the plugin sets :attr:`is_extension` to ``True``, then both setting and getting an interface value that is the same as the plugin's plugin_attrib value will work, as so:: @@ -1087,12 +1087,12 @@ class ElementBase(object): class StanzaBase(ElementBase): """ - StanzaBase provides the foundation for all other stanza objects used by - SleekXMPP, and defines a basic set of interfaces common to nearly - all stanzas. These interfaces are the 'id', 'type', 'to', and 'from' - attributes. An additional interface, 'payload', is available to access - the XML contents of the stanza. Most stanza objects will provided more - specific interfaces, however. + StanzaBase provides the foundation for all other stanza objects used + by SleekXMPP, and defines a basic set of interfaces common to nearly + all stanzas. These interfaces are the ``'id'``, ``'type'``, ``'to'``, + and ``'from'`` attributes. An additional interface, ``'payload'``, is + available to access the XML contents of the stanza. Most stanza objects + will provided more specific interfaces, however. **Stanza Interfaces:**