Skip to content

Support Cython-based async functions #550

@touilleMan

Description

@touilleMan

The title say it all, some projects re-implement their own iscoroutine function by looking for CO_COROUTINE and CO_ITERABLE_COROUTINE flags (for instance) to address this...

This is more of a CPython issue of course, but this currently means the coroutine generated by cython are not compatible with trio:

import trio

async def trio_main():
    print('hello...')
    await trio.sleep(1)
    print(' world !')

def main():
    trio.run(trio_main)

if __name__ == '__main__':
    main()
$ python cython_test.py 
hello...
 world !
$ cythonize -a -i cython_test.py 
Compiling /home/emmanuel/projects/parsec-lrw/cython_test.py because it changed.
[1/1] Cythonizing /home/emmanuel/projects/parsec-lrw/cython_test.py
running build_ext
building 'cython_test' extension
creating /home/emmanuel/projects/parsec-lrw/tmp0p_t5pyt/home
creating /home/emmanuel/projects/parsec-lrw/tmp0p_t5pyt/home/emmanuel
creating /home/emmanuel/projects/parsec-lrw/tmp0p_t5pyt/home/emmanuel/projects
creating /home/emmanuel/projects/parsec-lrw/tmp0p_t5pyt/home/emmanuel/projects/parsec-lrw
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/emmanuel/projects/cpython/build-install/include/python3.6m -c /home/emmanuel/projects/parsec-lrw/cython_test.c -o /home/emmanuel/projects/parsec-lrw/tmp0p_t5pyt/home/emmanuel/projects/parsec-lrw/cython_test.o
gcc -pthread -shared /home/emmanuel/projects/parsec-lrw/tmp0p_t5pyt/home/emmanuel/projects/parsec-lrw/cython_test.o -o /home/emmanuel/projects/parsec-lrw/cython_test.cpython-36m-x86_64-linux-gnu.so
$ python 
Python 3.6.3 (v3.6.3:2c5fed8, Feb  6 2018, 17:05:14) 
[GCC 5.4.1 20160904] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cython_test
>>> cython_test.main()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cython_test.py", line 10, in cython_test.main
    trio.run(trio_main)
  File "/home/emmanuel/projects/parsec-lrw/venv/lib/python3.6/site-packages/trio/_core/_run.py", line 1238, in run
    return result.unwrap()
  File "/home/emmanuel/projects/parsec-lrw/venv/lib/python3.6/site-packages/trio/_core/_result.py", line 119, in unwrap
    raise self.error
  File "/home/emmanuel/projects/parsec-lrw/venv/lib/python3.6/site-packages/trio/_core/_run.py", line 1347, in run_impl
    msg = task.context.run(task.coro.send, next_send)
  File "/home/emmanuel/projects/parsec-lrw/venv/lib/python3.6/site-packages/contextvars/__init__.py", line 38, in run
    return callable(*args, **kwargs)
  File "/home/emmanuel/projects/parsec-lrw/venv/lib/python3.6/site-packages/trio/_core/_run.py", line 934, in init
    async_fn, args, system_nursery, None
  File "/home/emmanuel/projects/parsec-lrw/venv/lib/python3.6/site-packages/trio/_core/_run.py", line 805, in spawn_impl
    .format(getattr(async_fn, "__qualname__", async_fn))
TypeError: trio expected an async function, but 'trio_main' appears to be synchronous

I didn't dig into CPython internal so my understanding on why inspect.iscoroutine != asyncio.iscoroutine on this is fairly limited, but I guess we should do something on our own to fix this anyway ;-)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions