Repository navigation
trio_asyncio.open_loop() in a fixture? #71
Copy link
Copy link
Open
Description
I hoped to be able to do the following for my test cases requiring trio-asyncio:
@pytest_trio.trio_fixture
async def trio_aio_loop():
async with trio_asyncio.open_loop() as loop:
yield loop
@pytest.mark.trio
async def test_aio_funcs(trio_aio_loop, autojump_clock):
@trio_asyncio.aio_as_trio
async def func():
await asyncio.sleep(0.1)
return 1
assert await func() == 1
However the fixture blows up:
test setup failed
@pytest_trio.trio_fixture
async def trio_aio_loop():
> async with trio_asyncio.open_loop() as loop:
tests/test_loop.py:261:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.../env/lib/python3.7/site-packages/async_generator/_util.py:34: in __aenter__
return await self._agen.asend(None)
.../env/lib/python3.7/site-packages/async_generator/_impl.py:366: in step
return await ANextIter(self._it, start_fn, *args)
.../env/lib/python3.7/site-packages/async_generator/_impl.py:197: in __next__
return self._invoke(first_fn, *first_args)
.../env/lib/python3.7/site-packages/async_generator/_impl.py:209: in _invoke
result = fn(*args)
.../env/lib/python3.7/site-packages/trio_asyncio/async_.py:108: in open_loop
async with trio.open_nursery() as nursery:
.../env/lib/python3.7/site-packages/trio/_core/_run.py:378: in __aenter__
self._scope = CancelScope._create(deadline=inf, shield=False)
.../env/lib/python3.7/site-packages/trio/_core/_run.py:130: in _create
task = _core.current_task()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def current_task():
"""Return the :class:`Task` object representing the current task.
Returns:
Task: the :class:`Task` that called :func:`current_task`.
"""
try:
return GLOBAL_RUN_CONTEXT.task
except AttributeError:
> raise RuntimeError("must be called from async context") from None
E RuntimeError: must be called from async context
.../env/lib/python3.7/site-packages/trio/_core/_run.py:1534: RuntimeError
I assume that has to do something with the description of fixture handling here (I admit not having read it in full). It seems rather intricate, so I have no idea how hard this would be to fix. I think it would be a valuable addition, though.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
touilleMan commentedon Jan 11, 2019
Hi,
You should have a look here:
https://github.com/Scille/parsec-cloud/blob/e1e25366d07425312712c01950440476a7322608/tests/conftest.py#L133-L140
Btw trio-asyncio is tricky because it creates relationship between two event loops, which can end up in hard to track deadlocks. For instance you should avoid using the
nurseryfitxure along with anasyncio_loopfixture (because there are both disconnected from trio point of view, but once theasyncio_loopis torndown, coroutines belonging to thenurseryfixture and using asyncio code won't work anymore without explanation...)ensko commentedon Jan 11, 2019
thanks for the hint! could you very shortly explain why it has to be
@pytest.fixtureinstead of@pytest_trio.trio_fixture, even thoughtrio_asyncio.open_loop()is a trio-style async context manager? The shielded cancel scope is separate from that, for the issue you pointed out above, right?touilleMan commentedon Jan 12, 2019
@SillyFreak
@pytest_trio.trio_fixtureis just a small wrapper around@pytest.fixtureto flag the test using it as trio (in my tests I use the@pytest.mark.triodecorator to add this trio flag)njsmith commentedon Jan 12, 2019
If you have trio-mode enabled, then
@pytest.fixtureand@pytest_trio.trio_fixtureare equivalent when applied to anasync def; it doesn't matter which one you use. You can also use@pytest_trio.trio_fixtureon synchronous fixtures, or when trio mode isn't enabled, and in that case it makes a difference.lordi commentedon Feb 2, 2019
I think we currently can't use
trio_asyncio.open_loopat all withpytest_trio, because it would require that the test is ran withtrio_asyncio.runinstead oftrio.run. Is that assumption correct?njsmith commentedon Feb 2, 2019
@lordi No,
trio_asyncio.runis just a confusing shorthand for doingtrio.runand thentrio_asyncio.open_loop. So you don't need it; you can just doopen_loopyourself. I'm not sure why we havetrio_asyncio.run, honestly; trio_asyncio's core is pretty solid but the API still needs some fine tuning.lordi commentedon Feb 2, 2019
Ok, thanks, that's good to know.
jmehnle commentedon Aug 12, 2024
Did anything change since 2019? I'm using this fixture, and it is working just fine:
BTW, I ran across #105. Would it make sense to offer another value, say,
trio_asyncio, for thetrio_runini option?oremanj commentedon Aug 12, 2024
I'm not sure why the original poster ran into trouble, but I agree a fixture like you describe should work fine. I think the shield shouldn't be necessary anymore after some recent improvements to trio-asyncio (there's now a bunch of careful shielding inside
open_loop) but I don't think it will do any harm either.Yeah that seems like a pretty easy win!
Support `trio_run = trio_asyncio` ini option.
jmehnle commentedon Aug 12, 2024
Please consider #146.
seowalex commentedon Sep 2, 2025
It looks like this is still not solved, are there any blockers to merging the above PR?