diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fabc57b9c2..2732712eb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -204,6 +204,40 @@ jobs: name: Alpine flags: Alpine,3.12 + Cython: + name: "Cython" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python: ['3.8', '3.12'] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: '${{ matrix.python }}' + cache: pip + # setuptools is needed to get distutils on 3.12, which cythonize requires + - name: install trio and setuptools + run: python -m pip install --upgrade pip . setuptools + + - name: install cython<3 + run: python -m pip install "cython<3" + - name: compile pyx file + run: cythonize -i tests/cython/test_cython.pyx + - name: import & run module + run: python -c 'import tests.cython.test_cython' + + - name: install cython>=3 + run: python -m pip install "cython>=3" + - name: compile pyx file + # different cython version should trigger a re-compile, but --force just in case + run: cythonize --inplace --force tests/cython/test_cython.pyx + - name: import & run module + run: python -c 'import tests.cython.test_cython' + # https://github.com/marketplace/actions/alls-green#why check: # This job does nothing and is only used for the branch protection @@ -214,6 +248,7 @@ jobs: - Ubuntu - macOS - Alpine + - Cython runs-on: ubuntu-latest diff --git a/src/trio/_core/_run.py b/src/trio/_core/_run.py index 9ed301815a..c5d6b65712 100644 --- a/src/trio/_core/_run.py +++ b/src/trio/_core/_run.py @@ -1767,6 +1767,7 @@ def spawn_impl( except AttributeError: name = repr(name) + # very old Cython versions (<0.29.24) has the attribute, but with a value of None if getattr(coro, "cr_frame", None) is None: # This async function is implemented in C or Cython async def python_wrapper(orig_coro: Awaitable[RetT]) -> RetT: diff --git a/tests/cython/test_cython.pyx b/tests/cython/test_cython.pyx new file mode 100644 index 0000000000..b836caf90c --- /dev/null +++ b/tests/cython/test_cython.pyx @@ -0,0 +1,22 @@ +# cython: language_level=3 +import trio + +# the output of the prints are not currently checked, we only check +# if the program can be compiled and doesn't crash when run. + +# The content of the program can easily be extended if there's other behaviour +# that might be likely to be problematic for cython. +async def foo() -> None: + print('.') + +async def trio_main() -> None: + print('hello...') + await trio.sleep(1) + print(' world !') + + async with trio.open_nursery() as nursery: + nursery.start_soon(foo) + nursery.start_soon(foo) + nursery.start_soon(foo) + +trio.run(trio_main)