-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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