mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-23 19:19:53 +00:00
Some more docs house cleaning
This commit is contained in:
parent
6906c15e8e
commit
329b0df3f6
2 changed files with 70 additions and 134 deletions
|
@ -17,21 +17,21 @@ of the tedium of creating/manipulating XML.
|
||||||
|
|
||||||
The Foundation: XMLStream
|
The Foundation: XMLStream
|
||||||
-------------------------
|
-------------------------
|
||||||
``XMLStream`` is a mostly XMPP-agnostic class whose purpose is to read
|
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic
|
||||||
and write from a bi-directional XML stream. It also allows for callback
|
class whose purpose is to read and write from a bi-directional XML stream.
|
||||||
functions to execute when XML matching given patterns is received; these
|
It also allows for callback functions to execute when XML matching given
|
||||||
callbacks are also referred to as :term:`stream handlers <stream handler>`.
|
patterns is received; these callbacks are also referred to as :term:`stream
|
||||||
The class also provides a basic eventing system which can be triggered
|
handlers <stream handler>`. The class also provides a basic eventing system
|
||||||
either manually or on a timed schedule.
|
which can be triggered either manually or on a timed schedule.
|
||||||
|
|
||||||
The Main Threads
|
The Main Threads
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
``XMLStream`` instances run using at least three background threads: the
|
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` instances run using at
|
||||||
send thread, the read thread, and the scheduler thread. The send thread is
|
least three background threads: the send thread, the read thread, and the
|
||||||
in charge of monitoring the send queue and writing text to the outgoing
|
scheduler thread. The send thread is in charge of monitoring the send queue
|
||||||
XML stream. The read thread pulls text off of the incoming XML stream and
|
and writing text to the outgoing XML stream. The read thread pulls text off
|
||||||
stores the results in an event queue. The scheduler thread is used to emit
|
of the incoming XML stream and stores the results in an event queue. The
|
||||||
events after a given period of time.
|
scheduler thread is used to emit events after a given period of time.
|
||||||
|
|
||||||
Additionally, the main event processing loop may be executed in its
|
Additionally, the main event processing loop may be executed in its
|
||||||
own thread if SleekXMPP is being used in the background for another
|
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
|
new object is determined using a map of namespaced element names to
|
||||||
classes.
|
classes.
|
||||||
|
|
||||||
Our incoming XML is thus turned into a ``Message`` :term:`stanza object`
|
Our incoming XML is thus turned into a :class:`~sleekxmpp.stanza.Message`
|
||||||
because the namespaced element name ``{jabber:client}message`` is
|
:term:`stanza object` because the namespaced element name
|
||||||
associated with the class ``sleekxmpp.stanza.Message``.
|
``{jabber:client}message`` is associated with the class
|
||||||
|
:class:`~sleekxmpp.stanza.Message`.
|
||||||
|
|
||||||
2. **Match stanza objects to callbacks.**
|
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
|
:term:`stanza object` is paired with a reference to the handler and
|
||||||
placed into the event queue.
|
placed into the event queue.
|
||||||
|
|
||||||
Our ``Message`` object is thus paired with the message stanza handler
|
Our :class:`~sleekxmpp.stanza.Message` object is thus paired with the message stanza handler
|
||||||
``BaseXMPP._handle_message`` to create the tuple::
|
:meth:`BaseXMPP._handle_message` to create the tuple::
|
||||||
|
|
||||||
('stanza', stanza_obj, handler)
|
('stanza', stanza_obj, handler)
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ when this bit of XML is received (with an assumed namespace of
|
||||||
parameter.
|
parameter.
|
||||||
|
|
||||||
.. warning::
|
.. 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
|
processing thread. If the handler blocks, event processing will also
|
||||||
block.
|
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
|
Since a :term:`stream handler` shouldn't block, if extensive processing
|
||||||
for a stanza is required (such as needing to send and receive an
|
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
|
:class:`~sleekxmpp.stanza.Iq` stanza), then custom events must be used.
|
||||||
explicitly tied to the incoming XML stream and may be raised at any
|
These events are not explicitly tied to the incoming XML stream and may
|
||||||
time. Importantly, these events may be handled in their own thread.
|
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
|
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 <stream handler>`,
|
handler registered for the event. In contrast to :term:`stream handlers
|
||||||
these functions are referred to as :term:`event handlers <event handler>`.
|
<stream handler>`, these functions are referred to as :term:`event
|
||||||
Each stanza/handler pair is then put into the event queue.
|
handlers <event handler>`. Each stanza/handler pair is then put into the
|
||||||
|
event queue.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
It is possible to skip the event queue and process an event immediately
|
It is possible to skip the event queue and process an event immediately
|
||||||
by using ``direct=True`` when raising the event.
|
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::
|
raises a ``'message'`` event::
|
||||||
|
|
||||||
self.event('message', msg)
|
self.event('message', msg)
|
||||||
|
@ -145,125 +148,30 @@ when this bit of XML is received (with an assumed namespace of
|
||||||
|
|
||||||
Raising XMPP Awareness: BaseXMPP
|
Raising XMPP Awareness: BaseXMPP
|
||||||
--------------------------------
|
--------------------------------
|
||||||
While ``XMLStream`` attempts to shy away from anything too XMPP specific,
|
While :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
|
||||||
``BaseXMPP``'s sole purpose is to provide foundational support for sending
|
from anything too XMPP specific, :class:`~sleekxmpp.basexmpp.BaseXMPP`'s
|
||||||
and receiving XMPP stanzas. This support includes registering the basic
|
sole purpose is to provide foundational support for sending and receiving
|
||||||
message, presence, and iq stanzas, methods for creating and sending
|
XMPP stanzas. This support includes registering the basic message,
|
||||||
stanzas, and default handlers for incoming messages and keeping track of
|
presence, and iq stanzas, methods for creating and sending stanzas, and
|
||||||
presence notifications.
|
default handlers for incoming messages and keeping track of presence
|
||||||
|
notifications.
|
||||||
|
|
||||||
The plugin system for adding new XEP support is also maintained by
|
The plugin system for adding new XEP support is also maintained by
|
||||||
``BaseXMPP``.
|
:class:`~sleekxmpp.basexmpp.BaseXMPP`.
|
||||||
|
|
||||||
.. index:: ClientXMPP, BaseXMPP
|
.. index:: ClientXMPP, BaseXMPP
|
||||||
|
|
||||||
ClientXMPP
|
ClientXMPP
|
||||||
----------
|
----------
|
||||||
``ClientXMPP`` extends ``BaseXMPP`` with additional logic for connecting to
|
:class:`~sleekxmpp.clientxmpp.ClientXMPP` extends
|
||||||
an XMPP server by performing DNS lookups. It also adds support for stream
|
: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.
|
features such as STARTTLS and SASL.
|
||||||
|
|
||||||
.. index:: ComponentXMPP, BaseXMPP
|
.. index:: ComponentXMPP, BaseXMPP
|
||||||
|
|
||||||
ComponentXMPP
|
ComponentXMPP
|
||||||
-------------
|
-------------
|
||||||
``ComponentXMPP`` is only a thin layer on top of ``BaseXMPP`` that
|
:class:`~sleekxmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
|
||||||
implements the component handshake protocol.
|
:class:`~sleekxmpp.basexmpp.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 <stanza object>`
|
|
||||||
are wrappers for XML objects which expose dictionary like interfaces
|
|
||||||
for manipulating their XML content. For example, consider the XML:
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<message />
|
|
||||||
|
|
||||||
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("<message />"))
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
<message to="user@example.com">
|
|
||||||
<body>Following so far?</body>
|
|
||||||
</message>
|
|
||||||
|
|
||||||
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 <stanza object>` may be nested. Nested
|
|
||||||
:term:`stanza objects <stanza object>` are referred to as :term:`stanza plugins <stanza plugin>`
|
|
||||||
or :term:`substanzas <substanza>`.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
<the-parent-xml-element xmlns="the-parent-namespace" foo="a">
|
|
||||||
<the-child-xml-element xmlsn="the-child-namespace" baz="b" />
|
|
||||||
</the-parent-xml-element>
|
|
||||||
|
|
||||||
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 <substanza>` can be accessed using a standard
|
|
||||||
``substanzas`` interface.
|
|
||||||
|
|
28
docs/howto/stanzas.rst
Normal file
28
docs/howto/stanzas.rst
Normal file
|
@ -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
|
||||||
|
--------------------------
|
Loading…
Reference in a new issue