summaryrefslogtreecommitdiff
path: root/poezio/asyncio.py
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2016-10-05 20:20:46 +0200
committermathieui <mathieui@mathieui.net>2016-10-05 20:20:46 +0200
commit3c9eac5dc99eb809584d4877e1eea603c97be3da (patch)
tree58b91b290986bc751711218e5c7ff776b0deb4e4 /poezio/asyncio.py
parenteacc5a6fb188af6b7027064e4bc34212729334dd (diff)
downloadpoezio-3c9eac5dc99eb809584d4877e1eea603c97be3da.tar.gz
poezio-3c9eac5dc99eb809584d4877e1eea603c97be3da.tar.bz2
poezio-3c9eac5dc99eb809584d4877e1eea603c97be3da.tar.xz
poezio-3c9eac5dc99eb809584d4877e1eea603c97be3da.zip
Add monkeypatching hack on the event loop
Previously inside slixmpp, it’s cleaner to do it only in poezio.
Diffstat (limited to 'poezio/asyncio.py')
-rw-r--r--poezio/asyncio.py42
1 files changed, 42 insertions, 0 deletions
diff --git a/poezio/asyncio.py b/poezio/asyncio.py
new file mode 100644
index 00000000..2b02a91f
--- /dev/null
+++ b/poezio/asyncio.py
@@ -0,0 +1,42 @@
+"""
+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
+import functools
+import collections
+from asyncio import events
+
+import slixmpp
+
+
+def monkey_patch_asyncio_slixmpp():
+ def idle_call(self, callback):
+ if asyncio.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.popleft()
+ handle._run()
+ cls = asyncio.get_event_loop().__class__
+ cls._idle = collections.deque()
+ cls.idle_call = idle_call
+ real_run_once = cls._run_once
+ cls._run_once = my_run_once
+
+ spawn_event = slixmpp.xmlstream.XMLStream._spawn_event
+ def patchy(self, xml):
+ self.loop.idle_call(functools.partial(spawn_event, self, xml))
+ slixmpp.xmlstream.XMLStream._spawn_event = patchy
+
+