Open mikenerone opened 3 years ago
I guess this has the same cause as #123 -- we're not properly querying pytest to figure out the list of fixtures. I would guess fixing one would also fix the other.
I just got bit by this too. Min viable reproduction, in case it's useful as a testcase somewhere (though probably not because of the added trio_asyncio dep):
import asyncio
import pytest
import trio
import trio_asyncio
@pytest.fixture
async def trio_asyncio_loop():
# When a ^C happens, trio send a Cancelled exception to each running
# coroutine. We must protect this one to avoid deadlock if it is cancelled
# before another coroutine that uses trio-asyncio.
with trio.CancelScope(shield=True):
async with trio_asyncio.open_loop() as loop:
yield loop
@pytest.mark.usefixtures('trio_asyncio_loop')
class TestMetatest:
async def test_the_thing(self):
await trio_asyncio.aio_as_trio(asyncio.sleep)(0)
For posterity / any wandering googlers travelers:
_____________________________________________________________________________________________________________________________ TestMetatest.test_the_thing ______________________________________________________________________________________________________________________________
self = <tests.unittests.datastores.test_postgres.TestMetatest object at 0x7fbd4be01af0>
async def test_the_thing(self):
from trio_asyncio import aio_as_trio
> await aio_as_trio(asyncio.sleep)(0)
tests/unittests/datastores/test_postgres.py:21:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <trio_asyncio._adapter.Asyncio_Trio_Wrapper object at 0x7fbd4be319d0>, args = (0,), kwargs = {}, f = <coroutine object _call_defer at 0x7fbd4bd56c00>
async def __call__(self, *args, **kwargs):
if self.args:
raise RuntimeError("Call 'aio_as_trio(proc)(*args)', not 'aio_as_trio(proc, *args)'")
# We route this through _calL_defer because some wrappers require
# running in asyncio context
f = _call_defer(self.proc, *args, **kwargs)
> return await self.loop.run_aio_coroutine(f)
E AttributeError: 'NoneType' object has no attribute 'run_aio_coroutine'
The workaround is simple, though not DRY:
class TestMetatest:
# Explicitly call for the fixture on every test case instead of using mark.usefixtures
async def test_the_thing(self, trio_asyncio_loop):
await trio_asyncio.aio_as_trio(asyncio.sleep)(0)
Async fixtures can't be used in
@pytest.mark.usefixtures(...)
decorators. I'm sure this is a side-effect of the trio-fixture workaround approach explained in the docs, but it should be possible to examine the test function's marks and honor them.