-
Notifications
You must be signed in to change notification settings - Fork 160
Fix bug when entering/exiting task group as part of different asyncio tasks #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bug when entering/exiting task group as part of different asyncio tasks #75
Conversation
I do not expect I will merge this, as I have my own fix underway which also tests all backends, not just asyncio. |
This brings to light a fairly big issue: say task A enters the cancel scope and then hits a yield. Then another task resumes the generator. Next, a spawned task crashes. The host task must now be cancelled, but how do we get the host task now? |
I tested this on trio and it simply crashes with a |
Although anyio currently trips on |
This has been a problem for quite a while: https://discuss.python.org/t/preventing-yield-inside-certain-context-managers/1091/13 |
Oh, that was interesting, thanks. (The correct link is: https://discuss.python.org/t/preventing-yield-inside-certain-context-managers/1091/13)
It seems it doesn't have to be that way. Along the way I came across these docs on If I uninstall import anyio
import pytest_trio
@pytest_trio.trio_fixture
async def client():
async with anyio.create_task_group() as tg:
yield "client"
async def test_something(client):
pass Then I get an exception ( But as soon as I add |
There is already a bug open against pytest-asyncio about this issue: pytest-dev/pytest-asyncio#124 |
Well, I'm not @florimondmanca but on my system I have a heap of normally-benign modules installed so that I can test various stuff while I develop (and thus break) things. Requiring the removal (or reinstallation) of pytest-asyncio is no fun. Worse, I can't test that the module I'm writing works in a "pure" asyncio environment and in one that's running under trio, asyncio+anyio, and/or whatever. |
That is unfortunate, but there is little I can do about the invasive behavior of pytest-asyncio. You can of course use AnyIO's pytest plugin to test your pure async stuff, as it only acts as a light wrapper around |
Nice, thanks. There’s even a pending PR attempting to solve it: pytest-dev/pytest-asyncio#125
I was providing a code snippet to someone who runs on pytest-asyncio, and one of the components in that snippet uses anyio under the hood. I would assume this will be a common situation unless we propagate the need to know about anyio (use the anyio plugin) up to anyone who depends on anything that uses anyio. The compatibility layer at the run function level is looking good already, this is just one edge case that I think needs fixing on the pytest-asyncio side. |
Fixing #74 will at least let people use task groups inside async fixtures. But the handling of exceptions from tasks spawned from those task groups is still a tricky problem. |
There is also the problem of async fixtures with the |
I now understand the reason why the asyncio test run did not show as failing. This is because |
@agronholm Exactly — the fixture gets torn down by running the second part of the async generator, but that fails and so the test is marked as errorred, when it would have ended up being marked as skipped otherwise. |
No, I think you misunderstood. The reason why my test passed on asyncio (even though it shouldn't have) is that the cancel scope is both entered and exited during test setup (due to the semantics of |
I need to look at both trio and curio codebases to see how they handle this. |
I don't think trio shuts down async generators at the end, and neither does curio. |
Is there any branch or PR where the tests you’re mentioning are available to look at? Would help me better follow the discussion here. I thought you were mentioning the original issue in #74. :) |
Closing in favor of #76. |
Fixes #74