Skip to content
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

warn when the type hint of an async generator is not AsyncGenerator #233

Open
graingert opened this issue Apr 9, 2024 · 7 comments
Open
Labels
postponed Low priority, blocked, or similar.

Comments

@graingert
Copy link
Member

Typing an async generator as AsyncIterator or AsyncIterable prevents wrapping it with contextlib.aclosing

@Zac-HD
Copy link
Member

Zac-HD commented Apr 9, 2024

Sure, why not 🙂

Although I'll note that even if you correctly use with aclosing(...) as ait: in every single scope, you still have to avoid ever yielding across a cancel scope.

@jakkdl
Copy link
Member

jakkdl commented Apr 12, 2024

I see two different ways of implementing this:

  1. Give an error any time AsyncIterator or AsyncIterable is used as return type.
  2. Detect async generators by looking for async methods with a yield inside (except if that's a nested function), and give an error if there is a return type and it is not AsyncGenerator.

1 is significantly simpler to implement, avoids false positives, and sounds like it resolves the issue just as well? Whereas the title of the issue implies 2.

@Zac-HD
Copy link
Member

Zac-HD commented Apr 12, 2024

(1) fails for functions which return a ReceiveChannel, though.

I'd treat this as a distinctly low priority issue since it's nontrivial to implement and I prefer to ban async generators anyway, but no objection if someone wants to contribute it.

@alicederyn
Copy link

This should probably not trigger for functions decorated with @pytest.fixture as AsyncIterator is just fine there.

@graingert
Copy link
Member Author

graingert commented Apr 19, 2024

Not if you're using pytest-trio - the yield can raise trio.Cancelled https://pytest-trio.readthedocs.io/en/stable/reference.html#an-important-note-about-yield-fixtures

Now, here’s the punchline: this means that in our examples above, the teardown code might not be executed at all! This is different from how pytest fixtures normally work. Normally, the yield in a pytest fixture never raises an exception, so you can be certain that any code you put after it will execute as normal. But if you have a fixture with background tasks, and they crash, then your yield might raise an exception, and Python will skip executing the code after the yield.

This means the fixture function needs to return something with .athrow()

@alicederyn
Copy link

That sounds like a severe bug in pytest-trio.

@jakkdl jakkdl added the postponed Low priority, blocked, or similar. label May 24, 2024
@Zac-HD
Copy link
Member

Zac-HD commented May 27, 2024

No, that seems fine to me? The docs are a bit odd, but this is just like applying @asynccontextmanager.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
postponed Low priority, blocked, or similar.
Projects
None yet
Development

No branches or pull requests

4 participants