summaryrefslogtreecommitdiff
path: root/docs/using_asyncio.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/using_asyncio.rst')
-rw-r--r--docs/using_asyncio.rst148
1 files changed, 148 insertions, 0 deletions
diff --git a/docs/using_asyncio.rst b/docs/using_asyncio.rst
new file mode 100644
index 00000000..55ed7679
--- /dev/null
+++ b/docs/using_asyncio.rst
@@ -0,0 +1,148 @@
+.. _using_asyncio:
+
+=============
+Using asyncio
+=============
+
+Block on IQ sending
+~~~~~~~~~~~~~~~~~~~
+
+:meth:`.Iq.send` now returns a :class:`~.Future` so you can easily block with:
+
+.. code-block:: python
+
+ result = yield from iq.send()
+
+.. warning::
+
+ If the reply is an IQ with an ``error`` type, this will raise an
+ :class:`.IqError`, and if it timeouts, it will raise an
+ :class:`.IqTimeout`. Don't forget to catch it.
+
+You can still use callbacks instead.
+
+XEP plugin integration
+~~~~~~~~~~~~~~~~~~~~~~
+
+The same changes from the SleekXMPP API apply, so you can do:
+
+.. code-block:: python
+
+ iq_info = yield from self.xmpp['xep_0030'].get_info(jid)
+
+But the following will only return a Future:
+
+.. code-block:: python
+
+ iq_info = self.xmpp['xep_0030'].get_info(jid)
+
+
+Callbacks, Event Handlers, and Stream Handlers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+IQ callbacks and :term:`Event Handlers <event handler>` can be coroutine
+functions; in this case, they will be scheduled in the event loop using
+:meth:`.asyncio.async` and not ran immediately.
+
+A :class:`.CoroutineCallback` class has been added as well for
+:term:`Stream Handlers <stream handler>`, which will use
+:meth:`.asyncio.async` to schedule the callback.
+
+Running the event loop
+~~~~~~~~~~~~~~~~~~~~~~
+
+:meth:`.XMLStream.process` is only a thin wrapper on top of
+``loop.run_forever()`` (if ``timeout`` is provided then it will
+only run for this amount of time, and if ``forever`` is False it will
+run until disconnection).
+
+Therefore you can handle the event loop in any way you like
+instead of using ``process()``.
+
+
+Examples
+~~~~~~~~
+
+Blocking until the session is established
+-----------------------------------------
+
+This code blocks until the XMPP session is fully established, which
+can be useful to make sure external events aren’t triggering XMPP
+callbacks while everything is not ready.
+
+.. code-block:: python
+
+ import asyncio, slixmpp
+
+ client = slixmpp.ClientXMPP('jid@example', 'password')
+ client.connected_event = asyncio.Event()
+ callback = lambda _: client.connected_event.set()
+ client.add_event_handler('session_start', callback)
+ client.connect()
+ loop.run_until_complete(event.wait())
+ # do some other stuff before running the event loop, e.g.
+ # loop.run_until_complete(httpserver.init())
+ client.process()
+
+
+Use with other asyncio-based libraries
+--------------------------------------
+
+This code interfaces with aiohttp to retrieve two pages asynchronously
+when the session is established, and then send the HTML content inside
+a simple <message>.
+
+.. code-block:: python
+
+ import asyncio, aiohttp, slixmpp
+
+ @asyncio.coroutine
+ def get_pythonorg(event):
+ req = yield from aiohttp.request('get', 'http://www.python.org')
+ text = yield from req.text
+ client.send_message(mto='jid2@example', mbody=text)
+
+ @asyncio.coroutine
+ def get_asyncioorg(event):
+ req = yield from aiohttp.request('get', 'http://www.asyncio.org')
+ text = yield from req.text
+ client.send_message(mto='jid3@example', mbody=text)
+
+ client = slixmpp.ClientXMPP('jid@example', 'password')
+ client.add_event_handler('session_start', get_pythonorg)
+ client.add_event_handler('session_start', get_asyncioorg)
+ client.connect()
+ client.process()
+
+
+Blocking Iq
+-----------
+
+This client checks (via XEP-0092) the software used by every entity it
+receives a message from. After this, it sends a message to a specific
+JID indicating its findings.
+
+.. code-block:: python
+
+ import asyncio, slixmpp
+
+ class ExampleClient(slixmpp.ClientXMPP):
+ def __init__(self, *args, **kwargs):
+ slixmpp.ClientXMPP.__init__(self, *args, **kwargs)
+ self.register_plugin('xep_0092')
+ self.add_event_handler('message', self.on_message)
+
+ @asyncio.coroutine
+ def on_message(self, event):
+ # You should probably handle IqError and IqTimeout exceptions here
+ # but this is an example.
+ version = yield from self['xep_0092'].get_version(message['from'])
+ text = "%s sent me a message, he runs %s" % (message['from'],
+ version['software_version']['name'])
+ self.send_message(mto='master@example.tld', mbody=text)
+
+ client = ExampleClient('jid@example', 'password')
+ client.connect()
+ client.process()
+
+