-
Notifications
You must be signed in to change notification settings - Fork 17
ENH: Enforce that sync-ness matches. #17
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
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.coroutinegenerate a coroutine but inspect module doesn't realize this... I guess it's a bug - using
types.coroutinedoesn't even turn the function into a coroutine function (i.e. callingtypes_coroutinein 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