return None
+def _create_future():
+ future = Future()
+ # Fixup asyncio debug info by removing extraneous stack entries
+ source_traceback = getattr(future, "_source_traceback", ())
+ while source_traceback:
+ # Each traceback entry is equivalent to a
+ # (filename, self.lineno, self.name, self.line) tuple
+ filename = source_traceback[-1][0]
+ if filename == __file__:
+ del source_traceback[-1]
+ else:
+ break
+ return future
+
+
def engine(func):
"""Callback-oriented decorator for asynchronous generators.
@functools.wraps(wrapped)
def wrapper(*args, **kwargs):
- future = Future()
+ future = _create_future()
if replace_callback and 'callback' in kwargs:
callback = kwargs.pop('callback')
orig_stack_contexts = stack_context._state.contexts
yielded = next(result)
if stack_context._state.contexts is not orig_stack_contexts:
- yielded = Future()
+ yielded = _create_future()
yielded.set_exception(
stack_context.StackContextInconsistentError(
'stack_context inconsistency (probably caused '
a subclass of `YieldPoint`. It still behaves the same way when
yielded.
"""
- future = Future()
+ future = _create_future()
def handle_exception(typ, value, tb):
if future.done():
assert all(is_future(i) for i in children)
unfinished_children = set(children)
- future = Future()
+ future = _create_future()
if not children:
future.set_result({} if keys is not None else [])
if is_future(x):
return x
else:
- fut = Future()
+ fut = _create_future()
fut.set_result(x)
return fut
# callers and B) concurrent futures can only be cancelled while they are
# in the queue, so cancellation cannot reliably bound our waiting time.
future = convert_yielded(future)
- result = Future()
+ result = _create_future()
chain_future(future, result)
io_loop = IOLoop.current()
.. versionadded:: 4.1
"""
- f = Future()
+ f = _create_future()
IOLoop.current().call_later(duration, lambda: f.set_result(None))
return f
except ImportError:
futures = None
+try:
+ import asyncio
+except ImportError:
+ asyncio = None
+
class GenEngineTest(AsyncTestCase):
def setUp(self):
self.assertIs(self.local_ref(), None)
self.finished = True
+ @unittest.skipIf(sys.version_info < (3,),
+ "test only relevant with asyncio Futures")
+ def test_asyncio_future_debug_info(self):
+ self.finished = True
+ # Enable debug mode
+ asyncio_loop = asyncio.get_event_loop()
+ self.addCleanup(asyncio_loop.set_debug, asyncio_loop.get_debug())
+ asyncio_loop.set_debug(True)
+
+ def f():
+ yield gen.moment
+
+ coro = gen.coroutine(f)()
+ self.assertIsInstance(coro, asyncio.Future)
+ # We expect the coroutine repr() to show the place where
+ # it was instantiated
+ expected = ("created at %s:%d"
+ % (__file__, f.__code__.co_firstlineno + 3))
+ actual = repr(coro)
+ self.assertIn(expected, actual)
+
class GenSequenceHandler(RequestHandler):
@asynchronous