Skip to content
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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

ssanderson
Copy link
Owner

For #15. cc @touilleMan

def is_coroutine(f):
return False
else:
def is_coroutine(f):

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 ?

Copy link
Owner Author

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).

Copy link
Owner Author

@ssanderson ssanderson May 16, 2018

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

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. calling types_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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants