Example #1
0
 def errback(failure):
     try:
         failure.raiseException()
         # Should never happen, but just in case
         raise Exception("errback called without error")
     except:
         future_set_exc_info(f, sys.exc_info())
Example #2
0
 def handle_exception(self, typ, value, tb):
     if not self.running and not self.finished:
         self.future = Future()
         future_set_exc_info(self.future, (typ, value, tb))
         self.run()
         return True
     else:
         return False
Example #3
0
    def handle_yield(self, yielded):
        # Lists containing YieldPoints require stack contexts;
        # other lists are handled in convert_yielded.
        if _contains_yieldpoint(yielded):
            yielded = multi(yielded)

        if isinstance(yielded, YieldPoint):
            # YieldPoints are too closely coupled to the Runner to go
            # through the generic convert_yielded mechanism.
            self.future = Future()

            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        future_set_result_unless_cancelled(
                            self.future, yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = Future()
                    future_set_exc_info(self.future, sys.exc_info())

            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate

                    def cb():
                        start_yield_point()
                        self.run()

                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        else:
            try:
                self.future = convert_yielded(yielded)
            except BadYieldError:
                self.future = Future()
                future_set_exc_info(self.future, sys.exc_info())

        if self.future is moment:
            self.io_loop.add_callback(self.run)
            return False
        elif not self.future.done():

            def inner(f):
                # Break a reference cycle to speed GC.
                f = None  # noqa
                self.run()

            self.io_loop.add_future(self.future, inner)
            return False
        return True
Example #4
0
 def start_yield_point():
     try:
         yielded.start(self)
         if yielded.is_ready():
             future_set_result_unless_cancelled(
                 self.future, yielded.get_result())
         else:
             self.yield_point = yielded
     except Exception:
         self.future = Future()
         future_set_exc_info(self.future, sys.exc_info())
Example #5
0
 def set_result(self, key, result):
     """Sets the result for ``key`` and attempts to resume the generator."""
     self.results[key] = result
     if self.yield_point is not None and self.yield_point.is_ready():
         try:
             future_set_result_unless_cancelled(
                 self.future, self.yield_point.get_result())
         except:
             future_set_exc_info(self.future, sys.exc_info())
         self.yield_point = None
         self.run()
Example #6
0
 def run():
     try:
         result = func()
         if result is not None:
             from tornado_py2.gen import convert_yielded
             result = convert_yielded(result)
     except Exception:
         future_cell[0] = Future()
         future_set_exc_info(future_cell[0], sys.exc_info())
     else:
         if is_future(result):
             future_cell[0] = result
         else:
             future_cell[0] = Future()
             future_cell[0].set_result(result)
     self.add_future(future_cell[0], lambda future: self.stop())
Example #7
0
 def callback(f):
     unfinished_children.remove(f)
     if not unfinished_children:
         result_list = []
         for f in children:
             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)
Example #8
0
 def handle_exception(typ, value, tb):
     if future.done():
         return False
     else:
         future_set_exc_info(future, (typ, value, tb))
         return True
Example #9
0
    def wrapper(*args, **kwargs):
        future = _create_future()

        if replace_callback and 'callback' in kwargs:
            warnings.warn(
                "callback arguments are deprecated, use the returned Future instead",
                DeprecationWarning,
                stacklevel=2)
            callback = kwargs.pop('callback')
            IOLoop.current().add_future(
                future, lambda future: callback(future.result()))

        try:
            result = 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
        else:
            if isinstance(result, GeneratorType):
                # 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:
                    orig_stack_contexts = stack_context._state.contexts
                    yielded = next(result)
                    if stack_context._state.contexts is not orig_stack_contexts:
                        yielded = _create_future()
                        yielded.set_exception(
                            stack_context.StackContextInconsistentError(
                                'stack_context inconsistency (probably caused '
                                'by yield within a "with StackContext" block)')
                        )
                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(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
        future_set_result_unless_cancelled(future, result)
        return future
Example #10
0
    def run(self):
        """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 not future.done():
                    return
                self.future = None
                try:
                    orig_stack_contexts = stack_context._state.contexts
                    exc_info = None

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

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

                    if stack_context._state.contexts is not orig_stack_contexts:
                        self.gen.throw(
                            stack_context.StackContextInconsistentError(
                                'stack_context inconsistency (probably caused '
                                'by yield within a "with StackContext" block)')
                        )
                except (StopIteration, Return) as e:
                    self.finished = True
                    self.future = _null_future
                    if self.pending_callbacks and not self.had_exception:
                        # If we ran cleanly without waiting on all callbacks
                        # raise an error (really more of a warning).  If we
                        # had an exception then some callbacks may have been
                        # orphaned, so skip the check in that case.
                        raise LeakedCallbackError(
                            "finished without waiting for callbacks %r" %
                            self.pending_callbacks)
                    future_set_result_unless_cancelled(
                        self.result_future, _value_from_stopiteration(e))
                    self.result_future = None
                    self._deactivate_stack_context()
                    return
                except Exception:
                    self.finished = True
                    self.future = _null_future
                    future_set_exc_info(self.result_future, sys.exc_info())
                    self.result_future = None
                    self._deactivate_stack_context()
                    return
                if not self.handle_yield(yielded):
                    return
                yielded = None
        finally:
            self.running = False