-
-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
gh-114104: clarify asynchronous comprehension docs to match runtime behavior #121175
Conversation
Fixes #10534 This PR fixes a bug in typechecking asynchronous generators. Mypy currently typechecks a generator/comprehension as `AsyncGenerator` if the leftmost expression contains `await`, or if it contains an `async for`. However, there are other situations where we should get async generator: If there is an `await` expression in any of the conditions or in any sequence except for the leftmost one, the generator/comprehension should also be typechecked as `AsyncGenerator`. I've implemented this change in Mypy and added a test case to assert this behavior. If I enter the test cases into a regular repl, I can confirm that the runtime representation is generator/async_generator as the test case expects. According to the [language reference](https://docs.python.org/3/reference/expressions.html#grammar-token-python-grammar-comp_for): > If a comprehension contains either async for clauses or await expressions or other asynchronous comprehensions it is called an asynchronous comprehension. Confusingly, the documentation itself is actually not quite correct either, as pointed out in python/cpython#114104 Alongside this change, I've made a PR to update the docs to be more precise: python/cpython#121175 has more details.
Thanks for improving this and thanks for the mypy PR as well! |
Doc/reference/expressions.rst
Outdated
:keyword:`!await` expressions anywhere except the iterable expression in the leftmost | ||
:keyword:`!for` clause, or other asynchronous comprehensions, it is called an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"except the iterable expression in the leftmost :keyword:!for
clause" is also applied to "other asynchronous comprehensions".
For example:
(x for x in foo(y async for y in a))
Here the "for x" comprehension expression is not asynchronous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Thanks @yangdanny97 for the PR, and @kumaraditya303 for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12, 3.13. |
…time behavior (pythonGH-121175) (cherry picked from commit 91313af) Co-authored-by: Danny Yang <yangdanny97@users.noreply.github.com>
…time behavior (pythonGH-121175) (cherry picked from commit 91313af) Co-authored-by: Danny Yang <yangdanny97@users.noreply.github.com>
GH-121234 is a backport of this pull request to the 3.13 branch. |
GH-121235 is a backport of this pull request to the 3.12 branch. |
The documentation currently states:
According to the #114104,
await
in the leftmost sequence of a comprehension does not make it an asynchronous comprehension, and the comments indicate that this is the intended behavior.This PR updates the documentation to reflect that.
await
are compiled to async generators #114104📚 Documentation preview 📚: https://cpython-previews--121175.org.readthedocs.build/