示例#1
0
 def wrapper(*args, **kwargs):
     # type: (*Any, **Any) -> Future[_T]
     # This function is type-annotated with a comment to work around
     # https://bitbucket.org/pypy/pypy/issues/2868/segfault-with-args-type-annotation-in
     future = _create_future()
     if contextvars is not None:
         ctx_run = contextvars.copy_context().run  # type: Callable
     else:
         ctx_run = _fake_ctx_run
     try:
         result = ctx_run(func, *args, **kwargs)
     except (Return, StopIteration) as e:
         result = _value_from_stopiteration(e)
     except Exception:
         future_set_exc_info(future, sys.exc_info())
         try:
             return future
         finally:
             # Avoid circular references
             future = None  # type: ignore
     else:
         if isinstance(result, Generator):
             # Inline the first iteration of Runner.run.  This lets us
             # avoid the cost of creating a Runner when the coroutine
             # never actually yields, which in turn allows us to
             # use "optional" coroutines in critical path code without
             # performance penalty for the synchronous case.
             try:
                 yielded = ctx_run(next, result)
             except (StopIteration, Return) as e:
                 future_set_result_unless_cancelled(
                     future, _value_from_stopiteration(e))
             except Exception:
                 future_set_exc_info(future, sys.exc_info())
             else:
                 # Provide strong references to Runner objects as long
                 # as their result future objects also have strong
                 # references (typically from the parent coroutine's
                 # Runner). This keeps the coroutine's Runner alive.
                 # We do this by exploiting the public API
                 # add_done_callback() instead of putting a private
                 # attribute on the Future.
                 # (GitHub issues #1769, #2229).
                 runner = Runner(ctx_run, result, future, yielded)
                 future.add_done_callback(lambda _: runner)
             yielded = None
             try:
                 return future
             finally:
                 # Subtle memory optimization: if next() raised an exception,
                 # the future's exc_info contains a traceback which
                 # includes this stack frame.  This creates a cycle,
                 # which will be collected at the next full GC but has
                 # been shown to greatly increase memory usage of
                 # benchmarks (relative to the refcount-based scheme
                 # used in the absence of cycles).  We can avoid the
                 # cycle by clearing the local variable after we return it.
                 future = None  # type: ignore
     future_set_result_unless_cancelled(future, result)
     return future
示例#2
0
 def callback(ret: int) -> None:
     if ret != 0 and raise_error:
         # Unfortunately we don't have the original args any more.
         future_set_exception_unless_cancelled(
             future, CalledProcessError(ret, "unknown"))
     else:
         future_set_result_unless_cancelled(future, ret)
示例#3
0
 def _finish_request(self, future: "Optional[Future[None]]") -> None:
     self._clear_callbacks()
     if not self.is_client and self._disconnect_on_finish:
         self.close()
         return
     # Turn Nagle's algorithm back on, leaving the stream in its
     # default state for the next request.
     self.stream.set_nodelay(False)
     if not self._finish_future.done():
         future_set_result_unless_cancelled(self._finish_future, None)
示例#4
0
 def _on_connection_close(self) -> None:
     # Note that this callback is only registered on the IOStream
     # when we have finished reading the request and are waiting for
     # the application to produce its response.
     if self._close_callback is not None:
         callback = self._close_callback
         self._close_callback = None
         callback()
     if not self._finish_future.done():
         future_set_result_unless_cancelled(self._finish_future, None)
     self._clear_callbacks()
示例#5
0
    def notify(self, n: int = 1) -> None:
        """Wake ``n`` waiters."""
        waiters = []  # Waiters we plan to run right now.
        while n and self._waiters:
            waiter = self._waiters.popleft()
            if not waiter.done():  # Might have timed out.
                n -= 1
                waiters.append(waiter)

        for waiter in waiters:
            future_set_result_unless_cancelled(waiter, True)
示例#6
0
 def _on_write_complete(self, future: "Future[None]") -> None:
     exc = future.exception()
     if exc is not None and not isinstance(exc, iostream.StreamClosedError):
         future.result()
     if self._write_callback is not None:
         callback = self._write_callback
         self._write_callback = None
         self.stream.io_loop.add_callback(callback)
     if self._write_future is not None:
         future = self._write_future
         self._write_future = None
         future_set_result_unless_cancelled(future, None)
示例#7
0
文件: gen.py 项目: valnar1/SickGear
    def run(self) -> None:
        """Starts or resumes the generator, running until it reaches a
        yield point that is not ready.
        """
        if self.running or self.finished:
            return
        try:
            self.running = True
            while True:
                future = self.future
                if future is None:
                    raise Exception("No pending future")
                if not future.done():
                    return
                self.future = None
                try:
                    exc_info = None

                    try:
                        value = future.result()
                    except Exception:
                        exc_info = sys.exc_info()
                    future = None

                    if exc_info is not None:
                        try:
                            yielded = self.gen.throw(*exc_info)  # type: ignore
                        finally:
                            # Break up a reference to itself
                            # for faster GC on CPython.
                            exc_info = None
                    else:
                        yielded = self.gen.send(value)

                except (StopIteration, Return) as e:
                    self.finished = True
                    self.future = _null_future
                    future_set_result_unless_cancelled(
                        self.result_future, _value_from_stopiteration(e)
                    )
                    self.result_future = None  # type: ignore
                    return
                except Exception:
                    self.finished = True
                    self.future = _null_future
                    future_set_exc_info(self.result_future, sys.exc_info())
                    self.result_future = None  # type: ignore
                    return
                if not self.handle_yield(yielded):
                    return
                yielded = None
        finally:
            self.running = False
示例#8
0
    def detach(self) -> iostream.IOStream:
        """Take control of the underlying stream.

        Returns the underlying `.IOStream` object and stops all further
        HTTP processing.  May only be called during
        `.HTTPMessageDelegate.headers_received`.  Intended for implementing
        protocols like websockets that tunnel over an HTTP handshake.
        """
        self._clear_callbacks()
        stream = self.stream
        self.stream = None  # type: ignore
        if not self._finish_future.done():
            future_set_result_unless_cancelled(self._finish_future, None)
        return stream
示例#9
0
    def put_nowait(self, item: _T) -> None:
        """Put an item into the queue without blocking.

        If no free slot is immediately available, raise `QueueFull`.
        """
        self._consume_expired()
        if self._getters:
            assert self.empty(), "queue non-empty, why are getters waiting?"
            getter = self._getters.popleft()
            self.__put_internal(item)
            future_set_result_unless_cancelled(getter, self._get())
        elif self.full():
            raise QueueFull
        else:
            self.__put_internal(item)
示例#10
0
    def get_nowait(self) -> _T:
        """Remove and return an item from the queue without blocking.

        Return an item if one is immediately available, else raise
        `QueueEmpty`.
        """
        self._consume_expired()
        if self._putters:
            assert self.full(), "queue not full, why are putters waiting?"
            item, putter = self._putters.popleft()
            self.__put_internal(item)
            future_set_result_unless_cancelled(putter, None)
            return self._get()
        elif self.qsize():
            return self._get()
        else:
            raise QueueEmpty
示例#11
0
 def callback(fut: Future) -> None:
     unfinished_children.remove(fut)
     if not unfinished_children:
         result_list = []
         for f in children_futs:
             try:
                 result_list.append(f.result())
             except Exception as e:
                 if future.done():
                     if not isinstance(e, quiet_exceptions):
                         app_log.error("Multiple exceptions in yield list",
                                       exc_info=True)
                 else:
                     future_set_exc_info(future, sys.exc_info())
         if not future.done():
             if keys is not None:
                 future_set_result_unless_cancelled(
                     future, dict(zip(keys, result_list)))
             else:
                 future_set_result_unless_cancelled(future, result_list)
示例#12
0
def sleep(duration: float) -> "Future[None]":
    """Return a `.Future` that resolves after the given number of seconds.

    When used with ``yield`` in a coroutine, this is a non-blocking
    analogue to `time.sleep` (which should not be used in coroutines
    because it is blocking)::

        yield gen.sleep(0.5)

    Note that calling this function on its own does nothing; you must
    wait on the `.Future` it returns (usually by yielding it).

    .. versionadded:: 4.1
    """
    f = _create_future()
    IOLoop.current().call_later(
        duration, lambda: future_set_result_unless_cancelled(f, None))
    return f
示例#13
0
 def close(self) -> None:
     if self.stream is not None:
         self.stream.close()
     self._clear_callbacks()
     if not self._finish_future.done():
         future_set_result_unless_cancelled(self._finish_future, None)
示例#14
0
文件: gen.py 项目: valnar1/SickGear
def multi_future(
    children: Union[List[_Yieldable], Dict[Any, _Yieldable]],
    quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (),
) -> "Union[Future[List], Future[Dict]]":
    """Wait for multiple asynchronous futures in parallel.

    Since Tornado 6.0, this function is exactly the same as `multi`.

    .. versionadded:: 4.0

    .. versionchanged:: 4.2
       If multiple ``Futures`` fail, any exceptions after the first (which is
       raised) will be logged. Added the ``quiet_exceptions``
       argument to suppress this logging for selected exception types.

    .. deprecated:: 4.3
       Use `multi` instead.
    """
    if isinstance(children, dict):
        keys = list(children.keys())  # type: Optional[List]
        children_seq = children.values()  # type: Iterable
    else:
        keys = None
        children_seq = children
    children_futs = list(map(convert_yielded, children_seq))
    assert all(is_future(i) or isinstance(i, _NullFuture) for i in children_futs)
    unfinished_children = set(children_futs)

    future = _create_future()
    if not children_futs:
        future_set_result_unless_cancelled(future, {} if keys is not None else [])

    def callback(fut: Future) -> None:
        unfinished_children.remove(fut)
        if not unfinished_children:
            result_list = []
            for f in children_futs:
                try:
                    result_list.append(f.result())
                except Exception as e:
                    if future.done():
                        if not isinstance(e, quiet_exceptions):
                            app_log.error(
                                "Multiple exceptions in yield list", exc_info=True
                            )
                    else:
                        future_set_exc_info(future, sys.exc_info())
            if not future.done():
                if keys is not None:
                    future_set_result_unless_cancelled(
                        future, dict(zip(keys, result_list))
                    )
                else:
                    future_set_result_unless_cancelled(future, result_list)

    listening = set()  # type: Set[Future]
    for f in children_futs:
        if f not in listening:
            listening.add(f)
            future_add_done_callback(f, callback)
    return future
示例#15
0
 def on_timeout() -> None:
     if not waiter.done():
         future_set_result_unless_cancelled(waiter, False)
     self._garbage_collect()
示例#16
0
 def handle_response(response: "HTTPResponse") -> None:
     if response.error:
         if raise_error or not response._error_is_response_code:
             future_set_exception_unless_cancelled(future, response.error)
             return
     future_set_result_unless_cancelled(future, response)