diff --git a/docs/architecture.rst b/docs/architecture.rst index 53c326e..a2e0a27 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -17,21 +17,21 @@ of the tedium of creating/manipulating XML. The Foundation: XMLStream ------------------------- -``XMLStream`` is a mostly XMPP-agnostic class whose purpose is to read -and write from a bi-directional XML stream. It also allows for callback -functions to execute when XML matching given patterns is received; these -callbacks are also referred to as :term:`stream handlers `. -The class also provides a basic eventing system which can be triggered -either manually or on a timed schedule. +:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic +class whose purpose is to read and write from a bi-directional XML stream. +It also allows for callback functions to execute when XML matching given +patterns is received; these callbacks are also referred to as :term:`stream +handlers `. The class also provides a basic eventing system +which can be triggered either manually or on a timed schedule. The Main Threads ~~~~~~~~~~~~~~~~ -``XMLStream`` instances run using at least three background threads: the -send thread, the read thread, and the scheduler thread. The send thread is -in charge of monitoring the send queue and writing text to the outgoing -XML stream. The read thread pulls text off of the incoming XML stream and -stores the results in an event queue. The scheduler thread is used to emit -events after a given period of time. +:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` instances run using at +least three background threads: the send thread, the read thread, and the +scheduler thread. The send thread is in charge of monitoring the send queue +and writing text to the outgoing XML stream. The read thread pulls text off +of the incoming XML stream and stores the results in an event queue. The +scheduler thread is used to emit events after a given period of time. Additionally, the main event processing loop may be executed in its own thread if SleekXMPP is being used in the background for another @@ -61,9 +61,10 @@ when this bit of XML is received (with an assumed namespace of new object is determined using a map of namespaced element names to classes. - Our incoming XML is thus turned into a ``Message`` :term:`stanza object` - because the namespaced element name ``{jabber:client}message`` is - associated with the class ``sleekxmpp.stanza.Message``. + Our incoming XML is thus turned into a :class:`~sleekxmpp.stanza.Message` + :term:`stanza object` because the namespaced element name + ``{jabber:client}message`` is associated with the class + :class:`~sleekxmpp.stanza.Message`. 2. **Match stanza objects to callbacks.** @@ -72,8 +73,8 @@ when this bit of XML is received (with an assumed namespace of :term:`stanza object` is paired with a reference to the handler and placed into the event queue. - Our ``Message`` object is thus paired with the message stanza handler - ``BaseXMPP._handle_message`` to create the tuple:: + Our :class:`~sleekxmpp.stanza.Message` object is thus paired with the message stanza handler + :meth:`BaseXMPP._handle_message` to create the tuple:: ('stanza', stanza_obj, handler) @@ -88,7 +89,7 @@ when this bit of XML is received (with an assumed namespace of parameter. .. warning:: - The callback, aka :term:`stream handler`, is executed in the main + The callback, aka :term:`stream handler`, is executed in the main event processing thread. If the handler blocks, event processing will also block. @@ -96,20 +97,22 @@ when this bit of XML is received (with an assumed namespace of Since a :term:`stream handler` shouldn't block, if extensive processing for a stanza is required (such as needing to send and receive an - ``Iq`` stanza), then custom events must be used. These events are not - explicitly tied to the incoming XML stream and may be raised at any - time. Importantly, these events may be handled in their own thread. + :class:`~sleekxmpp.stanza.Iq` stanza), then custom events must be used. + These events are not explicitly tied to the incoming XML stream and may + be raised at any time. Importantly, these events may be handled in their + own thread. When the event is raised, a copy of the stanza is created for each - handler registered for the event. In contrast to :term:`stream handlers `, - these functions are referred to as :term:`event handlers `. - Each stanza/handler pair is then put into the event queue. + handler registered for the event. In contrast to :term:`stream handlers + `, these functions are referred to as :term:`event + handlers `. Each stanza/handler pair is then put into the + event queue. .. note:: It is possible to skip the event queue and process an event immediately by using ``direct=True`` when raising the event. - The code for ``BaseXMPP._handle_message`` follows this pattern, and + The code for :meth:`BaseXMPP._handle_message` follows this pattern, and raises a ``'message'`` event:: self.event('message', msg) @@ -145,125 +148,30 @@ when this bit of XML is received (with an assumed namespace of Raising XMPP Awareness: BaseXMPP -------------------------------- -While ``XMLStream`` attempts to shy away from anything too XMPP specific, -``BaseXMPP``'s sole purpose is to provide foundational support for sending -and receiving XMPP stanzas. This support includes registering the basic -message, presence, and iq stanzas, methods for creating and sending -stanzas, and default handlers for incoming messages and keeping track of -presence notifications. +While :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` attempts to shy away +from anything too XMPP specific, :class:`~sleekxmpp.basexmpp.BaseXMPP`'s +sole purpose is to provide foundational support for sending and receiving +XMPP stanzas. This support includes registering the basic message, +presence, and iq stanzas, methods for creating and sending stanzas, and +default handlers for incoming messages and keeping track of presence +notifications. The plugin system for adding new XEP support is also maintained by -``BaseXMPP``. +:class:`~sleekxmpp.basexmpp.BaseXMPP`. .. index:: ClientXMPP, BaseXMPP ClientXMPP ---------- -``ClientXMPP`` extends ``BaseXMPP`` with additional logic for connecting to -an XMPP server by performing DNS lookups. It also adds support for stream +:class:`~sleekxmpp.clientxmpp.ClientXMPP` extends +:class:`~sleekxmpp.clientxmpp.BaseXMPP` with additional logic for connecting +to an XMPP server by performing DNS lookups. It also adds support for stream features such as STARTTLS and SASL. .. index:: ComponentXMPP, BaseXMPP ComponentXMPP ------------- -``ComponentXMPP`` is only a thin layer on top of ``BaseXMPP`` that -implements the component handshake protocol. - -.. index:: - double: object; stanza - -Stanza Objects: A Brief Look ----------------------------- -.. seealso:: - See :ref:`api-stanza-objects` for a more detailed overview. - -Almost worthy of their own standalone library, :term:`stanza objects ` -are wrappers for XML objects which expose dictionary like interfaces -for manipulating their XML content. For example, consider the XML: - -.. code-block:: xml - - - -A very plain element to start with, but we can create a :term:`stanza object` -using ``sleekxmpp.stanza.Message`` as so:: - - msg = Message(xml=ET.fromstring("")) - -The ``Message`` stanza class defines interfaces such as ``'body'`` and -``'to'``, so we can assign values to those interfaces to include new XML -content:: - - msg['body'] = "Following so far?" - msg['to'] = 'user@example.com' - -Dumping the XML content of ``msg`` (using ``msg.xml``), we find: - -.. code-block:: xml - - - Following so far? - - -The process is similar for reading from interfaces and deleting interface -contents. A :term:`stanza object` behaves very similarly to a regular -``dict`` object: you may assign to keys, read from keys, and ``del`` keys. - -Stanza interfaces come with built-in behaviours such as adding/removing -attribute and sub element values. However, a lot of the time more custom -logic is needed. This can be provided by defining methods of the form -``get_*``, ``set_*``, and ``del_*`` for any interface which requires custom -behaviour. - -Stanza Plugins -~~~~~~~~~~~~~~ -Since it is generally possible to embed one XML element inside another, -:term:`stanza objects ` may be nested. Nested -:term:`stanza objects ` are referred to as :term:`stanza plugins ` -or :term:`substanzas `. - -A :term:`stanza plugin` exposes its own interfaces by adding a new -interface to its parent stanza. To demonstrate, consider these two stanza -class definitions using ``sleekxmpp.xmlstream.ElementBase``: - - -.. code-block:: python - - class Parent(ElementBase): - name = "the-parent-xml-element-name" - namespace = "the-parent-namespace" - interfaces = set(('foo', 'bar')) - - class Child(ElementBase): - name = "the-child-xml-element-name" - namespace = "the-child-namespace" - plugin_attrib = 'child' - interfaces = set(('baz',)) - - -If we register the ``Child`` stanza as a plugin of the ``Parent`` stanza as -so, using ``sleekxmpp.xmlstream.register_stanza_plugin``:: - - register_stanza_plugin(Parent, Child) - -Then we can access content in the child stanza through the parent. -Note that the interface used to access the child stanza is the same as -``Child.plugin_attrib``:: - - parent = Parent() - parent['foo'] = 'a' - parent['child']['baz'] = 'b' - -The above code would produce: - -.. code-block:: xml - - - - - -It is also possible to allow a :term:`substanza` to appear multiple times -by using ``iterable=True`` in the ``register_stanza_plugin`` call. All -iterable :term:`substanzas ` can be accessed using a standard -``substanzas`` interface. +:class:`~sleekxmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of +:class:`~sleekxmpp.basexmpp.BaseXMPP` that implements the component handshake +protocol. diff --git a/docs/howto/stanzas.rst b/docs/howto/stanzas.rst new file mode 100644 index 0000000..7ca7bbf --- /dev/null +++ b/docs/howto/stanzas.rst @@ -0,0 +1,28 @@ +How to Work with Stanza Objects +=============================== + + +.. _create-stanza-interfaces: + +Defining Stanza Interfaces +-------------------------- + + +.. _create-stanza-plugins: + +Creating Stanza Plugins +----------------------- + + + +.. _create-extension-plugins: + +Creating a Stanza Extension +--------------------------- + + + +.. _override-parent-interfaces: + +Overriding a Parent Stanza +--------------------------