Merge branch 'doc-stanza' into 'master'

Fill the stanza howto

See merge request poezio/slixmpp!122
This commit is contained in:
mathieui 2021-02-06 17:59:53 +01:00
commit b9e479f213
4 changed files with 701 additions and 239 deletions

View file

@ -3,28 +3,411 @@
How to Work with Stanza Objects
===============================
Slixmpp provides a large variety of facilities for abstracting the underlying
XML payloads of XMPP. Most of the visible user interface comes in a
dict-like interface provided in a specific ``__getitem__`` implementation
for :class:`~slixmpp.xmlstream.ElementBase` objects.
As a very high-level example, here is how to create a stanza with
an XEP-0191 payload, assuming the :class:`xep_0191 <slixmpp.plugins.xep_0191.XEP_0191>`
plugin is loaded:
.. code-block:: python
from slixmpp.stanza import Iq
iq = Iq()
iq['to'] = 'toto@example.com'
iq['type'] = 'set'
iq['block']['items'] = {'a@example.com', 'b@example.com'}
Printing the resulting :class:`~slixmpp.stanaz.Iq` object gives us the
following XML (reformatted for readability):
.. code-block:: xml
<iq xmlns="jabber:client" id="0" to="toto@example.com" type="set">
<block xmlns="urn:xmpp:blocking">
<item jid="b@example.com" />
<item jid="a@example.com" />
</block>
</iq>
Realistically, users of the Slixmpp library should make use of the shorthand
functions available in their :class:`~.ClientXMPP` or
:class:`~.ComponentXMPP` objects to create :class:`~.Iq`, :class:`~.Message`
or :class:`~.Presence` objects that are bound to a stream, and which have
a generated unique identifier.
The most relevant functions are:
.. autofunction:: slixmpp.BaseXMPP.make_iq_get
.. autofunction:: slixmpp.BaseXMPP.make_iq_set
.. autofunction:: slixmpp.BaseXMPP.make_message
.. autofunction:: slixmpp.BaseXMPP.make_presence
The previous example then becomes:
.. code-block:: python
iq = xmpp.make_iq_get(ito='toto@example.com')
iq['block']['items'] = {'a@example.com', 'b@example.com'}
.. note::
xml:lang is handled by piping the lang name after the attribute. For
example ``message['body|fr']`` will return the ``<body/>`` attribute
with ``xml:lang="fr``.
The next sections will try to explain as clearly as possible
how the magic operates.
.. _create-stanza-interfaces:
Defining Stanza Interfaces
--------------------------
The stanza interface is very rich and let developers have full control
over the API they want to have to manipulate stanzas.
The entire interface is defined as class attributes that are redefined
when subclassing :class:`~.ElementBase` when `creating a stanza plugin <create-stanza-plugins>`_.
The main attributes defining a stanza interface:
- plugin_attrib_: ``str``, the name of this element on the parent
- plugin_multi_attrib_: ``str``, the name of the iterable for this element on the parent
- interfaces_: ``set``, all known interfaces for this element
- sub_interfaces_: ``set`` (subset of ``interfaces``), for sub-elements with only text nodes
- bool_interfaces_: ``set`` (subset of ``interfaces``), for empty-sub-elements
- overrides_: ``list`` (subset of ``interfaces``), for ``interfaces`` to ovverride on the parent
- is_extension_: ``bool``, if the element is only an extension of the parent stanza
.. _plugin_attrib:
plugin_attrib
~~~~~~~~~~~~~
The ``plugin_attrib`` string is the defining element of any stanza plugin,
as it the name through which the element is accessed (except for ``overrides``
and ``is_extension``).
The extension is then registered through the help of :func:`~.register_stanza_plugin`
which will attach the plugin to its parent.
.. code-block:: python
from slixmpp import ElementBase, Iq
class Payload(ElementBase):
name = 'apayload'
plugin_attrib = 'mypayload'
namespace = 'x-toto'
register_stanza_plugin(Iq, Payload)
iq = Iq()
iq.enable('mypayload') # Similar to iq['mypayload']
The :class:`~.Iq` element created now contains our custom ``<apayload/>`` element.
.. code-block:: xml
<iq xmlns="jabber:client" id="0">
<apayload xmlns="x-toto"/>
</iq>
.. _plugin_multi_attrib:
plugin_multi_attrib
~~~~~~~~~~~~~~~~~~~
The :func:`~.register_stanza_plugin` function has an ``iterable`` parameter, which
defaults to ``False``. When set to ``True``, it means that iterating over the element
is possible.
.. code-block:: python
class Parent(ElementBase):
pass # does not matter
class Sub(ElementBase):
name = 'sub'
plugin_attrib = 'sub'
class Sub2(ElementBase):
name = 'sub2'
plugin_attrib = 'sub2'
register_stanza_plugin(Parent, Sub, iterable=True)
register_stanza_plugin(Parent, Sub2, iterable=True)
parent = Parent()
parent.append(Sub())
parent.append(Sub2())
parent.append(Sub2())
parent.append(Sub())
for element in parent:
do_something # A mix of Sub and Sub2 elements
In this situation, iterating over ``parent`` will yield each of the appended elements,
one after the other.
Sometimes you only want one specific type of sub-element, which is the use of
the ``plugin_multi_attrib`` string interface. This name will be mapped on the
parent, just like ``plugin_attrib``, but will return a list of all elements
of the same type only.
Re-using our previous example:
.. code-block:: python
class Parent(ElementBase):
pass # does not matter
class Sub(ElementBase):
name = 'sub'
plugin_attrib = 'sub'
plugin_multi_attrib = 'subs'
class Sub2(ElementBase):
name = 'sub2'
plugin_attrib = 'sub2'
plugin_multi_attrib = 'subs2'
register_stanza_plugin(Parent, Sub, iterable=True)
register_stanza_plugin(Parent, Sub2, iterable=True)
parent = Parent()
parent.append(Sub())
parent.append(Sub2())
parent.append(Sub2())
parent.append(Sub())
for sub in parent['subs']:
do_something # ony Sub objects here
for sub2 in parent['subs2']:
do_something # ony Sub2 objects here
.. _interfaces:
interfaces
~~~~~~~~~~
The ``interfaces`` set **must** contain all the known ways to interact with
this element. It does not include plugins (registered to the element through
:func:`~.register_stanza_plugin`), which are dynamic.
By default, a name present in ``interfaces`` will be mapped to an attribute
of the element with the same name.
.. code-block:: python
class Example(Element):
name = 'example'
interfaces = {'toto'}
example = Example()
example['toto'] = 'titi'
In this case, ``example`` contains ``<example toto="titi"/>``.
For empty and text_only sub-elements, there are sub_interfaces_ and
bool_interfaces_ (the keys **must** still be in ``interfaces``.
You can however define any getter, setter, and delete custom method for any of
those interfaces. Keep in mind that if one of the three is not custom,
Slixmpp will use the default one, so you have to make sure that either you
redefine all get/set/del custom methods, or that your custom methods are
compatible with the default ones.
In the following example, we want the ``toto`` attribute to be an integer.
.. code-block:: python
class Example(Element):
interfaces = {'toto', 'titi', 'tata'}
def get_toto(self) -> Optional[int]:
try:
return int(self.xml.attrib.get('toto', ''))
except ValueError:
return None
def set_toto(self, value: int):
int(value) # make sure the value is an int
self.xml.attrib['toto'] = str(value)
example = Example()
example['tata'] = "Test" # works
example['toto'] = 1 # works
print(type(example['toto'])) # the value is an int
example['toto'] = "Test 2" # ValueError
One important thing to keep in mind is that the ``get_`` methods must be resilient
(when having a default value makes sense) because they are called on objects
received from the network.
.. _sub_interfaces:
sub_interfaces
~~~~~~~~~~~~~~
The ``bool_interfaces`` set allows mapping an interface to the text node of
sub-element of the current payload, with the same namespace
Here is a simple example:
.. code-block:: python
class FirstLevel(ElementBase):
name = 'first'
namespace = 'ns'
interfaces = {'second'}
sub_interfaces = {'second'}
parent = FirstLevel()
parent['second'] = 'Content of second node'
Which will produces the following:
.. code-block:: xml
<first xmlns="ns">
<second>Content of second node</second>
</first>
We can see that ``sub_interfaces`` allows to quickly create a sub-element and
manipulate its text node without requiring a custom element, getter or setter.
.. _bool_interfaces:
bool_interfaces
~~~~~~~~~~~~~~~
The ``bool_interfaces`` set allows mapping an interface to a direct sub-element of the
current payload, with the same namespace.
Here is a simple example:
.. code-block:: python
class FirstLevel(ElementBase):
name = 'first'
namespace = 'ns'
interfaces = {'second'}
bool_interfaces = {'second'}
parent = FirstLevel()
parent['second'] = True
Which will produces the following:
.. code-block:: xml
<first xmlns="ns">
<second/>
</first>
We can see that ``bool_interfaces`` allows to quickly create sub-elements with no
content, without the need to create a custom class or getter/setter.
overrides
~~~~~~~~~
List of ``interfaces`` on the present element that should override the
parent ``interfaces`` with the same name.
.. code-block:: python
class Parent(ElementBase):
name = 'parent'
interfaces = {'toto', 'titi'}
class Sub(ElementBase):
name = 'sub'
plugin_attrib = name
interfaces = {'toto', 'titi'}
overrides = ['toto']
register_stanza_plugin(Parent, Sub)
parent = Parent()
parent['toto'] = 'test' # equivalent to parent['sub']['toto'] = "test"
is_extension
~~~~~~~~~~~~
Stanza extensions are a specific kind of stanza plugin which have
the ``is_extension`` class attribute set to ``True``.
The following code will directly plug the extension into the
:class:`~.Message` element, allowing direct access
to the interface:
.. code-block:: python
class MyCustomExtension(ElementBase):
is_extension = True
name = 'mycustom'
namespace = 'custom-ns'
plugin_attrib = 'mycustom'
interfaces = {'mycustom'}
register_stanza_plugin(Message, MyCustomExtension)
With this extension, we can do the folliowing:
.. code-block:: python
message = Message()
message['mycustom'] = 'toto'
Without the extension, obtaining the same results would be:
.. code-block:: python
message = Message()
message['mycustom']['mycustom'] = 'toto'
The extension is therefore named extension because it extends the
parent element transparently.
.. _create-stanza-plugins:
Creating Stanza Plugins
-----------------------
A stanza plugin is a class that inherits from :class:`~.ElementBase`, and
**must** contain at least the following attributes:
- name: XML element name (e.g. ``toto`` if the element is ``<toto/>``
- namespace: The XML namespace of the element.
- plugin_attrib_: ``str``, the name of this element on the parent
- interfaces_: ``set``, all known interfaces for this element
.. _create-extension-plugins:
It is then registered through :func:`~.register_stanza_plugin` on the parent
element.
Creating a Stanza Extension
---------------------------
.. note::
.. _override-parent-interfaces:
Overriding a Parent Stanza
--------------------------
:func:`~.register_stanza_plugin` should NOT be called at the module level,
because it executes code, and executing code at the module level can slow
down import significantly!

View file

@ -11,6 +11,9 @@ import asyncio
import logging
from typing import (
Dict,
Optional,
Union,
TYPE_CHECKING,
)
@ -18,14 +21,22 @@ from slixmpp import plugins, roster, stanza
from slixmpp.api import APIRegistry
from slixmpp.exceptions import IqError, IqTimeout
from slixmpp.stanza import Message, Presence, Iq, StreamError
from slixmpp.stanza import (
Message,
Presence,
Iq,
StreamError,
)
from slixmpp.stanza.roster import Roster
from slixmpp.xmlstream import XMLStream, JID
from slixmpp.xmlstream import ET, register_stanza_plugin
from slixmpp.xmlstream.matcher import MatchXPath
from slixmpp.xmlstream.handler import Callback
from slixmpp.xmlstream.stanzabase import XML_NS
from slixmpp.xmlstream.stanzabase import (
ElementBase,
XML_NS,
)
from slixmpp.plugins import PluginManager, load_plugin
@ -33,8 +44,16 @@ from slixmpp.plugins import PluginManager, load_plugin
log = logging.getLogger(__name__)
from slixmpp.types import (
PresenceShows,
PresenceTypes,
MessageTypes,
IqTypes,
)
if TYPE_CHECKING:
from slixmpp.types import PluginsDict
# Circular imports
from slixmpp.pluginsdict import PluginsDict
class BaseXMPP(XMLStream):
@ -229,7 +248,7 @@ class BaseXMPP(XMLStream):
self.plugin[name].post_init()
self.plugin[name].post_inited = True
def register_plugin(self, plugin, pconfig=None, module=None):
def register_plugin(self, plugin: str, pconfig: Optional[Dict] = None, module=None):
"""Register and configure a plugin for use in this stream.
:param plugin: The name of the plugin class. Plugin names must
@ -279,32 +298,34 @@ class BaseXMPP(XMLStream):
"""Return a plugin given its name, if it has been registered."""
return self.plugin.get(key, default)
def Message(self, *args, **kwargs):
def Message(self, *args, **kwargs) -> Message:
"""Create a Message stanza associated with this stream."""
msg = Message(self, *args, **kwargs)
msg['lang'] = self.default_lang
return msg
def Iq(self, *args, **kwargs):
def Iq(self, *args, **kwargs) -> Iq:
"""Create an Iq stanza associated with this stream."""
return Iq(self, *args, **kwargs)
def Presence(self, *args, **kwargs):
def Presence(self, *args, **kwargs) -> Presence:
"""Create a Presence stanza associated with this stream."""
pres = Presence(self, *args, **kwargs)
pres['lang'] = self.default_lang
return pres
def make_iq(self, id=0, ifrom=None, ito=None, itype=None, iquery=None):
"""Create a new Iq stanza with a given Id and from JID.
def make_iq(self, id: str = "0", ifrom: Optional[JID] = None,
ito: Optional[JID] = None, itype: Optional[IqTypes] = None,
iquery: Optional[str] = None) -> Iq:
"""Create a new :class:`~.Iq` stanza with a given Id and from JID.
:param id: An ideally unique ID value for this stanza thread.
Defaults to 0.
:param ifrom: The from :class:`~slixmpp.xmlstream.jid.JID`
:param ifrom: The from :class:`~.JID`
to use for this stanza.
:param ito: The destination :class:`~slixmpp.xmlstream.jid.JID`
:param ito: The destination :class:`~.JID`
for this stanza.
:param itype: The :class:`~slixmpp.stanza.iq.Iq`'s type,
:param itype: The :class:`~.Iq`'s type,
one of: ``'get'``, ``'set'``, ``'result'``,
or ``'error'``.
:param iquery: Optional namespace for adding a query element.
@ -317,15 +338,17 @@ class BaseXMPP(XMLStream):
iq['query'] = iquery
return iq
def make_iq_get(self, queryxmlns=None, ito=None, ifrom=None, iq=None):
"""Create an :class:`~slixmpp.stanza.iq.Iq` stanza of type ``'get'``.
def make_iq_get(self, queryxmlns: Optional[str] =None,
ito: Optional[JID] = None, ifrom: Optional[JID] = None,
iq: Optional[Iq] = None) -> Iq:
"""Create an :class:`~.Iq` stanza of type ``'get'``.
Optionally, a query element may be added.
:param queryxmlns: The namespace of the query to use.
:param ito: The destination :class:`~slixmpp.xmlstream.jid.JID`
:param ito: The destination :class:`~.JID`
for this stanza.
:param ifrom: The ``'from'`` :class:`~slixmpp.xmlstream.jid.JID`
:param ifrom: The ``'from'`` :class:`~.JID`
to use for this stanza.
:param iq: Optionally use an existing stanza instead
of generating a new one.
@ -340,15 +363,17 @@ class BaseXMPP(XMLStream):
iq['from'] = ifrom
return iq
def make_iq_result(self, id=None, ito=None, ifrom=None, iq=None):
def make_iq_result(self, id: Optional[str] = None,
ito: Optional[JID] = None, ifrom: Optional[JID] = None,
iq: Optional[Iq] = None) -> Iq:
"""
Create an :class:`~slixmpp.stanza.iq.Iq` stanza of type
Create an :class:`~.Iq` stanza of type
``'result'`` with the given ID value.
:param id: An ideally unique ID value. May use :meth:`new_id()`.
:param ito: The destination :class:`~slixmpp.xmlstream.jid.JID`
:param ito: The destination :class:`~.JID`
for this stanza.
:param ifrom: The ``'from'`` :class:`~slixmpp.xmlstream.jid.JID`
:param ifrom: The ``'from'`` :class:`~.JID`
to use for this stanza.
:param iq: Optionally use an existing stanza instead
of generating a new one.
@ -365,21 +390,23 @@ class BaseXMPP(XMLStream):
iq['from'] = ifrom
return iq
def make_iq_set(self, sub=None, ito=None, ifrom=None, iq=None):
def make_iq_set(self, sub: Optional[Union[ElementBase, ET.Element]] = None,
ito: Optional[JID] = None, ifrom: Optional[JID] = None,
iq: Optional[Iq] = None) -> Iq:
"""
Create an :class:`~slixmpp.stanza.iq.Iq` stanza of type ``'set'``.
Create an :class:`~.Iq` stanza of type ``'set'``.
Optionally, a substanza may be given to use as the
stanza's payload.
:param sub: Either an
:class:`~slixmpp.xmlstream.stanzabase.ElementBase`
:class:`~.ElementBase`
stanza object or an
:class:`~xml.etree.ElementTree.Element` XML object
to use as the :class:`~slixmpp.stanza.iq.Iq`'s payload.
:param ito: The destination :class:`~slixmpp.xmlstream.jid.JID`
to use as the :class:`~.Iq`'s payload.
:param ito: The destination :class:`~.JID`
for this stanza.
:param ifrom: The ``'from'`` :class:`~slixmpp.xmlstream.jid.JID`
:param ifrom: The ``'from'`` :class:`~.JID`
to use for this stanza.
:param iq: Optionally use an existing stanza instead
of generating a new one.
@ -399,7 +426,7 @@ class BaseXMPP(XMLStream):
condition='feature-not-implemented',
text=None, ito=None, ifrom=None, iq=None):
"""
Create an :class:`~slixmpp.stanza.iq.Iq` stanza of type ``'error'``.
Create an :class:`~.Iq` stanza of type ``'error'``.
:param id: An ideally unique ID value. May use :meth:`new_id()`.
:param type: The type of the error, such as ``'cancel'`` or
@ -407,9 +434,9 @@ class BaseXMPP(XMLStream):
:param condition: The error condition. Defaults to
``'feature-not-implemented'``.
:param text: A message describing the cause of the error.
:param ito: The destination :class:`~slixmpp.xmlstream.jid.JID`
:param ito: The destination :class:`~.JID`
for this stanza.
:param ifrom: The ``'from'`` :class:`~slixmpp.xmlstream.jid.JID`
:param ifrom: The ``'from'`` :class:`~jid.JID`
to use for this stanza.
:param iq: Optionally use an existing stanza instead
of generating a new one.
@ -426,17 +453,19 @@ class BaseXMPP(XMLStream):
iq['from'] = ifrom
return iq
def make_iq_query(self, iq=None, xmlns='', ito=None, ifrom=None):
def make_iq_query(self, iq: Optional[Iq] = None, xmlns: str = '',
ito: Optional[JID] = None,
ifrom: Optional[JID] = None) -> Iq:
"""
Create or modify an :class:`~slixmpp.stanza.iq.Iq` stanza
Create or modify an :class:`~.Iq` stanza
to use the given query namespace.
:param iq: Optionally use an existing stanza instead
of generating a new one.
:param xmlns: The query's namespace.
:param ito: The destination :class:`~slixmpp.xmlstream.jid.JID`
:param ito: The destination :class:`~.JID`
for this stanza.
:param ifrom: The ``'from'`` :class:`~slixmpp.xmlstream.jid.JID`
:param ifrom: The ``'from'`` :class:`~.JID`
to use for this stanza.
"""
if not iq:
@ -448,7 +477,7 @@ class BaseXMPP(XMLStream):
iq['from'] = ifrom
return iq
def make_query_roster(self, iq=None):
def make_query_roster(self, iq: Optional[Iq] = None) -> ET.Element:
"""Create a roster query element.
:param iq: Optionally use an existing stanza instead
@ -458,11 +487,14 @@ class BaseXMPP(XMLStream):
iq['query'] = 'jabber:iq:roster'
return ET.Element("{jabber:iq:roster}query")
def make_message(self, mto, mbody=None, msubject=None, mtype=None,
mhtml=None, mfrom=None, mnick=None):
def make_message(self, mto: JID, mbody: Optional[str] = None,
msubject: Optional[str] = None,
mtype: Optional[MessageTypes] = None,
mhtml: Optional[str] = None, mfrom: Optional[JID] = None,
mnick: Optional[str] = None) -> Message:
"""
Create and initialize a new
:class:`~slixmpp.stanza.message.Message` stanza.
:class:`~.Message` stanza.
:param mto: The recipient of the message.
:param mbody: The main contents of the message.
@ -484,11 +516,16 @@ class BaseXMPP(XMLStream):
message['html']['body'] = mhtml
return message
def make_presence(self, pshow=None, pstatus=None, ppriority=None,
pto=None, ptype=None, pfrom=None, pnick=None):
def make_presence(self, pshow: Optional[PresenceShows] = None,
pstatus: Optional[str] = None,
ppriority: Optional[int] = None,
pto: Optional[JID] = None,
ptype: Optional[PresenceTypes] = None,
pfrom: Optional[JID] = None,
pnick: Optional[str] = None) -> Presence:
"""
Create and initialize a new
:class:`~slixmpp.stanza.presence.Presence` stanza.
:class:`~.Presence` stanza.
:param pshow: The presence's show value.
:param pstatus: The presence's status message.
@ -508,11 +545,14 @@ class BaseXMPP(XMLStream):
presence['nick'] = pnick
return presence
def send_message(self, mto, mbody, msubject=None, mtype=None,
mhtml=None, mfrom=None, mnick=None):
def send_message(self, mto: JID, mbody: Optional[str] = None,
msubject: Optional[str] = None,
mtype: Optional[MessageTypes] = None,
mhtml: Optional[str] = None, mfrom: Optional[JID] = None,
mnick: Optional[str] = None):
"""
Create, initialize, and send a new
:class:`~slixmpp.stanza.message.Message` stanza.
:class:`~.Message` stanza.
:param mto: The recipient of the message.
:param mbody: The main contents of the message.
@ -528,11 +568,16 @@ class BaseXMPP(XMLStream):
self.make_message(mto, mbody, msubject, mtype,
mhtml, mfrom, mnick).send()
def send_presence(self, pshow=None, pstatus=None, ppriority=None,
pto=None, pfrom=None, ptype=None, pnick=None):
def send_presence(self, pshow: Optional[PresenceShows] = None,
pstatus: Optional[str] = None,
ppriority: Optional[int] = None,
pto: Optional[JID] = None,
ptype: Optional[PresenceTypes] = None,
pfrom: Optional[JID] = None,
pnick: Optional[str] = None):
"""
Create, initialize, and send a new
:class:`~slixmpp.stanza.presence.Presence` stanza.
:class:`~.Presence` stanza.
:param pshow: The presence's show value.
:param pstatus: The presence's status message.
@ -549,7 +594,7 @@ class BaseXMPP(XMLStream):
ptype='subscribe', pnick=None):
"""
Create, initialize, and send a new
:class:`~slixmpp.stanza.presence.Presence` stanza of
:class:`~.Presence` stanza of
type ``'subscribe'``.
:param pto: The recipient of a directed presence.

193
slixmpp/pluginsdict.py Normal file
View file

@ -0,0 +1,193 @@
# Slixmpp: The Slick XMPP Library
# Copyright © 2021 Mathieu Pasquet <mathieui@mathieui.net>
# This file is part of Slixmpp.
# See the file LICENSE for copying permission.
try:
from typing import TypedDict
except ImportError:
from typing_extensions import TypedDict
# Plugins mega-dict
from slixmpp.plugins.xep_0004 import XEP_0004
from slixmpp.plugins.xep_0009 import XEP_0009
from slixmpp.plugins.xep_0012 import XEP_0012
from slixmpp.plugins.xep_0013 import XEP_0013
from slixmpp.plugins.xep_0020 import XEP_0020
from slixmpp.plugins.xep_0027 import XEP_0027
from slixmpp.plugins.xep_0030 import XEP_0030
from slixmpp.plugins.xep_0033 import XEP_0033
from slixmpp.plugins.xep_0045 import XEP_0045
from slixmpp.plugins.xep_0047 import XEP_0047
from slixmpp.plugins.xep_0049 import XEP_0049
from slixmpp.plugins.xep_0050 import XEP_0050
from slixmpp.plugins.xep_0054 import XEP_0054
from slixmpp.plugins.xep_0059 import XEP_0059
from slixmpp.plugins.xep_0060 import XEP_0060
from slixmpp.plugins.xep_0065 import XEP_0065
from slixmpp.plugins.xep_0066 import XEP_0066
from slixmpp.plugins.xep_0070 import XEP_0070
from slixmpp.plugins.xep_0071 import XEP_0071
from slixmpp.plugins.xep_0077 import XEP_0077
from slixmpp.plugins.xep_0079 import XEP_0079
from slixmpp.plugins.xep_0080 import XEP_0080
from slixmpp.plugins.xep_0082 import XEP_0082
from slixmpp.plugins.xep_0084 import XEP_0084
from slixmpp.plugins.xep_0085 import XEP_0085
from slixmpp.plugins.xep_0086 import XEP_0086
from slixmpp.plugins.xep_0092 import XEP_0092
from slixmpp.plugins.xep_0106 import XEP_0106
from slixmpp.plugins.xep_0107 import XEP_0107
from slixmpp.plugins.xep_0108 import XEP_0108
from slixmpp.plugins.xep_0115 import XEP_0115
from slixmpp.plugins.xep_0118 import XEP_0118
from slixmpp.plugins.xep_0122 import XEP_0122
from slixmpp.plugins.xep_0128 import XEP_0128
from slixmpp.plugins.xep_0131 import XEP_0131
from slixmpp.plugins.xep_0133 import XEP_0133
from slixmpp.plugins.xep_0152 import XEP_0152
from slixmpp.plugins.xep_0153 import XEP_0153
from slixmpp.plugins.xep_0163 import XEP_0163
from slixmpp.plugins.xep_0172 import XEP_0172
from slixmpp.plugins.xep_0184 import XEP_0184
from slixmpp.plugins.xep_0186 import XEP_0186
from slixmpp.plugins.xep_0191 import XEP_0191
from slixmpp.plugins.xep_0196 import XEP_0196
from slixmpp.plugins.xep_0198 import XEP_0198
from slixmpp.plugins.xep_0199 import XEP_0199
from slixmpp.plugins.xep_0202 import XEP_0202
from slixmpp.plugins.xep_0203 import XEP_0203
from slixmpp.plugins.xep_0221 import XEP_0221
from slixmpp.plugins.xep_0222 import XEP_0222
from slixmpp.plugins.xep_0223 import XEP_0223
from slixmpp.plugins.xep_0224 import XEP_0224
from slixmpp.plugins.xep_0231 import XEP_0231
from slixmpp.plugins.xep_0235 import XEP_0235
from slixmpp.plugins.xep_0249 import XEP_0249
from slixmpp.plugins.xep_0256 import XEP_0256
from slixmpp.plugins.xep_0257 import XEP_0257
from slixmpp.plugins.xep_0258 import XEP_0258
from slixmpp.plugins.xep_0279 import XEP_0279
from slixmpp.plugins.xep_0280 import XEP_0280
from slixmpp.plugins.xep_0297 import XEP_0297
from slixmpp.plugins.xep_0300 import XEP_0300
from slixmpp.plugins.xep_0308 import XEP_0308
from slixmpp.plugins.xep_0313 import XEP_0313
from slixmpp.plugins.xep_0319 import XEP_0319
from slixmpp.plugins.xep_0332 import XEP_0332
from slixmpp.plugins.xep_0333 import XEP_0333
from slixmpp.plugins.xep_0334 import XEP_0334
from slixmpp.plugins.xep_0335 import XEP_0335
from slixmpp.plugins.xep_0352 import XEP_0352
from slixmpp.plugins.xep_0353 import XEP_0353
from slixmpp.plugins.xep_0359 import XEP_0359
from slixmpp.plugins.xep_0363 import XEP_0363
from slixmpp.plugins.xep_0369 import XEP_0369
from slixmpp.plugins.xep_0377 import XEP_0377
from slixmpp.plugins.xep_0380 import XEP_0380
from slixmpp.plugins.xep_0382 import XEP_0382
from slixmpp.plugins.xep_0394 import XEP_0394
from slixmpp.plugins.xep_0403 import XEP_0403
from slixmpp.plugins.xep_0404 import XEP_0404
from slixmpp.plugins.xep_0405 import XEP_0405
from slixmpp.plugins.xep_0421 import XEP_0421
from slixmpp.plugins.xep_0422 import XEP_0422
from slixmpp.plugins.xep_0424 import XEP_0424
from slixmpp.plugins.xep_0425 import XEP_0425
from slixmpp.plugins.xep_0428 import XEP_0428
from slixmpp.plugins.xep_0437 import XEP_0437
from slixmpp.plugins.xep_0439 import XEP_0439
from slixmpp.plugins.xep_0444 import XEP_0444
class PluginsDict(TypedDict):
xep_0004: XEP_0004
xep_0009: XEP_0009
xep_0012: XEP_0012
xep_0013: XEP_0013
xep_0020: XEP_0020
xep_0027: XEP_0027
xep_0030: XEP_0030
xep_0033: XEP_0033
xep_0045: XEP_0045
xep_0047: XEP_0047
xep_0049: XEP_0049
xep_0050: XEP_0050
xep_0054: XEP_0054
xep_0059: XEP_0059
xep_0060: XEP_0060
xep_0065: XEP_0065
xep_0066: XEP_0066
xep_0070: XEP_0070
xep_0071: XEP_0071
xep_0077: XEP_0077
xep_0079: XEP_0079
xep_0080: XEP_0080
xep_0082: XEP_0082
xep_0084: XEP_0084
xep_0085: XEP_0085
xep_0086: XEP_0086
xep_0092: XEP_0092
xep_0106: XEP_0106
xep_0107: XEP_0107
xep_0108: XEP_0108
xep_0115: XEP_0115
xep_0118: XEP_0118
xep_0122: XEP_0122
xep_0128: XEP_0128
xep_0131: XEP_0131
xep_0133: XEP_0133
xep_0152: XEP_0152
xep_0153: XEP_0153
xep_0163: XEP_0163
xep_0172: XEP_0172
xep_0184: XEP_0184
xep_0186: XEP_0186
xep_0191: XEP_0191
xep_0196: XEP_0196
xep_0198: XEP_0198
xep_0199: XEP_0199
xep_0202: XEP_0202
xep_0203: XEP_0203
xep_0221: XEP_0221
xep_0222: XEP_0222
xep_0223: XEP_0223
xep_0224: XEP_0224
xep_0231: XEP_0231
xep_0235: XEP_0235
xep_0249: XEP_0249
xep_0256: XEP_0256
xep_0257: XEP_0257
xep_0258: XEP_0258
xep_0279: XEP_0279
xep_0280: XEP_0280
xep_0297: XEP_0297
xep_0300: XEP_0300
xep_0308: XEP_0308
xep_0313: XEP_0313
xep_0319: XEP_0319
xep_0332: XEP_0332
xep_0333: XEP_0333
xep_0334: XEP_0334
xep_0335: XEP_0335
xep_0352: XEP_0352
xep_0353: XEP_0353
xep_0359: XEP_0359
xep_0363: XEP_0363
xep_0369: XEP_0369
xep_0377: XEP_0377
xep_0380: XEP_0380
xep_0382: XEP_0382
xep_0394: XEP_0394
xep_0403: XEP_0403
xep_0404: XEP_0404
xep_0405: XEP_0405
xep_0421: XEP_0421
xep_0422: XEP_0422
xep_0424: XEP_0424
xep_0425: XEP_0425
xep_0428: XEP_0428
xep_0437: XEP_0437
xep_0439: XEP_0439
xep_0444: XEP_0444

View file

@ -4,193 +4,34 @@
# See the file LICENSE for copying permission.
"""
This file contains boilerplate to define types relevant to slixmpp,
such as the plugins dict.
This file contains boilerplate to define types relevant to slixmpp.
"""
try:
from typing import TypedDict
from typing import (
Literal,
)
except ImportError:
from typing_extensions import TypedDict
from typing_extensions import (
Literal,
)
from slixmpp.plugins.xep_0004 import XEP_0004
from slixmpp.plugins.xep_0009 import XEP_0009
from slixmpp.plugins.xep_0012 import XEP_0012
from slixmpp.plugins.xep_0013 import XEP_0013
from slixmpp.plugins.xep_0020 import XEP_0020
from slixmpp.plugins.xep_0027 import XEP_0027
from slixmpp.plugins.xep_0030 import XEP_0030
from slixmpp.plugins.xep_0033 import XEP_0033
from slixmpp.plugins.xep_0045 import XEP_0045
from slixmpp.plugins.xep_0047 import XEP_0047
from slixmpp.plugins.xep_0049 import XEP_0049
from slixmpp.plugins.xep_0050 import XEP_0050
from slixmpp.plugins.xep_0054 import XEP_0054
from slixmpp.plugins.xep_0059 import XEP_0059
from slixmpp.plugins.xep_0060 import XEP_0060
from slixmpp.plugins.xep_0065 import XEP_0065
from slixmpp.plugins.xep_0066 import XEP_0066
from slixmpp.plugins.xep_0070 import XEP_0070
from slixmpp.plugins.xep_0071 import XEP_0071
from slixmpp.plugins.xep_0077 import XEP_0077
from slixmpp.plugins.xep_0079 import XEP_0079
from slixmpp.plugins.xep_0080 import XEP_0080
from slixmpp.plugins.xep_0082 import XEP_0082
from slixmpp.plugins.xep_0084 import XEP_0084
from slixmpp.plugins.xep_0085 import XEP_0085
from slixmpp.plugins.xep_0086 import XEP_0086
from slixmpp.plugins.xep_0092 import XEP_0092
from slixmpp.plugins.xep_0106 import XEP_0106
from slixmpp.plugins.xep_0107 import XEP_0107
from slixmpp.plugins.xep_0108 import XEP_0108
from slixmpp.plugins.xep_0115 import XEP_0115
from slixmpp.plugins.xep_0118 import XEP_0118
from slixmpp.plugins.xep_0122 import XEP_0122
from slixmpp.plugins.xep_0128 import XEP_0128
from slixmpp.plugins.xep_0131 import XEP_0131
from slixmpp.plugins.xep_0133 import XEP_0133
from slixmpp.plugins.xep_0152 import XEP_0152
from slixmpp.plugins.xep_0153 import XEP_0153
from slixmpp.plugins.xep_0163 import XEP_0163
from slixmpp.plugins.xep_0172 import XEP_0172
from slixmpp.plugins.xep_0184 import XEP_0184
from slixmpp.plugins.xep_0186 import XEP_0186
from slixmpp.plugins.xep_0191 import XEP_0191
from slixmpp.plugins.xep_0196 import XEP_0196
from slixmpp.plugins.xep_0198 import XEP_0198
from slixmpp.plugins.xep_0199 import XEP_0199
from slixmpp.plugins.xep_0202 import XEP_0202
from slixmpp.plugins.xep_0203 import XEP_0203
from slixmpp.plugins.xep_0221 import XEP_0221
from slixmpp.plugins.xep_0222 import XEP_0222
from slixmpp.plugins.xep_0223 import XEP_0223
from slixmpp.plugins.xep_0224 import XEP_0224
from slixmpp.plugins.xep_0231 import XEP_0231
from slixmpp.plugins.xep_0235 import XEP_0235
from slixmpp.plugins.xep_0249 import XEP_0249
from slixmpp.plugins.xep_0256 import XEP_0256
from slixmpp.plugins.xep_0257 import XEP_0257
from slixmpp.plugins.xep_0258 import XEP_0258
from slixmpp.plugins.xep_0279 import XEP_0279
from slixmpp.plugins.xep_0280 import XEP_0280
from slixmpp.plugins.xep_0297 import XEP_0297
from slixmpp.plugins.xep_0300 import XEP_0300
from slixmpp.plugins.xep_0308 import XEP_0308
from slixmpp.plugins.xep_0313 import XEP_0313
from slixmpp.plugins.xep_0319 import XEP_0319
from slixmpp.plugins.xep_0332 import XEP_0332
from slixmpp.plugins.xep_0333 import XEP_0333
from slixmpp.plugins.xep_0334 import XEP_0334
from slixmpp.plugins.xep_0335 import XEP_0335
from slixmpp.plugins.xep_0352 import XEP_0352
from slixmpp.plugins.xep_0353 import XEP_0353
from slixmpp.plugins.xep_0359 import XEP_0359
from slixmpp.plugins.xep_0363 import XEP_0363
from slixmpp.plugins.xep_0369 import XEP_0369
from slixmpp.plugins.xep_0377 import XEP_0377
from slixmpp.plugins.xep_0380 import XEP_0380
from slixmpp.plugins.xep_0382 import XEP_0382
from slixmpp.plugins.xep_0394 import XEP_0394
from slixmpp.plugins.xep_0403 import XEP_0403
from slixmpp.plugins.xep_0404 import XEP_0404
from slixmpp.plugins.xep_0405 import XEP_0405
from slixmpp.plugins.xep_0421 import XEP_0421
from slixmpp.plugins.xep_0422 import XEP_0422
from slixmpp.plugins.xep_0424 import XEP_0424
from slixmpp.plugins.xep_0425 import XEP_0425
from slixmpp.plugins.xep_0428 import XEP_0428
from slixmpp.plugins.xep_0437 import XEP_0437
from slixmpp.plugins.xep_0439 import XEP_0439
from slixmpp.plugins.xep_0444 import XEP_0444
PresenceTypes = Literal[
'error', 'probe', 'subscribe', 'subscribed',
'unavailable', 'unsubscribe', 'unsubscribed',
]
PresenceShows = Literal[
'away', 'chat', 'dnd', 'xa',
]
class PluginsDict(TypedDict):
xep_0004: XEP_0004
xep_0009: XEP_0009
xep_0012: XEP_0012
xep_0013: XEP_0013
xep_0020: XEP_0020
xep_0027: XEP_0027
xep_0030: XEP_0030
xep_0033: XEP_0033
xep_0045: XEP_0045
xep_0047: XEP_0047
xep_0049: XEP_0049
xep_0050: XEP_0050
xep_0054: XEP_0054
xep_0059: XEP_0059
xep_0060: XEP_0060
xep_0065: XEP_0065
xep_0066: XEP_0066
xep_0070: XEP_0070
xep_0071: XEP_0071
xep_0077: XEP_0077
xep_0079: XEP_0079
xep_0080: XEP_0080
xep_0082: XEP_0082
xep_0084: XEP_0084
xep_0085: XEP_0085
xep_0086: XEP_0086
xep_0092: XEP_0092
xep_0106: XEP_0106
xep_0107: XEP_0107
xep_0108: XEP_0108
xep_0115: XEP_0115
xep_0118: XEP_0118
xep_0122: XEP_0122
xep_0128: XEP_0128
xep_0131: XEP_0131
xep_0133: XEP_0133
xep_0152: XEP_0152
xep_0153: XEP_0153
xep_0163: XEP_0163
xep_0172: XEP_0172
xep_0184: XEP_0184
xep_0186: XEP_0186
xep_0191: XEP_0191
xep_0196: XEP_0196
xep_0198: XEP_0198
xep_0199: XEP_0199
xep_0202: XEP_0202
xep_0203: XEP_0203
xep_0221: XEP_0221
xep_0222: XEP_0222
xep_0223: XEP_0223
xep_0224: XEP_0224
xep_0231: XEP_0231
xep_0235: XEP_0235
xep_0249: XEP_0249
xep_0256: XEP_0256
xep_0257: XEP_0257
xep_0258: XEP_0258
xep_0279: XEP_0279
xep_0280: XEP_0280
xep_0297: XEP_0297
xep_0300: XEP_0300
xep_0308: XEP_0308
xep_0313: XEP_0313
xep_0319: XEP_0319
xep_0332: XEP_0332
xep_0333: XEP_0333
xep_0334: XEP_0334
xep_0335: XEP_0335
xep_0352: XEP_0352
xep_0353: XEP_0353
xep_0359: XEP_0359
xep_0363: XEP_0363
xep_0369: XEP_0369
xep_0377: XEP_0377
xep_0380: XEP_0380
xep_0382: XEP_0382
xep_0394: XEP_0394
xep_0403: XEP_0403
xep_0404: XEP_0404
xep_0405: XEP_0405
xep_0421: XEP_0421
xep_0422: XEP_0422
xep_0424: XEP_0424
xep_0425: XEP_0425
xep_0428: XEP_0428
xep_0437: XEP_0437
xep_0439: XEP_0439
xep_0444: XEP_0444
MessageTypes = Literal[
'chat', 'error', 'groupchat',
'headline', 'normal',
]
IqTypes = Literal[
"error", "get", "set", "result",
]