Skip to content

Commit

Permalink
Merge pull request tornadoweb#1890 from pitrou/coroutine_introspection
Browse files Browse the repository at this point in the history
Improve introspection of coroutines
  • Loading branch information
bdarnell authored Nov 20, 2016
2 parents 6f73e9b + e068d99 commit f31750f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/gen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@

.. autofunction:: maybe_future

.. autofunction:: is_coroutine_function

Legacy interface
----------------

Expand Down
13 changes: 12 additions & 1 deletion tornado/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,11 @@ def _make_coroutine_wrapper(func, replace_callback):
"""
# On Python 3.5, set the coroutine flag on our generator, to allow it
# to be used with 'await'.
wrapped = func
if hasattr(types, 'coroutine'):
func = types.coroutine(func)

@functools.wraps(func)
@functools.wraps(wrapped)
def wrapper(*args, **kwargs):
future = TracebackFuture()

Expand Down Expand Up @@ -328,9 +329,19 @@ def wrapper(*args, **kwargs):
future = None
future.set_result(result)
return future

wrapper.__wrapped__ = wrapped
wrapper.__tornado_coroutine__ = True
return wrapper


def is_coroutine_function(func):
"""Return whether *func* is a coroutine function, i.e. a function
wrapped with `~.gen.coroutine`.
"""
return getattr(func, '__tornado_coroutine__', False)


class Return(Exception):
"""Special exception to return a value from a `coroutine`.
Expand Down
22 changes: 22 additions & 0 deletions tornado/test/gen_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,28 @@ def tearDown(self):
super(GenCoroutineTest, self).tearDown()
assert self.finished

def test_attributes(self):
self.finished = True

def f():
yield gen.moment

coro = gen.coroutine(f)
self.assertEqual(coro.__name__, f.__name__)
self.assertEqual(coro.__module__, f.__module__)
self.assertIs(coro.__wrapped__, f)

def test_is_coroutine_function(self):
self.finished = True

def f():
yield gen.moment

coro = gen.coroutine(f)
self.assertFalse(gen.is_coroutine_function(f))
self.assertTrue(gen.is_coroutine_function(coro))
self.assertFalse(gen.is_coroutine_function(coro()))

@gen_test
def test_sync_gen_return(self):
@gen.coroutine
Expand Down

0 comments on commit f31750f

Please sign in to comment.