diff options
Diffstat (limited to 'slixmpp/xmlstream/asyncio.py')
-rw-r--r-- | slixmpp/xmlstream/asyncio.py | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/slixmpp/xmlstream/asyncio.py b/slixmpp/xmlstream/asyncio.py new file mode 100644 index 00000000..0e0f610a --- /dev/null +++ b/slixmpp/xmlstream/asyncio.py @@ -0,0 +1,50 @@ +""" +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 events +from functools import wraps + +import collections + +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 + +def future_wrapper(func): + """ + Make sure the result of a function call is an asyncio.Future() + object. + """ + @wraps(func) + def wrapper(*args, **kwargs): + result = func(*args, **kwargs) + if isinstance(result, asyncio.Future): + return result + future = asyncio.Future() + future.set_result(result) + return future + + return wrapper |