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

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

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

Successfully merging this pull request may close these issues.

2 participants