-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
ENH: Enforce that sync-ness matches. #17
base: master
Are you sure you want to change the base?
Conversation
def is_coroutine(f): | ||
return False | ||
else: | ||
def is_coroutine(f): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not using inspect.iscoroutinefunction instead ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iscoroutinefunction
only checks if a function was defined as an async def
by looking at the CO_COROUTINE
flag on the code object. For older codebases with lots of yield from
coroutines, there's also the types.coroutine
decorator, which sets a different flag, CO_ITERABLE_COROUTINE
. This implementation handles both styles (and treats them as equivalent).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though, from reading the docs for iscoroutinefunction
, I think it's just a bug that it doesn't handle types.coroutine
functions correctly...
In [1]: from inspect import iscoroutinefunction
In [2]: iscoroutinefunction??
Signature: iscoroutinefunction(object)
Source:
def iscoroutinefunction(object):
"""Return true if the object is a coroutine function.
Coroutine functions are defined with "async def" syntax,
or generators decorated with "types.coroutine".
"""
return bool((isfunction(object) or ismethod(object)) and
object.__code__.co_flags & CO_COROUTINE)
File: /usr/lib/python3.5/inspect.py
Type: function
In [3]: import types
In [4]: @types.coroutine
...: def foo():
...: yield 3
...:
In [5]: iscoroutinefunction(foo)
Out[5]: False
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, it seems a bit more messy than what I originally thought:
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio, types, inspect
>>> asyncio.coroutine is types.coroutine
False
>>> @asyncio.coroutine
... def asyncio_coroutine():
... return 'foo'
...
>>> asyncio_coroutine()
<generator object asyncio_coroutine at 0x7f532573cdb0>
>>> inspect.iscoroutinefunction(asyncio_coroutine)
False
>>> inspect.iscoroutine(asyncio_coroutine())
False
>>> @types.coroutine
... def types_coroutine():
... return 'foo'
...
>>> types_coroutine()
'foo'
>>> inspect.iscoroutinefunction(types_coroutine)
False
>>> inspect.iscoroutine(types_coroutine())
False
>>> async def async_func():
... return 'foo'
...
>>> async_func()
<coroutine object async_func at 0x7f532573cdb0>
>>> inspect.iscoroutinefunction(async_func)
True
>>> inspect.iscoroutine(async_func())
True
So basically:
- using
async def foo()
works as expected - using
asyncio.coroutine
generate a coroutine but inspect module doesn't realize this... I guess it's a bug - using
types.coroutine
doesn't even turn the function into a coroutine function (i.e. callingtypes_coroutine
in the example returns the result instead of a coroutine), this is definitely a bug !
Note that I've done this test with CPython 3.5.2 and 3.6.3, both giving the same result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've realized I made a mistake with types.coroutine
which must take a generator function (I was testing with a regular function).
So my last bullet point was wrong, but anyway inspect doesn't work with it:
>>> import asyncio, types, inspect
>>> @types.coroutine
... def types_coroutine():
... yield 42
...
>>> types_coroutine()
<generator object types_coroutine at 0x7f36577fff68>
>>> inspect.iscoroutinefunction(types_coroutine)
False
>>> inspect.iscoroutine(types_coroutine())
False
For #15. cc @touilleMan