summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2021-02-24 20:59:12 +0100
committermathieui <mathieui@mathieui.net>2021-02-24 20:59:12 +0100
commit5f9ab45a5e161c3035a844184736b3180dae6047 (patch)
tree7228b6b366931dbc6dd43747aa6a7d601db77cd0
parentb8b57960f1ba2a5468b0ed76e6442f89fe98e0b4 (diff)
parent6d241be78971af2eb800f98fe2283f42344a7cb6 (diff)
downloadslixmpp-5f9ab45a5e161c3035a844184736b3180dae6047.tar.gz
slixmpp-5f9ab45a5e161c3035a844184736b3180dae6047.tar.bz2
slixmpp-5f9ab45a5e161c3035a844184736b3180dae6047.tar.xz
slixmpp-5f9ab45a5e161c3035a844184736b3180dae6047.zip
Merge branch 'stream-features-sync-event' into 'master'
Allow "sync" events to be processed in-order See merge request poezio/slixmpp!129
-rw-r--r--slixmpp/plugins/xep_0077/register.py6
-rw-r--r--slixmpp/xmlstream/xmlstream.py40
2 files changed, 42 insertions, 4 deletions
diff --git a/slixmpp/plugins/xep_0077/register.py b/slixmpp/plugins/xep_0077/register.py
index 953fee70..1850b2c9 100644
--- a/slixmpp/plugins/xep_0077/register.py
+++ b/slixmpp/plugins/xep_0077/register.py
@@ -203,14 +203,14 @@ class XEP_0077(BasePlugin):
self.xmpp.del_filter('in', self._force_stream_feature)
return stanza
- def _handle_register_feature(self, features):
+ async def _handle_register_feature(self, features):
if 'mechanisms' in self.xmpp.features:
# We have already logged in with an account
return False
if self.create_account and self.xmpp.event_handled('register'):
- form = self.get_registration()
- self.xmpp.event('register', form)
+ form = await self.get_registration()
+ await self.xmpp.event_async('register', form)
return True
return False
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.