diff options
author | mathieui <mathieui@mathieui.net> | 2021-02-15 21:46:59 +0100 |
---|---|---|
committer | mathieui <mathieui@mathieui.net> | 2021-02-24 20:50:05 +0100 |
commit | babd98dac7ffca467d0f7303cfd8bb72cca11f1b (patch) | |
tree | 8e607c25086782f5ee7b02774d947cb9a424d286 | |
parent | 73814605565df02ae534b5d0b57868b6cafa58f7 (diff) | |
download | slixmpp-babd98dac7ffca467d0f7303cfd8bb72cca11f1b.tar.gz slixmpp-babd98dac7ffca467d0f7303cfd8bb72cca11f1b.tar.bz2 slixmpp-babd98dac7ffca467d0f7303cfd8bb72cca11f1b.tar.xz slixmpp-babd98dac7ffca467d0f7303cfd8bb72cca11f1b.zip |
xmlstream: add event_async() for events that need in-order processing
Essentially stream feature handlers which can then make sure the feature
has been process correctly (e.g. 0077).
This is the same approach as slixmpp!4.
-rw-r--r-- | slixmpp/xmlstream/xmlstream.py | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/slixmpp/xmlstream/xmlstream.py b/slixmpp/xmlstream/xmlstream.py index 8a726e15..2f506018 100644 --- a/slixmpp/xmlstream/xmlstream.py +++ b/slixmpp/xmlstream/xmlstream.py @@ -850,8 +850,46 @@ class XMLStream(asyncio.BaseProtocol): """ return len(self.__event_handlers.get(name, [])) - def event(self, name, data={}): + async def event_async(self, name: str, data: Any = {}): + """Manually trigger a custom event, but await coroutines immediately. + + This event generator should only be called in situations when + in-order processing of events is important, such as features + handling. + + :param name: The name of the event to trigger. + :param data: Data that will be passed to each event handler. + Defaults to an empty dictionary, but is usually + a stanza object. + """ + handlers = self.__event_handlers.get(name, [])[:] + for handler in handlers: + handler_callback, disposable = handler + if disposable: + # If the handler is disposable, we will go ahead and + # remove it now instead of waiting for it to be + # processed in the queue. + try: + self.__event_handlers[name].remove(handler) + except ValueError: + pass + # If the callback is a coroutine, schedule it instead of + # running it directly + if iscoroutinefunction(handler_callback): + try: + await handler_callback(data) + except Exception as exc: + self.exception(exc) + else: + try: + handler_callback(data) + except Exception as e: + self.exception(e) + + def event(self, name: str, data: Any = {}): """Manually trigger a custom event. + Coroutine handlers are wrapped into a future and sent into the + event loop for their execution, and not awaited. :param name: The name of the event to trigger. :param data: Data that will be passed to each event handler. |