mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 02:38:25 +00:00
[syntax-errors] Async comprehension in sync comprehension (#17177)
Some checks are pending
CI / cargo build (msrv) (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / cargo build (msrv) (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
Summary -- Detect async comprehensions nested in sync comprehensions in async functions before Python 3.11, when this was [changed]. The actual logic of this rule is very straightforward, but properly tracking the async scopes took a bit of work. An alternative to the current approach is to offload the `in_async_context` check into the `SemanticSyntaxContext` trait, but that actually required much more extensive changes to the `TestContext` and also to ruff's semantic model, as you can see in the changes up to 31554b473507034735bd410760fde6341d54a050. This version has the benefit of mostly centralizing the state tracking in `SemanticSyntaxChecker`, although there was some subtlety around deferred function body traversal that made the changes to `Checker` more intrusive too (hence the new linter test). The `Checkpoint` struct/system is obviously overkill for now since it's only tracking a single `bool`, but I thought it might be more useful later. [changed]: https://github.com/python/cpython/issues/77527 Test Plan -- New inline tests and a new linter integration test.
This commit is contained in:
parent
dc02732d4d
commit
058439d5d3
18 changed files with 2076 additions and 28 deletions
|
@ -0,0 +1,6 @@
|
|||
# parse_options: {"target-version": "3.10"}
|
||||
async def f(): return [[x async for x in foo(n)] for n in range(3)] # list
|
||||
async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
|
||||
async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
||||
async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)]
|
||||
async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)]
|
|
@ -0,0 +1,2 @@
|
|||
# parse_options: {"target-version": "3.10"}
|
||||
async def test(): return [[x async for x in elements(n)] async for n in range(3)]
|
|
@ -0,0 +1,9 @@
|
|||
# parse_options: {"target-version": "3.10"}
|
||||
# this case fails if exit_expr doesn't run
|
||||
async def f():
|
||||
[_ for n in range(3)]
|
||||
[_ async for n in range(3)]
|
||||
# and this fails without exit_stmt
|
||||
async def f():
|
||||
def g(): ...
|
||||
[_ async for n in range(3)]
|
|
@ -0,0 +1,4 @@
|
|||
# parse_options: {"target-version": "3.11"}
|
||||
async def f(): return [[x async for x in foo(n)] for n in range(3)] # list
|
||||
async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
|
||||
async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
Loading…
Add table
Add a link
Reference in a new issue