asyncio.py 1.54 KB
Newer Older
1 2 3 4 5 6 7 8 9
"""
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
10
from asyncio import events
mathieui's avatar
mathieui committed
11
from functools import wraps
12

louiz’'s avatar
louiz’ committed
13 14
import collections

15
def idle_call(self, callback):
16
    if asyncio.iscoroutinefunction(callback):
17 18 19 20 21 22 23 24 25
        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:
louiz’'s avatar
louiz’ committed
26
        handle = self._idle.popleft()
27 28 29 30
        handle._run()

cls = asyncio.get_event_loop().__class__

louiz’'s avatar
louiz’ committed
31
cls._idle = collections.deque()
32 33 34 35
cls.idle_call = idle_call
real_run_once = cls._run_once
cls._run_once = my_run_once

mathieui's avatar
mathieui committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

def coroutine_wrapper(func):
    """
    Make sure the result of a function call is a coroutine
    if the ``coroutine`` keyword argument is true.
    """
    def wrap_coro(result):
        if asyncio.iscoroutinefunction(result):
            return result
        else:
            return asyncio.coroutine(lambda: result)()

    @wraps(func)
    def wrapper(*args, **kwargs):
        if kwargs.get('coroutine', False):
            return wrap_coro(func(*args, **kwargs))
        else:
            return func(*args, **kwargs)

    return wrapper