summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slixmpp/xmlstream/asyncio.py32
-rw-r--r--slixmpp/xmlstream/resolver.py2
-rw-r--r--slixmpp/xmlstream/xmlstream.py5
3 files changed, 36 insertions, 3 deletions
diff --git a/slixmpp/xmlstream/asyncio.py b/slixmpp/xmlstream/asyncio.py
new file mode 100644
index 00000000..52610d01
--- /dev/null
+++ b/slixmpp/xmlstream/asyncio.py
@@ -0,0 +1,32 @@
+"""
+A module that monkey patches the standard asyncio module to add an
+idle_call() method to the main loop. This method is used to execute a
+callback whenever the loop is not busy handling anything else. This means
+that it is a callback with lower priority than IO, timer, or even
+call_soon() ones. These callback are called only once each.
+"""
+
+import asyncio
+from asyncio import tasks, events
+
+def idle_call(self, callback):
+ if tasks.iscoroutinefunction(callback):
+ raise TypeError("coroutines cannot be used with idle_call()")
+ handle = events.Handle(callback, [], self)
+ self._idle.append(handle)
+
+def my_run_once(self):
+ if self._idle:
+ self._ready.append(events.Handle(lambda: None, (), self))
+ real_run_once(self)
+ if self._idle:
+ handle = self._idle.pop(0)
+ handle._run()
+
+cls = asyncio.get_event_loop().__class__
+
+cls._idle = []
+cls.idle_call = idle_call
+real_run_once = cls._run_once
+cls._run_once = my_run_once
+
diff --git a/slixmpp/xmlstream/resolver.py b/slixmpp/xmlstream/resolver.py
index a3697d14..f2c3f989 100644
--- a/slixmpp/xmlstream/resolver.py
+++ b/slixmpp/xmlstream/resolver.py
@@ -8,7 +8,7 @@
:license: MIT, see LICENSE for more details
"""
-import asyncio
+from slixmpp.xmlstream.asyncio import asyncio
import socket
import logging
import random
diff --git a/slixmpp/xmlstream/xmlstream.py b/slixmpp/xmlstream/xmlstream.py
index 187bfbc5..f1abfca6 100644
--- a/slixmpp/xmlstream/xmlstream.py
+++ b/slixmpp/xmlstream/xmlstream.py
@@ -12,7 +12,6 @@
:license: MIT, see LICENSE for more details
"""
-import asyncio
import functools
import copy
import logging
@@ -23,6 +22,7 @@ import uuid
import xml.etree.ElementTree
+from slixmpp.xmlstream.asyncio import asyncio
from slixmpp.xmlstream import tostring
from slixmpp.xmlstream.stanzabase import StanzaBase, ElementBase
from slixmpp.xmlstream.resolver import resolve, default_resolver
@@ -377,7 +377,8 @@ class XMLStream(object):
elif self.xml_depth == 1:
# A stanza is an XML element that is a direct child of
# the root element, hence the check of depth == 1
- self.__spawn_event(xml)
+ asyncio.get_event_loop().\
+ idle_call(functools.partial(self.__spawn_event, xml))
if self.xml_root is not None:
# Keep the root element empty of children to
# save on memory use.