summaryrefslogtreecommitdiff
path: root/slixmpp/xmlstream/handler
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2015-02-22 14:17:17 +0100
committermathieui <mathieui@mathieui.net>2015-02-22 14:17:17 +0100
commit2b3b86e281da03dfe4b2444be5b62811b4dcfe8d (patch)
tree10638578db29b92a20cb0760e50d4c2c73120a92 /slixmpp/xmlstream/handler
parent92e4bc752a7da814b5b7c19b0f5d2ee95f715f7e (diff)
downloadslixmpp-2b3b86e281da03dfe4b2444be5b62811b4dcfe8d.tar.gz
slixmpp-2b3b86e281da03dfe4b2444be5b62811b4dcfe8d.tar.bz2
slixmpp-2b3b86e281da03dfe4b2444be5b62811b4dcfe8d.tar.xz
slixmpp-2b3b86e281da03dfe4b2444be5b62811b4dcfe8d.zip
Allow event handlers to be coroutine functions
And do not copy data when running events with XMLStream.event()
Diffstat (limited to 'slixmpp/xmlstream/handler')
-rw-r--r--slixmpp/xmlstream/handler/__init__.py3
-rw-r--r--slixmpp/xmlstream/handler/coroutine_callback.py84
2 files changed, 86 insertions, 1 deletions
diff --git a/slixmpp/xmlstream/handler/__init__.py b/slixmpp/xmlstream/handler/__init__.py
index 31de9dfc..51a7ca6a 100644
--- a/slixmpp/xmlstream/handler/__init__.py
+++ b/slixmpp/xmlstream/handler/__init__.py
@@ -7,9 +7,10 @@
"""
from slixmpp.xmlstream.handler.callback import Callback
+from slixmpp.xmlstream.handler.coroutine_callback import CoroutineCallback
from slixmpp.xmlstream.handler.collector import Collector
from slixmpp.xmlstream.handler.waiter import Waiter
from slixmpp.xmlstream.handler.xmlcallback import XMLCallback
from slixmpp.xmlstream.handler.xmlwaiter import XMLWaiter
-__all__ = ['Callback', 'Waiter', 'XMLCallback', 'XMLWaiter']
+__all__ = ['Callback', 'CoroutineCallback', 'Waiter', 'XMLCallback', 'XMLWaiter']
diff --git a/slixmpp/xmlstream/handler/coroutine_callback.py b/slixmpp/xmlstream/handler/coroutine_callback.py
new file mode 100644
index 00000000..8ad9572e
--- /dev/null
+++ b/slixmpp/xmlstream/handler/coroutine_callback.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+"""
+ slixmpp.xmlstream.handler.callback
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Part of Slixmpp: The Slick XMPP Library
+
+ :copyright: (c) 2011 Nathanael C. Fritz
+ :license: MIT, see LICENSE for more details
+"""
+
+from slixmpp.xmlstream.handler.base import BaseHandler
+from slixmpp.xmlstream.asyncio import asyncio
+
+
+class CoroutineCallback(BaseHandler):
+
+ """
+ The Callback handler will execute a callback function with
+ matched stanzas.
+
+ The handler may execute the callback either during stream
+ processing or during the main event loop.
+
+ The event will be scheduled to be run soon in the event loop instead
+ of immediately.
+
+ :param string name: The name of the handler.
+ :param matcher: A :class:`~slixmpp.xmlstream.matcher.base.MatcherBase`
+ derived object for matching stanza objects.
+ :param pointer: The function to execute during callback. If ``pointer``
+ is not a coroutine, this function will raise a ValueError.
+ :param bool once: Indicates if the handler should be used only
+ once. Defaults to False.
+ :param bool instream: Indicates if the callback should be executed
+ during stream processing instead of in the
+ main event loop.
+ :param stream: The :class:`~slixmpp.xmlstream.xmlstream.XMLStream`
+ instance this handler should monitor.
+ """
+
+ def __init__(self, name, matcher, pointer, once=False,
+ instream=False, stream=None):
+ BaseHandler.__init__(self, name, matcher, stream)
+ if not asyncio.iscoroutinefunction(pointer):
+ raise ValueError("Given function is not a coroutine")
+
+ @asyncio.coroutine
+ def pointer_wrapper(stanza, *args, **kwargs):
+ try:
+ yield from pointer(stanza, *args, **kwargs)
+ except Exception as e:
+ stanza.exception(e)
+
+ self._pointer = pointer_wrapper
+ self._once = once
+ self._instream = instream
+
+ def prerun(self, payload):
+ """Execute the callback during stream processing, if
+ the callback was created with ``instream=True``.
+
+ :param payload: The matched
+ :class:`~slixmpp.xmlstream.stanzabase.ElementBase` object.
+ """
+ if self._once:
+ self._destroy = True
+ if self._instream:
+ self.run(payload, True)
+
+ def run(self, payload, instream=False):
+ """Execute the callback function with the matched stanza payload.
+
+ :param payload: The matched
+ :class:`~slixmpp.xmlstream.stanzabase.ElementBase` object.
+ :param bool instream: Force the handler to execute during stream
+ processing. This should only be used by
+ :meth:`prerun()`. Defaults to ``False``.
+ """
+ if not self._instream or instream:
+ asyncio.async(self._pointer(payload))
+ if self._once:
+ self._destroy = True
+ del self._pointer