Commit 5ab77c74 authored by louiz’'s avatar louiz’
Browse files

Rename to slixmpp

parent e5582694
......@@ -6,7 +6,7 @@ docs/_build/
*.swp
.tox/
.coverage
sleekxmpp.egg-info/
slixmpp.egg-info/
.ropeproject/
4913
*~
......
SleekXMPP
Slixmpp
#########
SleekXMPP is an MIT licensed XMPP library for Python 2.6/3.1+,
and is featured in examples in
`XMPP: The Definitive Guide <http://oreilly.com/catalog/9780596521271>`_
by Kevin Smith, Remko Tronçon, and Peter Saint-Andre. If you've arrived
here from reading the Definitive Guide, please see the notes on updating
the examples to the latest version of SleekXMPP.
Slixmpp is an MIT licensed XMPP library for Python 3.4+. It is a fork of
SleekXMPP.
SleekXMPP's design goals and philosphy are:
**Low number of dependencies**
Installing and using SleekXMPP should be as simple as possible, without
having to deal with long dependency chains.
As part of reducing the number of dependencies, some third party
modules are included with SleekXMPP in the ``thirdparty`` directory.
Imports from this module first try to import an existing installed
version before loading the packaged version, when possible.
**Every XEP as a plugin**
Following Python's "batteries included" approach, the goal is to
provide support for all currently active XEPs (final and draft). Since
adding XEP support is done through easy to create plugins, the hope is
to also provide a solid base for implementing and creating experimental
XEPs.
**Rewarding to work with**
As much as possible, SleekXMPP should allow things to "just work" using
sensible defaults and appropriate abstractions. XML can be ugly to work
with, but it doesn't have to be that way.
Get the Code
------------
Get the latest stable version from PyPI::
pip install sleekxmpp
The latest source code for SleekXMPP may be found on `Github
<http://github.com/fritzy/SleekXMPP>`_. Releases can be found in the
``master`` branch, while the latest development version is in the
``develop`` branch.
**Latest Release**
- `1.3.1 <http://github.com/fritzy/SleekXMPP/zipball/1.3.1>`_
**Develop Releases**
- `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
Installing DNSPython
---------------------
If you are using Python3 and wish to use dnspython, you will have to checkout and
install the ``python3`` branch::
git clone http://github.com/rthalley/dnspython
cd dnspython
git checkout python3
python3 setup.py install
Discussion
----------
A mailing list and XMPP chat room are available for discussing and getting
help with SleekXMPP.
**Mailing List**
`SleekXMPP Discussion on Google Groups <http://groups.google.com/group/sleekxmpp-discussion>`_
**Chat**
`sleek@conference.jabber.org <xmpp:sleek@conference.jabber.org?join>`_
Slixmpp's goals is to only rewrite the core of the library (the low level
socket handling, the timers, the events dispatching) in order to remove all
threads.
Documentation and Testing
......@@ -83,22 +19,22 @@ be in ``docs/_build/html``::
make html
open _build/html/index.html
To run the test suite for SleekXMPP::
To run the test suite for Slixmpp::
python testall.py
The SleekXMPP Boilerplate
The Slixmpp Boilerplate
-------------------------
Projects using SleekXMPP tend to follow a basic pattern for setting up client/component
connections and configuration. Here is the gist of the boilerplate needed for a SleekXMPP
Projects using Slixmpp tend to follow a basic pattern for setting up client/component
connections and configuration. Here is the gist of the boilerplate needed for a Slixmpp
based project. See the documetation or examples directory for more detailed archetypes for
SleekXMPP projects::
Slixmpp projects::
import logging
from sleekxmpp import ClientXMPP
from sleekxmpp.exceptions import IqError, IqTimeout
from slixmpp import ClientXMPP
from slixmpp.exceptions import IqError, IqTimeout
class EchoBot(ClientXMPP):
......@@ -155,8 +91,15 @@ SleekXMPP projects::
xmpp.process(block=True)
Slixmpp Credits
---------------
**Maintainer of the slixmpp fork:** Florent Le Coz
`louiz@louiz.org <xmpp:louiz@louiz.org?message>`_,
Credits
-------
**Main Author:** Nathan Fritz
`fritzy@netflint.net <xmpp:fritzy@netflint.net?message>`_,
`@fritzy <http://twitter.com/fritzy>`_
......
......@@ -72,17 +72,17 @@ qthelp:
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SleekXMPP.qhcp"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Slixmpp.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SleekXMPP.qhc"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Slixmpp.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/SleekXMPP"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SleekXMPP"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Slixmpp"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Slixmpp"
@echo "# devhelp"
epub:
......
......@@ -2,7 +2,7 @@
BaseXMPP
========
.. module:: sleekxmpp.basexmpp
.. module:: slixmpp.basexmpp
.. autoclass:: BaseXMPP
:members:
......@@ -2,7 +2,7 @@
ClientXMPP
==========
.. module:: sleekxmpp.clientxmpp
.. module:: slixmpp.clientxmpp
.. autoclass:: ClientXMPP
:members:
......@@ -2,7 +2,7 @@
ComponentXMPP
=============
.. module:: sleekxmpp.componentxmpp
.. module:: slixmpp.componentxmpp
.. autoclass:: ComponentXMPP
:members:
Exceptions
==========
.. module:: sleekxmpp.exceptions
.. module:: slixmpp.exceptions
.. autoexception:: XMPPError
......
.. module:: sleekxmpp.xmlstream.filesocket
.. module:: slixmpp.xmlstream.filesocket
.. _filesocket:
......
......@@ -3,14 +3,14 @@ Stanza Handlers
The Basic Handler
-----------------
.. module:: sleekxmpp.xmlstream.handler.base
.. module:: slixmpp.xmlstream.handler.base
.. autoclass:: BaseHandler
:members:
Callback
--------
.. module:: sleekxmpp.xmlstream.handler.callback
.. module:: slixmpp.xmlstream.handler.callback
.. autoclass:: Callback
:members:
......@@ -18,7 +18,7 @@ Callback
Waiter
------
.. module:: sleekxmpp.xmlstream.handler.waiter
.. module:: slixmpp.xmlstream.handler.waiter
.. autoclass:: Waiter
:members:
Jabber IDs (JID)
=================
.. module:: sleekxmpp.xmlstream.jid
.. module:: slixmpp.xmlstream.jid
.. autoclass:: JID
:members:
......@@ -3,7 +3,7 @@ Stanza Matchers
The Basic Matcher
-----------------
.. module:: sleekxmpp.xmlstream.matcher.base
.. module:: slixmpp.xmlstream.matcher.base
.. autoclass:: MatcherBase
:members:
......@@ -11,7 +11,7 @@ The Basic Matcher
ID Matching
-----------
.. module:: sleekxmpp.xmlstream.matcher.id
.. module:: slixmpp.xmlstream.matcher.id
.. autoclass:: MatcherId
:members:
......@@ -19,7 +19,7 @@ ID Matching
Stanza Path Matching
--------------------
.. module:: sleekxmpp.xmlstream.matcher.stanzapath
.. module:: slixmpp.xmlstream.matcher.stanzapath
.. autoclass:: StanzaPath
:members:
......@@ -27,7 +27,7 @@ Stanza Path Matching
XPath
-----
.. module:: sleekxmpp.xmlstream.matcher.xpath
.. module:: slixmpp.xmlstream.matcher.xpath
.. autoclass:: MatchXPath
:members:
......@@ -35,7 +35,7 @@ XPath
XMLMask
-------
.. module:: sleekxmpp.xmlstream.matcher.xmlmask
.. module:: slixmpp.xmlstream.matcher.xmlmask
.. autoclass:: MatchXMLMask
:members:
......@@ -2,7 +2,7 @@
Scheduler
=========
.. module:: sleekxmpp.xmlstream.scheduler
.. module:: slixmpp.xmlstream.scheduler
.. autoclass:: Task
:members:
......
......@@ -4,9 +4,9 @@
Stanza Objects
==============
.. module:: sleekxmpp.xmlstream.stanzabase
.. module:: slixmpp.xmlstream.stanzabase
The :mod:`~sleekmxpp.xmlstream.stanzabase` module provides a wrapper for the
The :mod:`~slixmpp.xmlstream.stanzabase` module provides a wrapper for the
standard :mod:`~xml.etree.ElementTree` 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
......@@ -52,9 +52,9 @@ elements of the original XML chunk.
.. seealso::
:ref:`create-stanza-interfaces`.
Because the :mod:`~sleekxmpp.xmlstream.stanzabase` module was developed
Because the :mod:`~slixmpp.xmlstream.stanzabase` module was developed
as part of an `XMPP <http://xmpp.org>`_ library, these chunks of XML are
referred to as :term:`stanzas <stanza>`, and in SleekXMPP we refer to a
referred to as :term:`stanzas <stanza>`, and in Slixmpp we refer to a
subclass of :class:`ElementBase` which defines the interfaces needed for
interacting with a given :term:`stanza` a :term:`stanza object`.
......@@ -72,7 +72,7 @@ plugin stanza object. Here is an example:
<iq type="result">
<query xmlns="http://jabber.org/protocol/disco#info">
<identity category="client" type="bot" name="SleekXMPP Bot" />
<identity category="client" type="bot" name="Slixmpp Bot" />
</query>
</iq>
......@@ -84,13 +84,13 @@ we can access the plugin as so::
>>> iq['disco_info']
'<query xmlns="http://jabber.org/protocol/disco#info">
<identity category="client" type="bot" name="SleekXMPP Bot" />
<identity category="client" type="bot" name="Slixmpp Bot" />
</query>'
We can then drill down through the plugin object's interfaces as desired::
>>> iq['disco_info']['identities']
[('client', 'bot', 'SleekXMPP Bot')]
[('client', 'bot', 'Slixmpp 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
......
.. module:: sleekxmpp.xmlstream.tostring
.. module:: slixmpp.xmlstream.tostring
.. _tostring:
XML Serialization
=================
Since the XML layer of SleekXMPP is based on :mod:`~xml.etree.ElementTree`,
Since the XML layer of Slixmpp is based on :mod:`~xml.etree.ElementTree`,
why not just use the built-in :func:`~xml.etree.ElementTree.tostring`
method? The answer is that using that method produces ugly results when
using namespaces. The :func:`tostring()` method used here intelligently
hides namespaces when able and does not introduce excessive namespace
prefixes::
>>> from sleekxmpp.xmlstream.tostring import tostring
>>> from slixmpp.xmlstream.tostring import tostring
>>> from xml.etree import cElementTree as ET
>>> xml = ET.fromstring('<foo xmlns="bar"><baz /></foo>')
>>> ET.tostring(xml)
......@@ -25,7 +25,7 @@ produce unexpected results depending on how the :func:`tostring()` method
is invoked. For example, when sending XML on the wire, the main XMPP
stanzas with their namespace of ``jabber:client`` will not include the
namespace because that is already declared by the stream header. But, if
you create a :class:`~sleekxmpp.stanza.message.Message` instance and dump
you create a :class:`~slixmpp.stanza.message.Message` instance and dump
it to the terminal, the ``jabber:client`` namespace will appear.
.. autofunction:: tostring
......
......@@ -2,7 +2,7 @@
XML Stream
==========
.. module:: sleekxmpp.xmlstream.xmlstream
.. module:: slixmpp.xmlstream.xmlstream
.. autoexception:: RestartStream
......
.. index:: XMLStream, BaseXMPP, ClientXMPP, ComponentXMPP
SleekXMPP Architecture
Slixmpp Architecture
======================
The core of SleekXMPP is contained in four classes: ``XMLStream``,
The core of Slixmpp is contained in four classes: ``XMLStream``,
``BaseXMPP``, ``ClientXMPP``, and ``ComponentXMPP``. Along side this
stack is a library for working with XML objects that eliminates most
of the tedium of creating/manipulating XML.
......@@ -17,7 +17,7 @@ of the tedium of creating/manipulating XML.
The Foundation: XMLStream
-------------------------
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic
:class:`~slixmpp.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
......@@ -26,7 +26,7 @@ which can be triggered either manually or on a timed schedule.
The Main Threads
~~~~~~~~~~~~~~~~
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` instances run using at
:class:`~slixmpp.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
......@@ -34,7 +34,7 @@ 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
own thread if Slixmpp is being used in the background for another
application.
Short-lived threads may also be spawned as requested for threaded
......@@ -61,10 +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 :class:`~sleekxmpp.stanza.Message`
Our incoming XML is thus turned into a :class:`~slixmpp.stanza.Message`
:term:`stanza object` because the namespaced element name
``{jabber:client}message`` is associated with the class
:class:`~sleekxmpp.stanza.Message`.
:class:`~slixmpp.stanza.Message`.
2. **Match stanza objects to callbacks.**
......@@ -73,14 +73,14 @@ 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 :class:`~sleekxmpp.stanza.Message` object is thus paired with the message stanza handler
Our :class:`~slixmpp.stanza.Message` object is thus paired with the message stanza handler
:meth:`BaseXMPP._handle_message` to create the tuple::
('stanza', stanza_obj, handler)
3. **Process the event queue.**
The event queue is the heart of SleekXMPP. Nearly every action that
The event queue is the heart of Slixmpp. Nearly every action that
takes place is first inserted into this queue, whether that be received
stanzas, custom events, or scheduled events.
......@@ -97,7 +97,7 @@ 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
:class:`~sleekxmpp.stanza.Iq` stanza), then custom events must be used.
:class:`~slixmpp.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.
......@@ -148,8 +148,8 @@ when this bit of XML is received (with an assumed namespace of
Raising XMPP Awareness: BaseXMPP
--------------------------------
While :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
from anything too XMPP specific, :class:`~sleekxmpp.basexmpp.BaseXMPP`'s
While :class:`~slixmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
from anything too XMPP specific, :class:`~slixmpp.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
......@@ -157,14 +157,14 @@ default handlers for incoming messages and keeping track of presence
notifications.
The plugin system for adding new XEP support is also maintained by
:class:`~sleekxmpp.basexmpp.BaseXMPP`.
:class:`~slixmpp.basexmpp.BaseXMPP`.
.. index:: ClientXMPP, BaseXMPP
ClientXMPP
----------
:class:`~sleekxmpp.clientxmpp.ClientXMPP` extends
:class:`~sleekxmpp.clientxmpp.BaseXMPP` with additional logic for connecting
:class:`~slixmpp.clientxmpp.ClientXMPP` extends
:class:`~slixmpp.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.
......@@ -172,6 +172,6 @@ features such as STARTTLS and SASL.
ComponentXMPP
-------------
:class:`~sleekxmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
:class:`~sleekxmpp.basexmpp.BaseXMPP` that implements the component handshake
:class:`~slixmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
:class:`~slixmpp.basexmpp.BaseXMPP` that implements the component handshake
protocol.
# -*- coding: utf-8 -*-
#
# SleekXMPP documentation build configuration file, created by
# Slixmpp documentation build configuration file, created by
# sphinx-quickstart on Tue Aug 9 22:27:06 2011.
#
# This file is execfile()d with the current directory set to its containing dir.
......@@ -40,7 +40,7 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'SleekXMPP'
project = u'Slixmpp'
copyright = u'2011, Nathan Fritz, Lance Stout'
# The version info for the project you're documenting, acts as replacement for
......@@ -105,7 +105,7 @@ html_theme = 'haiku'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = 'SleekXMPP'
html_title = 'Slixmpp'
# A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = '%s Documentation' % release
......@@ -168,7 +168,7 @@ html_additional_pages = {
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'SleekXMPPdoc'
htmlhelp_basename = 'Slixmppdoc'
# -- Options for LaTeX output --------------------------------------------------
......@@ -182,7 +182,7 @@ htmlhelp_basename = 'SleekXMPPdoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'SleekXMPP.tex', u'SleekXMPP Documentation',
('index', 'Slixmpp.tex', u'Slixmpp Documentation',
u'Nathan Fritz, Lance Stout', 'manual'),
]
......@@ -215,7 +215,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'sleekxmpp', u'SleekXMPP Documentation',
('index', 'slixmpp', u'Slixmpp Documentation',
[u'Nathan Fritz, Lance Stout'], 1)
]
......
.. _create-plugin:
Creating a SleekXMPP Plugin
Creating a Slixmpp Plugin
===========================
One of the goals of SleekXMPP is to provide support for every draft or final
XMPP extension (`XEP <http://xmpp.org/extensions/>`_). To do this, SleekXMPP has a
One of the goals of Slixmpp is to provide support for every draft or final
XMPP extension (`XEP <http://xmpp.org/extensions/>`_). To do this, Slixmpp has a
plugin mechanism for adding the functionalities required by each XEP. But even
though plugins were made to quickly implement and prototype the official XMPP
extensions, there is no reason you can't create your own plugin to implement
......@@ -14,11 +14,11 @@ This guide will help walk you through the steps to
implement a rudimentary version of `XEP-0077 In-band
Registration <http://xmpp.org/extensions/xep-0077.html>`_. In-band registration
was implemented in example 14-6 (page 223) of `XMPP: The Definitive
Guide <http://oreilly.com/catalog/9780596521271>`_ because there was no SleekXMPP
Guide <http://oreilly.com/catalog/9780596521271>`_ because there was no Slixmpp
plugin for XEP-0077 at the time of writing. We will partially fix that issue
here by turning the example implementation from *XMPP: The Definitive Guide*
into a plugin. Again, note that this will not a complete implementation, and a
different, more robust, official plugin for XEP-0077 may be added to SleekXMPP
different, more robust, official plugin for XEP-0077 may be added to Slixmpp
in the future.
.. note::
......@@ -29,10 +29,10 @@ in the future.
First Steps
-----------
Every plugin inherits from the class :mod:`base_plugin <sleekxmpp.plugins.base.base_plugin>`,
Every plugin inherits from the class :mod:`base_plugin <slixmpp.plugins.base.base_plugin>`,
and must include a ``plugin_init`` method. While the
plugins distributed with SleekXMPP must be placed in the plugins directory
``sleekxmpp/plugins`` to be loaded, custom plugins may be loaded from any
plugins distributed with Slixmpp must be placed in the plugins directory
``slixmpp/plugins`` to be loaded, custom plugins may be loaded from any
module. To do so, use the following form when registering the plugin:
.. code-block:: python
......@@ -42,7 +42,7 @@ module. To do so, use the following form when registering the plugin:
The plugin name must be the same as the plugin's class name.
Now, we can open our favorite text editors and create ``xep_0077.py`` in
``SleekXMPP/sleekxmpp/plugins``. We want to do some basic house-keeping and
``Slixmpp/slixmpp/plugins``. We want to do some basic house-keeping and
declare the name and description of the XEP we are implementing. If you
are creating your own custom plugin, you don't need to include the ``xep``
attribute.
......@@ -50,13 +50,13 @@ attribute.
.. code-block:: python
"""
Creating a SleekXMPP Plugin
Creating a Slixmpp Plugin
This is a minimal implementation of XEP-0077 to serve
as a tutorial for creating SleekXMPP plugins.
as a tutorial for creating Slixmpp plugins.
"""
from sleekxmpp.plugins.base import base_plugin
from slixmpp.plugins.base import base_plugin
class xep_0077(base_plugin):
"""
......@@ -68,7 +68,7 @@ attribute.
self.xep = "0077"
Now that we have a basic plugin, we need to edit
``sleekxmpp/plugins/__init__.py`` to include our new plugin by adding
``slixmpp/plugins/__init__.py`` to include our new plugin by adding
``'xep_0077'`` to the ``__all__`` declaration.
Interacting with Other Plugins
......@@ -83,12 +83,12 @@ finish activating the plugin.
The ``post_init`` method needs to call ``base_plugin.post_init(self)``
which will mark that ``post_init`` has been called for the plugin. Once the
SleekXMPP object begins processing, ``post_init`` will be called on any plugins
Slixmpp object begins processing, ``post_init`` will be called on any plugins
that have not already run ``post_init``. This allows you to register plugins and
their dependencies without needing to worry about the order in which you do so.
**Note:** by adding this call we have introduced a dependency on the XEP-0030
plugin. Be sure to register ``'xep_0030'`` as well as ``'xep_0077'``. SleekXMPP
plugin. Be sure to register ``'xep_0030'`` as well as ``'xep_0077'``. Slixmpp
does not automatically load plugin dependencies for you.
.. code-block:: python
......@@ -141,7 +141,7 @@ behaviour:
**Note:** The accessor methods currently use title case, and not camel case.
Thus if you need to access an item named ``"methodName"`` you will need to
use ``getMethodname``. This naming convention might change to full camel
case in a future version of SleekXMPP.
case in a future version of Slixmpp.
* ``sub_interfaces``
A subset of ``interfaces``, but these keys map to the text of any
......@@ -156,8 +156,8 @@ behaviour:
.. code-block:: python
from sleekxmpp.xmlstream import ElementBase, ET, JID, register_stanza_plugin
from sleekxmpp import Iq
from slixmpp.xmlstream import ElementBase, ET, JID, register_stanza_plugin
from slixmpp import Iq
class Registration(ElementBase):
namespace = 'jabber:iq:register'
......@@ -209,7 +209,7 @@ registration to our ``plugin_init`` method.
Also, we need to associate our ``Registration`` class with IQ stanzas;
that requires the use of the ``register_stanza_plugin`` function (in