summaryrefslogtreecommitdiff
path: root/poezio/asyncio.py
blob: d333ffa6a3bdbcb76b7ff13a20366eb205e47159 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""
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