Пример #1
0
    def test_run_once_in_executor_handle(self):
        def cb():
            pass

        self.assertRaises(AssertionError, self.loop.run_in_executor, None,
                          asyncio.Handle(cb, (), self.loop), ('', ))
        self.assertRaises(AssertionError, self.loop.run_in_executor, None,
                          asyncio.TimerHandle(10, cb, (), self.loop))
Пример #2
0
 def _call_soon(self, callback, args):
     if (asyncio.iscoroutine(callback) or asyncio.iscoroutinefunction(callback)):
         raise TypeError("coroutines cannot be used with call_soon()")
     self._check_closed()
     handle = asyncio.Handle(callback, args, self)
     if handle._source_traceback:
         del handle._source_traceback[-1]
     self._ready.append(handle)
     return handle
Пример #3
0
 def call_soon_threadsafe(self, callback, *args):
     handler = asyncio.Handle(callback, args, self)
     # We don't use _add_callback here because starting the Idle handle
     # is not threadsafe. Instead, we queue the callback and in the Async
     # handle callback (which is run in the loop thread) we start the
     # Idle handle if needed
     self._ready.append(handler)
     self._waker.send()
     return handler
Пример #4
0
    def call_soon_threadsafe(self, callback, *args, **context):
        """asyncio's thread-safe defer-to-mainloop

        Note that the callback is a sync function.
        """
        self._check_callback(callback, 'call_soon_threadsafe')
        self._check_closed()
        h = asyncio.Handle(callback, args, self, **context)
        self._token.run_sync_soon(self._q_send.send_nowait, h)
Пример #5
0
    def test_run_once_in_executor_cancelled(self):
        def cb():
            pass
        h = asyncio.Handle(cb, (), self.loop)
        h.cancel()

        f = self.loop.run_in_executor(None, h)
        self.assertIsInstance(f, asyncio.Future)
        self.assertTrue(f.done())
        self.assertIsNone(f.result())
    def call_later(self, delay, callback, *args, context=None):
        """Register callback to be invoked after a certain delay."""
        if asyncio.iscoroutinefunction(callback):
            raise TypeError("coroutines cannot be used with call_later")
        if not callable(callback):
            raise TypeError(
                "callback must be callable: {}".format(type(callback).__name__)
            )

        self.__log_debug(
            "Registering callback %s to be invoked with arguments %s after %s second(s)",
            callback, args, delay
        )

        if sys.version_info >= (3, 7):
            return self._add_callback(
                asyncio.Handle(callback, args, self, context=context), delay
            )
        return self._add_callback(asyncio.Handle(callback, args, self), delay)
Пример #7
0
 def add_writer(self, fd, callback, *args):
     handler = asyncio.Handle(callback, args, self)
     try:
         poll_h = self._fd_map[fd]
     except KeyError:
         poll_h = self._create_poll_handle(fd)
         self._fd_map[fd] = poll_h
     poll_h.pevents |= pyuv.UV_WRITABLE
     poll_h.write_handler = handler
     poll_h.start(poll_h.pevents, self._poll_cb)
def _sync_await(awaitable: Awaitable[Any]) -> Any:
    """
    _sync_await waits for the given future to complete by effectively yielding the current task and pumping the event
    loop.
    """

    # Fetch the current event loop and ensure a future.
    loop = None
    try:
        loop = asyncio.get_event_loop()
    except RuntimeError:
        pass
    if loop is None:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)

    fut = asyncio.ensure_future(awaitable)

    # If the loop is not running, we can just use run_until_complete. Without this, we would need to duplicate a fair
    # amount of bookkeeping logic around loop startup and shutdown.
    if not loop.is_running():
        return loop.run_until_complete(fut)

    # If we are executing inside a task, pretend we've returned from its current callback--effectively yielding to
    # the event loop--by calling _leave_task.
    task = _get_current_task(loop)
    if task is not None:
        _leave_task(loop, task)

    # Pump the event loop until the future is complete. This is the kernel of BaseEventLoop.run_forever, and may not
    # work with alternative event loop implementations.
    #
    # In order to make this reentrant with respect to _run_once, we keep track of the number of event handles on the
    # ready list and ensure that there are exactly that many handles on the list once we are finished.
    #
    # See https://github.com/python/cpython/blob/3.6/Lib/asyncio/base_events.py#L1428-L1452 for the details of the
    # _run_once kernel with which we need to cooperate.
    ntodo = len(loop._ready)  # type: ignore
    while not fut.done() and not fut.cancelled():
        loop._run_once()  # type: ignore
        if loop._stopping:  # type: ignore
            break
    # If we drained the ready list past what a calling _run_once would have expected, fix things up by pushing
    # cancelled handles onto the list.
    while len(loop._ready) < ntodo:  # type: ignore
        handle = asyncio.Handle(lambda: None, [], loop)
        handle._cancelled = True
        loop._ready.append(handle)  # type: ignore

    # If we were executing inside a task, restore its context and continue on.
    if task is not None:
        _enter_task(loop, task)

    # Return the result of the future.
    return fut.result()
Пример #9
0
def _call_asap(
    loop: Any, callback: Callable, *args: Any, context: Any = None
) -> asyncio.Handle:
    loop._check_closed()
    if loop._debug:
        loop._check_callback(callback, "call_soon_threadsafe")
    loop._call_soon(callback, args, context)
    if context is not None:
        handle = asyncio.Handle(callback, list(args), loop, context)  # type: ignore
    else:
        handle = asyncio.Handle(callback, list(args), loop)
    if handle._source_traceback:  # type: ignore
        del handle._source_traceback[-1]  # type: ignore

    loop._ready.insert(0, handle)

    if handle._source_traceback:  # type: ignore
        del handle._source_traceback[-1]  # type: ignore
    loop._write_to_self()
    return handle
Пример #10
0
 def add_signal_handler(self, sig, callback, *args):
     """asyncio's method to add a signal handler.
     """
     self._check_closed()
     self._check_signal(sig)
     if sig == signal.SIGKILL:
         raise RuntimeError("SIGKILL cannot be caught")
     h = asyncio.Handle(callback, args, self)
     assert sig not in self._signal_handlers, \
         "Signal %d is already being caught" % (sig,)
     self._orig_signals[sig] = signal.signal(sig, self._handle_sig)
     self._signal_handlers[sig] = h
Пример #11
0
def _call_asap(loop: Any,
               callback: Callable,
               *args: Any,
               context: Any = None) -> asyncio.Handle:
    loop._check_closed()
    if loop._debug:
        loop._check_callback(callback, 'call_soon_threadsafe')
    handle = loop._call_soon(callback, args, context)
    if context is not None:
        handle = asyncio.Handle(callback, args, loop, context)
    else:
        handle = asyncio.Handle(callback, args, loop)
    if handle._source_traceback:
        del handle._source_traceback[-1]

    loop._ready.insert(0, handle)

    if handle._source_traceback:
        del handle._source_traceback[-1]
    loop._write_to_self()
    return handle
Пример #12
0
    def call_later(self, delay, callback, *args):
        """Register callback to be invoked after a certain delay."""
        if asyncio.iscoroutinefunction(callback):
            raise TypeError("coroutines cannot be used with call_later")
        if not callable(callback):
            raise TypeError('callback must be callable: {}'.format(
                type(callback).__name__))

        self._logger.debug(
            'Registering callback {} to be invoked with arguments {} after {} second(s)'
            .format(callback, args, delay))
        return self._add_callback(asyncio.Handle(callback, args, self), delay)
Пример #13
0
 def add_signal_handler(self, sig, callback, *args):
     self._validate_signal(sig)
     signal_h = pyuv.Signal(self._loop)
     handler = asyncio.Handle(callback, args, self)
     signal_h.handler = handler
     try:
         signal_h.start(self._signal_cb, sig)
     except Exception as e:
         signal_h.close()
         raise RuntimeError(str(e))
     else:
         self._signal_handlers[sig] = signal_h
     return handler
Пример #14
0
    async def synchronize(self):
        """Suspend execution until all callbacks previously scheduled using
        ``call_soon()`` have been processed.

        This is a Trio-flavored async function.

        From asyncio, call ``await loop.run_trio(loop.synchronize)``
        instead of ``await asyncio.sleep(0)`` if you need to process all
        queued callbacks.

        """
        w = trio.Event()
        self._queue_handle(asyncio.Handle(w.set, (), self))
        await w.wait()
Пример #15
0
    def add_signal_handler(self, sig: int,
                           callback: typing.Callable[..., typing.Any],
                           *args: typing.Any):
        """Add a handler for a signal.  UNIX only.

        Raise ValueError if the signal number is invalid or uncatchable.
        Raise RuntimeError if there is a problem setting up the handler.
        """
        if asyncio.iscoroutine(callback) or asyncio.iscoroutinefunction(
                callback):
            raise TypeError("coroutines cannot be used "
                            "with add_signal_handler()")
        if not callable(callback):
            raise TypeError(f"{callback!r} is not callable")

        self._check_signal(sig)
        self._check_closed()
        try:
            # set_wakeup_fd() raises ValueError if this is not the
            # main thread.  By calling it early we ensure that an
            # event loop running in another thread cannot add a signal
            # handler.
            signal.set_wakeup_fd(self._csock.fileno())
        except (ValueError, OSError) as exc:
            raise RuntimeError(str(exc))

        handle = asyncio.Handle(callback, args, self, None)
        self._signal_handlers[sig] = handle

        try:
            # Register a dummy signal handler to ask Python to write the signal
            # number in the wakup file descriptor. _process_self_data() will
            # read signal numbers from this file descriptor to handle signals.
            signal.signal(sig, _sighandler_noop)

            # Set SA_RESTART to limit EINTR occurrences.
            signal.siginterrupt(sig, False)
        except OSError as exc:
            del self._signal_handlers[sig]
            if not self._signal_handlers:
                try:
                    signal.set_wakeup_fd(-1)
                except (ValueError, OSError) as nexc:
                    logger.info("set_wakeup_fd(-1) failed: %s", nexc)

            if exc.errno == errno.EINVAL:
                raise RuntimeError(f"sig {sig} cannot be caught")
            else:  # pragma: nocover
                raise
Пример #16
0
    def __init__(self, name, tag, *args, prefix=None, untagged_resp_name=None, loop=asyncio.get_event_loop(), timeout=None):
        self.name = name
        self.tag = tag
        self.args = args
        self.prefix = prefix + ' ' if prefix else None
        self.untagged_resp_name = untagged_resp_name or name

        self.response = None
        self._exception = None
        self._event = asyncio.Event(loop=loop)
        self._loop = loop
        self._timeout = timeout
        self._timer = asyncio.Handle(lambda: None, None, loop)  # fake timer
        self._set_timer()
        self._literal_data = None
        self._expected_size = 0
Пример #17
0
    def call_soon(self, callback, *args, context=None):
        def doit(hdl):
            if not hdl._cancelled:
                hdl._run()
            #end if
            return \
                False # always one-shot

        #end doit

    #begin call_soon
        self._check_closed()
        hdl = asyncio.Handle(callback, args, self)
        GLib.idle_add(doit, hdl)
        self = None  # avoid circular references
        return \
            hdl
Пример #18
0
    def test_run_once_in_executor_plain(self):
        def cb():
            pass
        h = asyncio.Handle(cb, (), self.loop)
        f = asyncio.Future(loop=self.loop)
        executor = mock.Mock()
        executor.submit.return_value = f

        self.loop.set_default_executor(executor)

        res = self.loop.run_in_executor(None, h)
        self.assertIs(f, res)

        executor = mock.Mock()
        executor.submit.return_value = f
        res = self.loop.run_in_executor(executor, h)
        self.assertIs(f, res)
        self.assertTrue(executor.submit.called)

        f.cancel()  # Don't complain about abandoned Future.
Пример #19
0
    def stop(self):
        """Halt the main loop.

        Any callbacks queued before this point are processed before
        stopping.

        """
        def do_stop():
            self._stop_pending = False
            raise StopAsyncIteration

#        async def stop_me():
#            def kick_():
#                raise StopAsyncIteration
#            self._queue_handle(asyncio.Handle(kick_, (), self))
#            await self._main_loop()
#        if threading.current_thread() != self._thread:
#            self.__run_in_thread(stop_me)
#        else:

        if self._thread_running and not self._stop_pending:
            self._stop_pending = True
            self._queue_handle(asyncio.Handle(do_stop, (), self))
def _patch_loop(loop):
    """
    Patch loop to make it reentrent.
    """
    def run_until_complete(self, future):
        if self.is_running():
            self._check_closed()
            f = asyncio.ensure_future(future)
            if f is not future:
                f._log_destroy_pending = False
            while not f.done():
                run_once(self)
            return f.result()
        else:
            return self._run_until_complete_orig(future)

    bogus_handle = asyncio.Handle(None, None, loop)
    bogus_handle.cancel()

    def run_once(self):
        ready = self._ready
        scheduled = self._scheduled

        # remove bogus handles to get more efficient timeout
        while ready and ready[0] is bogus_handle:
            ready.popleft()
        nready = len(ready)

        while scheduled and scheduled[0]._cancelled:
            self._timer_cancelled_count -= 1
            handle = heapq.heappop(scheduled)
            handle._scheduled = False

        timeout = None
        if ready or self._stopping:
            timeout = 0
        elif scheduled:
            when = scheduled[0]._when
            timeout = max(0, when - self.time())

        event_list = self._selector.select(timeout)
        self._process_events(event_list)

        end_time = self.time() + self._clock_resolution
        while scheduled:
            handle = scheduled[0]
            if handle._when >= end_time:
                break
            handle = heapq.heappop(scheduled)
            handle._scheduled = False
            ready.append(handle)

        self._nesting_level += 1
        ntodo = len(ready)
        for _ in range(ntodo):
            if not ready:
                break
            handle = ready.popleft()
            if handle._cancelled:
                continue
            handle._run()
        handle = None
        self._nesting_level -= 1

        # add bogus handles to keep loop._run_once happy
        if nready and self._nesting_level == 0:
            ready.extendleft([bogus_handle] * nready)

    cls = loop.__class__
    cls._run_until_complete_orig = cls.run_until_complete
    cls.run_until_complete = run_until_complete
    cls._nesting_level = 0
Пример #21
0
    def test__add_callback_handle(self):
        h = asyncio.Handle(lambda: False, (), self.loop)

        self.loop._add_callback(h)
        self.assertFalse(self.loop._scheduled)
        self.assertIn(h, self.loop._ready)
Пример #22
0
 def runTest(self):
     # add a dummy event
     handle = asyncio.Handle(lambda: None, (), self.loop)
     key = selectors.SelectorKey(1, 1, selectors.EVENT_READ,
                                 (handle, None))
     mock.get_map.return_value = {1: key}
Пример #23
0
 def call_soon(self, callback, *args, context=None):
     handle = asyncio.Handle(callback, args, self, context=context)
     window.setTimeout(handle._run)
     return handle
Пример #24
0
def call_soon(func, *args):
    func(*args)
    return asyncio.Handle(func, args, None)
Пример #25
0
def call_later(i, func, *args):
    if func.__name__ in dir(IrcBot):
        func(*args)
        return asyncio.Handle(func, args, None)
Пример #26
0
 def call_soon(self, callback, *args, context=None):
     h = asyncio.Handle(callback, args, self)
     self._immediate.append(h)
     return h
Пример #27
0
 def call_later(self, when, callback, *args, context=None):
     handle = asyncio.Handle(callback, args, self, context=context)
     window.setTimeout(handle._run, when * 1000.0)
     return handle
Пример #28
0
def _patch_loop(loop):
    """
    Patch loop to make it reentrent.
    """
    def run_forever_35_36(self):
        # from Python 3.5/3.6 asyncio.base_events
        self._check_closed()
        old_thread_id = self._thread_id
        old_running_loop = events._get_running_loop()
        self._set_coroutine_wrapper(self._debug)
        self._thread_id = threading.get_ident()
        if self._asyncgens is not None:
            old_agen_hooks = sys.get_asyncgen_hooks()
            sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                   finalizer=self._asyncgen_finalizer_hook)
        try:
            events._set_running_loop(self)
            while True:
                self._run_once()
                if self._stopping:
                    break
        finally:
            self._stopping = False
            self._thread_id = old_thread_id
            events._set_running_loop(old_running_loop)
            self._set_coroutine_wrapper(False)
            if self._asyncgens is not None:
                sys.set_asyncgen_hooks(*old_agen_hooks)

    def run_forever_37(self):
        # from Python 3.7 asyncio.base_events
        self._check_closed()
        old_thread_id = self._thread_id
        old_running_loop = events._get_running_loop()
        self._set_coroutine_origin_tracking(self._debug)
        self._thread_id = threading.get_ident()

        old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                               finalizer=self._asyncgen_finalizer_hook)
        try:
            events._set_running_loop(self)
            while True:
                self._run_once()
                if self._stopping:
                    break
        finally:
            self._stopping = False
            self._thread_id = old_thread_id
            events._set_running_loop(old_running_loop)
            self._set_coroutine_origin_tracking(False)
            sys.set_asyncgen_hooks(*old_agen_hooks)

    bogus_handle = asyncio.Handle(None, None, loop)
    bogus_handle.cancel()

    def run_once(self):
        ready = self._ready
        scheduled = self._scheduled

        # remove bogus handles to get more efficient timeout
        while ready and ready[0] is bogus_handle:
            ready.popleft()
        nready = len(ready)

        while scheduled and scheduled[0]._cancelled:
            self._timer_cancelled_count -= 1
            handle = heapq.heappop(scheduled)
            handle._scheduled = False

        timeout = None
        if ready or self._stopping:
            timeout = 0
        elif scheduled:
            when = scheduled[0]._when
            timeout = max(0, when - self.time())

        event_list = self._selector.select(timeout)
        self._process_events(event_list)

        end_time = self.time() + self._clock_resolution
        while scheduled:
            handle = scheduled[0]
            if handle._when >= end_time:
                break
            handle = heapq.heappop(scheduled)
            handle._scheduled = False
            ready.append(handle)

        self._nesting_level += 1
        ntodo = len(ready)
        for _ in range(ntodo):
            if not ready:
                break
            handle = ready.popleft()
            if handle._cancelled:
                continue
            handle._run()
        handle = None
        self._nesting_level -= 1

        if nready and self._nesting_level == 0:
            # When the loop was patched while it was already running,
            # there is an unpatched loop._run_once enclosing us.
            # It expects to process 'nready' handles and will crash
            # if there are less. # So here we feed it 'nready' bogus handles.
            ready.extendleft([bogus_handle] * nready)

    cls = loop.__class__
    cls._run_forever_orig = cls.run_forever
    if sys.version_info >= (3, 7, 0):
        cls.run_forever = run_forever_37
    else:
        cls.run_forever = run_forever_35_36
    cls._nesting_level = 0
Пример #29
0
 def call_soon(self, callback, *args, context=None):
     """Call the given callback as soon as possible."""
     h = asyncio.Handle(callback, args, self, context=context)
     self._todo.append(h)
     return h
Пример #30
0
 def call_soon(self, callback, *args):
     handler = asyncio.Handle(callback, args, self)
     self._ready.append(handler)
     return handler