summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_static/pygments.css70
-rw-r--r--docs/_templates/defindex.html35
-rw-r--r--docs/_templates/indexcontent.html61
-rw-r--r--docs/_templates/layout.html69
-rw-r--r--docs/api/basexmpp.rst2
-rw-r--r--docs/api/clientxmpp.rst13
-rw-r--r--docs/api/componentxmpp.rst8
-rw-r--r--docs/api/exceptions.rst14
-rw-r--r--docs/api/xmlstream.rst8
-rw-r--r--docs/api/xmlstream/filesocket.rst12
-rw-r--r--docs/api/xmlstream/handler.rst24
-rw-r--r--docs/api/xmlstream/jid.rst7
-rw-r--r--docs/api/xmlstream/matcher.rst41
-rw-r--r--docs/api/xmlstream/scheduler.rst11
-rw-r--r--docs/api/xmlstream/stanzabase.rst123
-rw-r--r--docs/api/xmlstream/tostring.rst46
-rw-r--r--docs/api/xmlstream/xmlstream.rst10
-rw-r--r--docs/architecture.rst176
-rw-r--r--docs/conf.py12
-rw-r--r--docs/create_plugin.rst2
-rw-r--r--docs/getting_started/component.rst73
-rw-r--r--docs/getting_started/iq.rst180
-rw-r--r--docs/getting_started/proxy.rst40
-rw-r--r--docs/handlersmatchers.rst2
-rw-r--r--docs/howto/stanzas.rst30
-rw-r--r--docs/index.rst40
-rw-r--r--docs/python-objects.invbin0 -> 105830 bytes
-rw-r--r--docs/xeps.rst48
28 files changed, 755 insertions, 402 deletions
diff --git a/docs/_static/pygments.css b/docs/_static/pygments.css
deleted file mode 100644
index f04bc738..00000000
--- a/docs/_static/pygments.css
+++ /dev/null
@@ -1,70 +0,0 @@
-.highlight .hll { background-color: #ffffcc }
-.highlight { background: #000000; color: #f6f3e8; }
-.highlight .c { color: #7C7C7C; } /* Comment */
-.highlight .err { color: #f6f3e8; } /* Error */
-.highlight .g { color: #f6f3e8; } /* Generic */
-.highlight .k { color: #00ADEE; } /* Keyword */
-.highlight .l { color: #f6f3e8; } /* Literal */
-.highlight .n { color: #f6f3e8; } /* Name */
-.highlight .o { color: #f6f3e8; } /* Operator */
-.highlight .x { color: #f6f3e8; } /* Other */
-.highlight .p { color: #f6f3e8; } /* Punctuation */
-.highlight .cm { color: #7C7C7C; } /* Comment.Multiline */
-.highlight .cp { color: #96CBFE; } /* Comment.Preproc */
-.highlight .c1 { color: #7C7C7C; } /* Comment.Single */
-.highlight .cs { color: #7C7C7C; } /* Comment.Special */
-.highlight .gd { color: #f6f3e8; } /* Generic.Deleted */
-.highlight .ge { color: #f6f3e8; } /* Generic.Emph */
-.highlight .gr { color: #ffffff; background-color: #ff0000 } /* Generic.Error */
-.highlight .gh { color: #f6f3e8; font-weight: bold; } /* Generic.Heading */
-.highlight .gi { color: #f6f3e8; } /* Generic.Inserted */
-.highlight .go { color: #070707; } /* Generic.Output */
-.highlight .gp { color: #f6f3e8; } /* Generic.Prompt */
-.highlight .gs { color: #f6f3e8; } /* Generic.Strong */
-.highlight .gu { color: #f6f3e8; font-weight: bold; } /* Generic.Subheading */
-.highlight .gt { color: #ffffff; font-weight: bold; background-color: #FF6C60 } /* Generic.Traceback */
-.highlight .kc { color: #6699CC; } /* Keyword.Constant */
-.highlight .kd { color: #6699CC; } /* Keyword.Declaration */
-.highlight .kn { color: #6699CC; } /* Keyword.Namespace */
-.highlight .kp { color: #6699CC; } /* Keyword.Pseudo */
-.highlight .kr { color: #6699CC; } /* Keyword.Reserved */
-.highlight .kt { color: #FFFFB6; } /* Keyword.Type */
-.highlight .ld { color: #f6f3e8; } /* Literal.Date */
-.highlight .m { color: #FF73FD; } /* Literal.Number */
-.highlight .s { color: #F46DBA;/*#A8FF60;*/ } /* Literal.String */
-.highlight .na { color: #f6f3e8; } /* Name.Attribute */
-.highlight .nb { color: #f6f3e8; } /* Name.Builtin */
-.highlight .nc { color: #f6f3e8; } /* Name.Class */
-.highlight .no { color: #99CC99; } /* Name.Constant */
-.highlight .nd { color: #f6f3e8; } /* Name.Decorator */
-.highlight .ni { color: #E18964; } /* Name.Entity */
-.highlight .ne { color: #f6f3e8; } /* Name.Exception */
-.highlight .nf { color: #F64DBA; } /* Name.Function */
-.highlight .nl { color: #f6f3e8; } /* Name.Label */
-.highlight .nn { color: #f6f3e8; } /* Name.Namespace */
-.highlight .nx { color: #f6f3e8; } /* Name.Other */
-.highlight .py { color: #f6f3e8; } /* Name.Property */
-.highlight .nt { color: #00ADEE; } /* Name.Tag */
-.highlight .nv { color: #C6C5FE; } /* Name.Variable */
-.highlight .ow { color: #ffffff; } /* Operator.Word */
-.highlight .w { color: #f6f3e8; } /* Text.Whitespace */
-.highlight .mf { color: #FF73FD; } /* Literal.Number.Float */
-.highlight .mh { color: #FF73FD; } /* Literal.Number.Hex */
-.highlight .mi { color: #FF73FD; } /* Literal.Number.Integer */
-.highlight .mo { color: #FF73FD; } /* Literal.Number.Oct */
-.highlight .sb { color: #A8FF60; } /* Literal.String.Backtick */
-.highlight .sc { color: #A8FF60; } /* Literal.String.Char */
-.highlight .sd { color: #A8FF60; } /* Literal.String.Doc */
-.highlight .s2 { color: #A8FF60; } /* Literal.String.Double */
-.highlight .se { color: #A8FF60; } /* Literal.String.Escape */
-.highlight .sh { color: #A8FF60; } /* Literal.String.Heredoc */
-.highlight .si { color: #A8FF60; } /* Literal.String.Interpol */
-.highlight .sx { color: #A8FF60; } /* Literal.String.Other */
-.highlight .sr { color: #A8FF60; } /* Literal.String.Regex */
-.highlight .s1 { color: #A8FF60; } /* Literal.String.Single */
-.highlight .ss { color: #A8FF60; } /* Literal.String.Symbol */
-.highlight .bp { color: #f6f3e8; } /* Name.Builtin.Pseudo */
-.highlight .vc { color: #C6C5FE; } /* Name.Variable.Class */
-.highlight .vg { color: #C6C5FE; } /* Name.Variable.Global */
-.highlight .vi { color: #C6C5FE; } /* Name.Variable.Instance */
-.highlight .il { color: #FF73FD; } /* Literal.Number.Integer.Long */
diff --git a/docs/_templates/defindex.html b/docs/_templates/defindex.html
deleted file mode 100644
index ce8d3af6..00000000
--- a/docs/_templates/defindex.html
+++ /dev/null
@@ -1,35 +0,0 @@
-{#
- basic/defindex.html
- ~~~~~~~~~~~~~~~~~~~
-
- Default template for the "index" page.
-
- :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-#}
-{% extends "layout.html" %}
-{% set title = _('Overview') %}
-{% block body %}
- <h1>{{ docstitle|e }}</h1>
- <p>
- Welcome! This is
- {% block description %}the documentation for {{ project|e }}
- {{ release|e }}{% if last_updated %}, last updated {{ last_updated|e }}{% endif %}{% endblock %}.
- </p>
- {% block tables %}
- <p><strong>{{ _('Indices and tables:') }}</strong></p>
- <table class="contentstable" align="center"><tr>
- <td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">{{ _('Complete Table of Contents') }}</a><br>
- <span class="linkdescr">{{ _('lists all sections and subsections') }}</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">{{ _('Search Page') }}</a><br>
- <span class="linkdescr">{{ _('search this documentation') }}</span></p>
- </td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("modindex") }}">{{ _('Global Module Index') }}</a><br>
- <span class="linkdescr">{{ _('quick access to all modules') }}</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">{{ _('General Index') }}</a><br>
- <span class="linkdescr">{{ _('all functions, classes, terms') }}</span></p>
- </td></tr>
- </table>
- {% endblock %}
-{% endblock %}
diff --git a/docs/_templates/indexcontent.html b/docs/_templates/indexcontent.html
deleted file mode 100644
index d5e17cd6..00000000
--- a/docs/_templates/indexcontent.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{% extends "defindex.html" %}
-{% block tables %}
- <p><strong>Parts of the documentation:</strong></p>
- <table class="contentstable" align="center"><tr>
- <td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("whatsnew/" + version) }}">What's new in Python {{ version }}?</a><br/>
- <span class="linkdescr">or <a href="{{ pathto("whatsnew/index") }}">all "What's new" documents</a> since 2.0</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("tutorial/index") }}">Tutorial</a><br/>
- <span class="linkdescr">start here</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
- <span class="linkdescr">keep this under your pillow</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">Language Reference</a><br/>
- <span class="linkdescr">describes syntax and language elements</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("using/index") }}">Python Setup and Usage</a><br/>
- <span class="linkdescr">how to use Python on different platforms</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("howto/index") }}">Python HOWTOs</a><br/>
- <span class="linkdescr">in-depth documents on specific topics</span></p>
- </td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("extending/index") }}">Extending and Embedding</a><br/>
- <span class="linkdescr">tutorial for C/C++ programmers</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("c-api/index") }}">Python/C API</a><br/>
- <span class="linkdescr">reference for C/C++ programmers</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("install/index") }}">Installing Python Modules</a><br/>
- <span class="linkdescr">information for installers &amp; sys-admins</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("distutils/index") }}">Distributing Python Modules</a><br/>
- <span class="linkdescr">sharing modules with others</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("documenting/index") }}">Documenting Python</a><br/>
- <span class="linkdescr">guide for documentation authors</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("faq/index") }}">FAQs</a><br/>
- <span class="linkdescr">frequently asked questions (with answers!)</span></p>
- </td></tr>
- </table>
-
- <p><strong>Indices and tables:</strong></p>
- <table class="contentstable" align="center"><tr>
- <td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("py-modindex") }}">Global Module Index</a><br/>
- <span class="linkdescr">quick access to all modules</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
- <span class="linkdescr">all functions, classes, terms</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">Glossary</a><br/>
- <span class="linkdescr">the most important terms explained</span></p>
- </td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
- <span class="linkdescr">search this documentation</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br/>
- <span class="linkdescr">lists all sections and subsections</span></p>
- </td></tr>
- </table>
-
- <p><strong>Meta information:</strong></p>
- <table class="contentstable" align="center"><tr>
- <td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("bugs") }}">Reporting bugs</a></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("about") }}">About the documentation</a></p>
- </td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("license") }}">History and License of Python</a></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("copyright") }}">Copyright</a></p>
- </td></tr>
- </table>
-{% endblock %}
diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html
deleted file mode 100644
index a5dd7c82..00000000
--- a/docs/_templates/layout.html
+++ /dev/null
@@ -1,69 +0,0 @@
-{#
- haiku/layout.html
- ~~~~~~~~~~~~~~~~~
-
- Sphinx layout template for the haiku theme.
-
- :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-#}
-{% extends "basic/layout.html" %}
-{% set script_files = script_files + ['_static/theme_extras.js'] %}
-{% set css_files = css_files + ['_static/print.css'] %}
-
-{# do not display relbars #}
-{% block relbar1 %}{% endblock %}
-{% block relbar2 %}{% endblock %}
-
-{% macro nav() %}
- <p>
- {%- block haikurel1 %}
- {%- endblock %}
- {%- if prev %}
- «&#160;&#160;<a href="{{ prev.link|e }}">{{ prev.title }}</a>
- &#160;&#160;::&#160;&#160;
- {%- endif %}
- <a class="uplink" href="{{ pathto(master_doc) }}">{{ _('Contents') }}</a>
- {%- if next %}
- &#160;&#160;::&#160;&#160;
- <a href="{{ next.link|e }}">{{ next.title }}</a>&#160;&#160;»
- {%- endif %}
- {%- block haikurel2 %}
- {%- endblock %}
- </p>
-{% endmacro %}
-
-{% block content %}
- <div class="header">
- {%- block haikuheader %}
- {%- if theme_full_logo != "false" %}
- <a href="{{ pathto('index') }}">
- <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
- </a>
- {%- else %}
- {%- if logo -%}
- <img class="rightlogo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
- {%- endif -%}
- <h1 class="heading">
- <a href="{{ pathto('index') }}"><span>{{ project|e }}</span></a>
- </h1>
- <h2 class="heading"><span>{{ shorttitle|e }}</span></h2>
- {%- endif %}
- {%- endblock %}
- </div>
- <div class="topnav">
- {{ nav() }}
- </div>
- <div class="content">
- {#{%- if display_toc %}
- <div id="toc">
- <h3>Table Of Contents</h3>
- {{ toc }}
- </div>
- {%- endif %}#}
- {% block body %}{% endblock %}
- </div>
- <div class="bottomnav">
- {{ nav() }}
- </div>
-{% endblock %}
diff --git a/docs/api/basexmpp.rst b/docs/api/basexmpp.rst
index 841df3db..fa96322e 100644
--- a/docs/api/basexmpp.rst
+++ b/docs/api/basexmpp.rst
@@ -1,5 +1,5 @@
========
-basexmpp
+BaseXMPP
========
.. module:: sleekxmpp.basexmpp
diff --git a/docs/api/clientxmpp.rst b/docs/api/clientxmpp.rst
index 8f87664e..a6f32c43 100644
--- a/docs/api/clientxmpp.rst
+++ b/docs/api/clientxmpp.rst
@@ -1,17 +1,8 @@
==========
-clientxmpp
+ClientXMPP
==========
.. module:: sleekxmpp.clientxmpp
.. autoclass:: ClientXMPP
-
- .. automethod:: connect
-
- .. automethod:: register_feature
-
- .. automethod:: get_roster
-
- .. automethod:: update_roster
-
- .. automethod:: del_roster_item
+ :members:
diff --git a/docs/api/componentxmpp.rst b/docs/api/componentxmpp.rst
new file mode 100644
index 00000000..989120c2
--- /dev/null
+++ b/docs/api/componentxmpp.rst
@@ -0,0 +1,8 @@
+=============
+ComponentXMPP
+=============
+
+.. module:: sleekxmpp.componentxmpp
+
+.. autoclass:: ComponentXMPP
+ :members:
diff --git a/docs/api/exceptions.rst b/docs/api/exceptions.rst
new file mode 100644
index 00000000..7bc72ce5
--- /dev/null
+++ b/docs/api/exceptions.rst
@@ -0,0 +1,14 @@
+Exceptions
+==========
+
+.. module:: sleekxmpp.exceptions
+
+
+.. autoexception:: XMPPError
+ :members:
+
+.. autoexception:: IqError
+ :members:
+
+.. autoexception:: IqTimeout
+ :members:
diff --git a/docs/api/xmlstream.rst b/docs/api/xmlstream.rst
deleted file mode 100644
index 7835bf57..00000000
--- a/docs/api/xmlstream.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-=========
-xmlstream
-=========
-
-.. module:: sleekxmpp.xmlstream
-
-.. autoclass:: XMLStream
- :members:
diff --git a/docs/api/xmlstream/filesocket.rst b/docs/api/xmlstream/filesocket.rst
new file mode 100644
index 00000000..35f44019
--- /dev/null
+++ b/docs/api/xmlstream/filesocket.rst
@@ -0,0 +1,12 @@
+.. module:: sleekxmpp.xmlstream.filesocket
+
+.. _filesocket:
+
+Python 2.6 File Socket Shims
+============================
+
+.. autoclass:: FileSocket
+ :members:
+
+.. autoclass:: Socket26
+ :members:
diff --git a/docs/api/xmlstream/handler.rst b/docs/api/xmlstream/handler.rst
new file mode 100644
index 00000000..33c0bf42
--- /dev/null
+++ b/docs/api/xmlstream/handler.rst
@@ -0,0 +1,24 @@
+Stanza Handlers
+===============
+
+The Basic Handler
+-----------------
+.. module:: sleekxmpp.xmlstream.handler.base
+
+.. autoclass:: BaseHandler
+ :members:
+
+Callback
+--------
+.. module:: sleekxmpp.xmlstream.handler.callback
+
+.. autoclass:: Callback
+ :members:
+
+
+Waiter
+------
+.. module:: sleekxmpp.xmlstream.handler.waiter
+
+.. autoclass:: Waiter
+ :members:
diff --git a/docs/api/xmlstream/jid.rst b/docs/api/xmlstream/jid.rst
new file mode 100644
index 00000000..22a2db45
--- /dev/null
+++ b/docs/api/xmlstream/jid.rst
@@ -0,0 +1,7 @@
+Jabber IDs (JID)
+=================
+
+.. module:: sleekxmpp.xmlstream.jid
+
+.. autoclass:: JID
+ :members:
diff --git a/docs/api/xmlstream/matcher.rst b/docs/api/xmlstream/matcher.rst
new file mode 100644
index 00000000..df3591bc
--- /dev/null
+++ b/docs/api/xmlstream/matcher.rst
@@ -0,0 +1,41 @@
+Stanza Matchers
+===============
+
+The Basic Matcher
+-----------------
+.. module:: sleekxmpp.xmlstream.matcher.base
+
+.. autoclass:: MatcherBase
+ :members:
+
+
+ID Matching
+-----------
+.. module:: sleekxmpp.xmlstream.matcher.id
+
+.. autoclass:: MatcherId
+ :members:
+
+
+Stanza Path Matching
+--------------------
+.. module:: sleekxmpp.xmlstream.matcher.stanzapath
+
+.. autoclass:: StanzaPath
+ :members:
+
+
+XPath
+-----
+.. module:: sleekxmpp.xmlstream.matcher.xpath
+
+.. autoclass:: MatchXPath
+ :members:
+
+
+XMLMask
+-------
+.. module:: sleekxmpp.xmlstream.matcher.xmlmask
+
+.. autoclass:: MatchXMLMask
+ :members:
diff --git a/docs/api/xmlstream/scheduler.rst b/docs/api/xmlstream/scheduler.rst
new file mode 100644
index 00000000..ff91701e
--- /dev/null
+++ b/docs/api/xmlstream/scheduler.rst
@@ -0,0 +1,11 @@
+=========
+Scheduler
+=========
+
+.. module:: sleekxmpp.xmlstream.scheduler
+
+.. autoclass:: Task
+ :members:
+
+.. autoclass:: Scheduler
+ :members:
diff --git a/docs/api/xmlstream/stanzabase.rst b/docs/api/xmlstream/stanzabase.rst
new file mode 100644
index 00000000..f575299e
--- /dev/null
+++ b/docs/api/xmlstream/stanzabase.rst
@@ -0,0 +1,123 @@
+.. _stanzabase:
+
+==============
+Stanza Objects
+==============
+
+.. module:: sleekxmpp.xmlstream.stanzabase
+
+The :mod:`~sleekmxpp.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
+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
+
+ <message to="user@example.com" from="friend@example.com">
+ <body>Hi!</body>
+ <x:extra>
+ <x:item>Custom item 1</x:item>
+ <x:item>Custom item 2</x:item>
+ <x:item>Custom item 3</x:item>
+ </x:extra>
+ </message>
+
+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
+``<x:item>`` 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 <http://xmpp.org>`_ library, these chunks of XML are
+referred to as :term:`stanzas <stanza>`, 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 <stanza>`
+or XML chunks easier, :term:`stanza objects <stanza object>` 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
+
+ <iq type="result">
+ <query xmlns="http://jabber.org/protocol/disco#info">
+ <identity category="client" type="bot" name="SleekXMPP Bot" />
+ </query>
+ </iq>
+
+We can can arrange this stanza into two objects: an outer, wrapper object for
+dealing with the ``<iq />`` element and its attributes, and a plugin object to
+control the ``<query />`` 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']
+ '<query xmlns="http://jabber.org/protocol/disco#info">
+ <identity category="client" type="bot" name="SleekXMPP Bot" />
+ </query>'
+
+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:`create-stanza-plugins`
+ - :ref:`create-extension-plugins`
+ - :ref:`override-parent-interfaces`
+
+
+Registering Stanza Plugins
+--------------------------
+
+.. autofunction:: register_stanza_plugin
+
+ElementBase
+-----------
+
+.. autoclass:: ElementBase
+ :members:
+ :private-members:
+ :special-members:
+
+StanzaBase
+----------
+
+.. autoclass:: StanzaBase
+ :members:
diff --git a/docs/api/xmlstream/tostring.rst b/docs/api/xmlstream/tostring.rst
new file mode 100644
index 00000000..82a8c2a5
--- /dev/null
+++ b/docs/api/xmlstream/tostring.rst
@@ -0,0 +1,46 @@
+.. module:: sleekxmpp.xmlstream.tostring
+
+.. _tostring:
+
+XML Serialization
+=================
+
+Since the XML layer of SleekXMPP 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 xml.etree import cElementTree as ET
+ >>> xml = ET.fromstring('<foo xmlns="bar"><baz /></foo>')
+ >>> ET.tostring(xml)
+ '<ns0:foo xmlns:ns0="bar"><ns0:baz /></foo>'
+ >>> tostring(xml)
+ '<foo xmlns="bar"><baz /></foo>'
+
+As a side effect of this namespace hiding, using :func:`tostring()` may
+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
+it to the terminal, the ``jabber:client`` namespace will appear.
+
+.. autofunction:: tostring
+
+Escaping Special Characters
+---------------------------
+
+In order to prevent errors when sending arbitrary text as the textual
+content of an XML element, certain characters must be escaped. These
+are: ``&``, ``<``, ``>``, ``"``, and ``'``. The default escaping
+mechanism is to replace those characters with their equivalent escape
+entities: ``&amp;``, ``&lt;``, ``&gt;``, ``&apos;``, and ``&quot;``.
+
+In the future, the use of CDATA sections may be allowed to reduce the
+size of escaped text or for when other XMPP processing agents do not
+undertand these entities.
+
+.. autofunction:: xml_escape
diff --git a/docs/api/xmlstream/xmlstream.rst b/docs/api/xmlstream/xmlstream.rst
new file mode 100644
index 00000000..90a7a6af
--- /dev/null
+++ b/docs/api/xmlstream/xmlstream.rst
@@ -0,0 +1,10 @@
+==========
+XML Stream
+==========
+
+.. module:: sleekxmpp.xmlstream.xmlstream
+
+.. autoexception:: RestartStream
+
+.. autoclass:: XMLStream
+ :members:
diff --git a/docs/architecture.rst b/docs/architecture.rst
index 53c326e1..a2e0a27d 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 <stream handler>`.
-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 <stream handler>`. 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 <stream handler>`,
- these functions are referred to as :term:`event handlers <event handler>`.
- Each stanza/handler pair is then put into the event queue.
+ handler registered for the event. In contrast to :term:`stream handlers
+ <stream handler>`, these functions are referred to as :term:`event
+ handlers <event handler>`. 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 <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.
+: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/conf.py b/docs/conf.py
index 8a165872..dd83f243 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -16,7 +16,7 @@ import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath('..'))
# -- General configuration -----------------------------------------------------
@@ -25,7 +25,7 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -50,7 +50,7 @@ copyright = u'2011, Nathan Fritz, Lance Stout'
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
-release = '1.0RC1'
+release = '1.0RC3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -81,7 +81,7 @@ exclude_patterns = ['_build']
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'default'
+pygments_style = 'tango'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
@@ -91,7 +91,7 @@ pygments_style = 'default'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'haiku'
+html_theme = 'nature'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -218,3 +218,5 @@ man_pages = [
('index', 'sleekxmpp', u'SleekXMPP Documentation',
[u'Nathan Fritz, Lance Stout'], 1)
]
+
+intersphinx_mapping = {'python': ('http://docs.python.org/3.2', 'python-objects.inv')}
diff --git a/docs/create_plugin.rst b/docs/create_plugin.rst
index 112ef505..12efa84c 100644
--- a/docs/create_plugin.rst
+++ b/docs/create_plugin.rst
@@ -1,3 +1,5 @@
+.. _create-plugin:
+
Creating a SleekXMPP Plugin
===========================
diff --git a/docs/getting_started/component.rst b/docs/getting_started/component.rst
index ca9ec066..ce548ba4 100644
--- a/docs/getting_started/component.rst
+++ b/docs/getting_started/component.rst
@@ -1,2 +1,75 @@
+.. _echocomponent:
+
+=================================
Create and Run a Server Component
=================================
+
+.. note::
+
+ If you have any issues working through this quickstart guide
+ or the other tutorials here, please either send a message to the
+ `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
+ or join the chat room at `sleek@conference.jabber.org
+ <xmpp:sleek@conference.jabber.org?join>`_.
+
+If you have not yet installed SleekXMPP, do so now by either checking out a version
+from `Github <http://github.com/fritzy/SleekXMPP>`_, or installing it using ``pip``
+or ``easy_install``.
+
+.. code-block:: sh
+
+ pip install sleekxmpp # Or: easy_install sleekxmpp
+
+
+Many XMPP applications eventually graduate to requiring to run as a server
+component in order to meet scalability requirements. To demonstrate how to
+turn an XMPP client bot into a component, we'll turn the echobot example
+(:ref:`echobot`) into a component version.
+
+The first difference is that we will add an additional import statement:
+
+.. code-block:: python
+
+ from sleekxmpp.componentxmpp import ComponentXMPP
+
+Likewise, we will change the bot's class definition to match:
+
+.. code-block:: python
+
+ class EchoComponent(ComponentXMPP):
+
+ def __init__(self, jid, secret, server, port):
+ ComponentXMPP.__init__(self, jid, secret, server, port)
+
+A component instance requires two extra parameters compared to a client
+instance: ``server`` and ``port``. These specifiy the name and port of
+the XMPP server that will be accepting the component. For example, for
+a MUC component, the following could be used:
+
+.. code-block:: python
+
+ muc = ComponentXMPP('muc.sleekxmpp.com', '******', 'sleekxmpp.com', 5555)
+
+.. note::
+
+ The ``server`` value is **NOT** derived from the provided JID for the
+ component, unlike with client connections.
+
+One difference with the component version is that we do not have
+to handle the :term:`session_start` event if we don't wish to deal
+with presence.
+
+The other, main difference with components is that the
+``'from'`` value for every stanza must be explicitly set, since
+components may send stanzas from multiple JIDs. To do so,
+the :meth:`~sleekxmpp.basexmpp.BaseXMPP.send_message()` and
+:meth:`~sleekxmpp.basexmpp.BaseXMPP.send_presence()` accept the parameters
+``mfrom`` and ``pfrom``, respectively. For any method that uses
+:class:`~sleekxmpp.stanza.iq.Iq` stanzas, ``ifrom`` may be used.
+
+
+Final Product
+-------------
+
+.. include:: ../../examples/echo_component.py
+ :literal:
diff --git a/docs/getting_started/iq.rst b/docs/getting_started/iq.rst
index 7ac1508c..98e0bdaf 100644
--- a/docs/getting_started/iq.rst
+++ b/docs/getting_started/iq.rst
@@ -1,2 +1,182 @@
Send/Receive IQ Stanzas
=======================
+
+Unlike :class:`~sleekxmpp.stanza.message.Message` and
+:class:`~sleekxmpp.stanza.presence.Presence` stanzas which only use
+text data for basic usage, :class:`~sleekxmpp.stanza.iq.Iq` stanzas
+require using XML payloads, and generally entail creating a new
+SleekXMPP plugin to provide the necessary convenience methods to
+make working with them easier.
+
+Basic Use
+---------
+
+XMPP's use of :class:`~sleekxmpp.stanza.iq.Iq` stanzas is built around
+namespaced ``<query />`` elements. For clients, just sending the
+empty ``<query />`` element will suffice for retrieving information. For
+example, a very basic implementation of service discovery would just
+need to be able to send:
+
+.. code-block:: xml
+
+ <iq to="user@example.com" type="get" id="1">
+ <query xmlns="http://jabber.org/protocol/disco#info" />
+ </iq>
+
+Creating Iq Stanzas
+~~~~~~~~~~~~~~~~~~~
+
+SleekXMPP provides built-in support for creating basic :class:`~sleekxmpp.stanza.iq.Iq`
+stanzas this way. The relevant methods are:
+
+* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq`
+* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_get`
+* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_set`
+* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_result`
+* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_error`
+* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_query`
+
+These methods all follow the same pattern: create or modify an existing
+:class:`~sleekxmpp.stanza.iq.Iq` stanza, set the ``'type'`` value based
+on the method name, and finally add a ``<query />`` element with the given
+namespace. For example, to produce the query above, you would use:
+
+.. code-block:: python
+
+ self.make_iq_get(queryxmlns='http://jabber.org/protocol/disco#info',
+ ito='user@example.com')
+
+
+Sending Iq Stanzas
+~~~~~~~~~~~~~~~~~~
+
+Once an :class:`~sleekxmpp.stanza.iq.Iq` stanza is created, sending it
+over the wire is done using its :meth:`~sleekxmpp.stanza.iq.Iq.send()`
+method, like any other stanza object. However, there are a few extra
+options to control how to wait for the query's response.
+
+These options are:
+
+* ``block``: The default behaviour is that :meth:`~sleekxmpp.stanza.iq.Iq.send()`
+ will block until a response is received and the response stanza will be the
+ return value. Setting ``block`` to ``False`` will cause the call to return
+ immediately. In which case, you will need to arrange some way to capture
+ the response stanza if you need it.
+
+* ``timeout``: When using the blocking behaviour, the call will eventually
+ timeout with an error. The default timeout is 30 seconds, but this may
+ be overidden two ways. To change the timeout globally, set:
+
+ .. code-block:: python
+
+ self.response_timeout = 10
+
+ To change the timeout for a single call, the ``timeout`` parameter works:
+
+ .. code-block:: python
+
+ iq.send(timeout=60)
+
+* ``callback``: When not using a blocking call, using the ``callback``
+ argument is a simple way to register a handler that will execute
+ whenever a response is finally received. Using this method, there
+ is no timeout limit. In case you need to remove the callback, the
+ name of the newly created callback is returned.
+
+ .. code-block:: python
+
+ cb_name = iq.send(callback=self.a_callback)
+
+ # ... later if we need to cancel
+ self.remove_handler(cb_name)
+
+Properly working with :class:`~sleekxmpp.stanza.iq.Iq` stanzas requires
+handling the intended, normal flow, error responses, and timed out
+requests. To make this easier, two exceptions may be thrown by
+:meth:`~sleekxmpp.stanza.iq.Iq.send()`: :exc:`~sleekxmpp.exceptions.IqError`
+and :exc:`~sleekxmpp.exceptions.IqTimeout`. These exceptions only
+apply to the default, blocking calls.
+
+.. code-block:: python
+
+ try:
+ resp = iq.send()
+ # ... do stuff with expected Iq result
+ except IqError as e:
+ err_resp = e.iq
+ # ... handle error case
+ except IqTimeout:
+ # ... no response received in time
+ pass
+
+If you do not care to distinguish between errors and timeouts, then you
+can combine both cases with a generic :exc:`~sleekxmpp.exceptions.XMPPError`
+exception:
+
+.. code-block:: python
+
+ try:
+ resp = iq.send()
+ except XMPPError:
+ # ... Don't care about the response
+ pass
+
+Advanced Use
+------------
+
+Going beyond the basics provided by SleekXMPP requires building at least a
+rudimentary SleekXMPP plugin to create a :term:`stanza object` for
+interfacting with the :class:`~sleekxmpp.stanza.iq.Iq` payload.
+
+.. seealso::
+
+ * :ref:`create-plugin`
+ * :ref:`work-with-stanzas`
+ * :ref:`using-handlers-matchers`
+
+
+The typical way to respond to :class:`~sleekxmpp.stanza.iq.Iq` requests is
+to register stream handlers. As an example, suppose we create a stanza class
+named ``CustomXEP`` which uses the XML element ``<query xmlns="custom-xep" />``,
+and has a :attr:`~sleekxmpp.xmlstream.stanzabase.ElementBase.plugin_attrib` value
+of ``custom_xep``.
+
+There are two types of incoming :class:`~sleekxmpp.stanza.iq.Iq` requests:
+``get`` and ``set``. You can register a handler that will accept both and then
+filter by type as needed, as so:
+
+.. code-block:: python
+
+ self.register_handler(Callback(
+ 'CustomXEP Handler',
+ StanzaPath('iq/custom_xep'),
+ self._handle_custom_iq))
+
+ # ...
+
+ def _handle_custom_iq(self, iq):
+ if iq['type'] == 'get':
+ # ...
+ pass
+ elif iq['type'] == 'set':
+ # ...
+ pass
+ else:
+ # ... This will capture error responses too
+ pass
+
+If you want to filter out query types beforehand, you can adjust the matching
+filter by using ``@type=get`` or ``@type=set`` if you are using the recommended
+:class:`~sleekxmpp.xmlstream.matcher.stanzapath.StanzaPath` matcher.
+
+.. code-block:: python
+
+ self.register_handler(Callback(
+ 'CustomXEP Handler',
+ StanzaPath('iq@type=get/custom_xep'),
+ self._handle_custom_iq_get))
+
+ # ...
+
+ def _handle_custom_iq_get(self, iq):
+ assert(iq['type'] == 'get')
diff --git a/docs/getting_started/proxy.rst b/docs/getting_started/proxy.rst
index 02ad10ae..60d521c5 100644
--- a/docs/getting_started/proxy.rst
+++ b/docs/getting_started/proxy.rst
@@ -1,2 +1,42 @@
+.. _proxy:
+
+=========================
Enable HTTP Proxy Support
=========================
+
+.. note::
+
+ If you have any issues working through this quickstart guide
+ or the other tutorials here, please either send a message to the
+ `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
+ or join the chat room at `sleek@conference.jabber.org
+ <xmpp:sleek@conference.jabber.org?join>`_.
+
+In some instances, you may wish to route XMPP traffic through
+an HTTP proxy, probably to get around restrictive firewalls.
+SleekXMPP provides support for basic HTTP proxying with DIGEST
+authentication.
+
+Enabling proxy support is done in two steps. The first is to instruct SleekXMPP
+to use a proxy, and the second is to configure the proxy details:
+
+.. code-block:: python
+
+ xmpp = ClientXMPP(...)
+ xmpp.use_proxy = True
+ xmpp.proxy_config = {
+ 'host': 'proxy.example.com',
+ 'port': 5555,
+ 'username': 'example_user',
+ 'password': '******'
+ }
+
+The ``'username'`` and ``'password'`` fields are optional if the proxy does not
+require authentication.
+
+
+The Final Product
+-----------------
+
+.. include:: ../../examples/proxy_echo_client.py
+ :literal:
diff --git a/docs/handlersmatchers.rst b/docs/handlersmatchers.rst
index 7ac750c0..628c4142 100644
--- a/docs/handlersmatchers.rst
+++ b/docs/handlersmatchers.rst
@@ -1,2 +1,4 @@
+.. _using-handlers-matchers:
+
Using Stream Handlers and Matchers
==================================
diff --git a/docs/howto/stanzas.rst b/docs/howto/stanzas.rst
new file mode 100644
index 00000000..d52a90d4
--- /dev/null
+++ b/docs/howto/stanzas.rst
@@ -0,0 +1,30 @@
+.. _work-with-stanzas:
+
+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
+--------------------------
diff --git a/docs/index.rst b/docs/index.rst
index 5da389b9..fc6541d6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -12,13 +12,8 @@ SleekXMPP
``master`` branch, while the latest development version is in the
``develop`` branch.
- **Stable Releases**
- - `1.0 Beta6.1 <http://github.com/fritzy/SleekXMPP/zipball/1.0-Beta6.1>`_
- - `1.0 Beta5 <http://github.com/fritzy/SleekXMPP/zipball/1.0-Beta5>`_
- - `1.0 Beta4 <http://github.com/fritzy/SleekXMPP/zipball/1.0-Beta4>`_
- - `1.0 Beta3 <http://github.com/fritzy/SleekXMPP/zipball/1.0-Beta3>`_
- - `1.0 Beta2 <http://github.com/fritzy/SleekXMPP/zipball/1.0-Beta2>`_
- - `1.0 Beta1 <http://github.com/fritzy/SleekXMPP/zipball/1.0-Beta1>`_
+ **Latest Stable Release**
+ - `1.0 RC3 <http://github.com/fritzy/SleekXMPP/zipball/1.0-RC3>`_
**Develop Releases**
- `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
@@ -84,8 +79,10 @@ Tutorials, FAQs, and How To Guides
.. toctree::
:maxdepth: 1
+ faq
xeps
xmpp_tdg
+ howto/stanzas
create_plugin
features
sasl
@@ -113,8 +110,35 @@ API Reference
event_index
api/clientxmpp
+ api/componentxmpp
api/basexmpp
- api/xmlstream
+ api/exceptions
+ api/xmlstream/jid
+ api/xmlstream/stanzabase
+ api/xmlstream/handler
+ api/xmlstream/matcher
+ api/xmlstream/xmlstream
+ api/xmlstream/scheduler
+ api/xmlstream/tostring
+ api/xmlstream/filesocket
+
+Core Stanzas
+~~~~~~~~~~~~
+.. toctree::
+ :maxdepth: 2
+
+ api/stanza/rootstanza
+ api/stanza/message
+ api/stanza/presence
+ api/stanza/iq
+ api/stanza/error
+ api/stanza/stream_error
+
+Plugins
+~~~~~~~
+.. toctree::
+ :maxdepth: 2
+
Additional Info
---------------
diff --git a/docs/python-objects.inv b/docs/python-objects.inv
new file mode 100644
index 00000000..b7afc07e
--- /dev/null
+++ b/docs/python-objects.inv
Binary files differ
diff --git a/docs/xeps.rst b/docs/xeps.rst
index a541a586..3653d10a 100644
--- a/docs/xeps.rst
+++ b/docs/xeps.rst
@@ -1,2 +1,50 @@
Supported XEPS
==============
+
+======= ============================= ================
+XEP Description Notes
+======= ============================= ================
+`0004`_ Data forms
+`0009`_ Jabber RPC
+`0012`_ Last Activity
+`0030`_ Service Discovery
+`0033`_ Extended Stanza Addressing
+`0045`_ Multi-User Chat (MUC) Client-side only
+`0050`_ Ad-hoc Commands
+`0059`_ Result Set Management
+`0060`_ Publish/Subscribe (PubSub) Client-side only
+`0066`_ Out-of-band Data
+`0078`_ Non-SASL Authentication
+`0082`_ XMPP Date and Time Profiles
+`0085`_ Chat-State Notifications
+`0086`_ Error Condition Mappings
+`0092`_ Software Version
+`0128`_ Service Discovery Extensions
+`0202`_ Entity Time
+`0203`_ Delayed Delivery
+`0224`_ Attention
+`0249`_ Direct MUC Invitations
+======= ============================= ================
+
+
+.. _0004: http://xmpp.org/extensions/xep-0004.html
+.. _0009: http://xmpp.org/extensions/xep-0009.html
+.. _0012: http://xmpp.org/extensions/xep-0012.html
+.. _0030: http://xmpp.org/extensions/xep-0030.html
+.. _0033: http://xmpp.org/extensions/xep-0033.html
+.. _0045: http://xmpp.org/extensions/xep-0045.html
+.. _0050: http://xmpp.org/extensions/xep-0050.html
+.. _0059: http://xmpp.org/extensions/xep-0059.html
+.. _0060: http://xmpp.org/extensions/xep-0060.html
+.. _0066: http://xmpp.org/extensions/xep-0066.html
+.. _0078: http://xmpp.org/extensions/xep-0078.html
+.. _0082: http://xmpp.org/extensions/xep-0082.html
+.. _0085: http://xmpp.org/extensions/xep-0085.html
+.. _0086: http://xmpp.org/extensions/xep-0086.html
+.. _0092: http://xmpp.org/extensions/xep-0092.html
+.. _0128: http://xmpp.org/extensions/xep-0128.html
+.. _0199: http://xmpp.org/extensions/xep-0199.html
+.. _0202: http://xmpp.org/extensions/xep-0202.html
+.. _0203: http://xmpp.org/extensions/xep-0203.html
+.. _0224: http://xmpp.org/extensions/xep-0224.html
+.. _0249: http://xmpp.org/extensions/xep-0249.html