mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 10:48:32 +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,823 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/err/nested_async_comprehension_py310.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..467,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 44..111,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("f"),
|
||||
range: 54..55,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 55..57,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 59..111,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 66..111,
|
||||
elt: ListComp(
|
||||
ExprListComp {
|
||||
range: 67..92,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 68..69,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 70..91,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 80..81,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 85..91,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 85..88,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 88..91,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 89..90,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 93..110,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 97..98,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 102..110,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 102..107,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 107..110,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 108..109,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 122..192,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("g"),
|
||||
range: 132..133,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 133..135,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 137..192,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 144..192,
|
||||
elt: DictComp(
|
||||
ExprDictComp {
|
||||
range: 145..173,
|
||||
key: Name(
|
||||
ExprName {
|
||||
range: 146..147,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 149..150,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 151..172,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 161..162,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 166..172,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 166..169,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 169..172,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 170..171,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 174..191,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 178..179,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 183..191,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 183..188,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 188..191,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 189..190,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 200..267,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("h"),
|
||||
range: 210..211,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 211..213,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 215..267,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 222..267,
|
||||
elt: SetComp(
|
||||
ExprSetComp {
|
||||
range: 223..248,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 224..225,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 226..247,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 236..237,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 241..247,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 241..244,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 244..247,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 245..246,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 249..266,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 253..254,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 258..266,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 258..263,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 263..266,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 264..265,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 277..371,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("i"),
|
||||
range: 287..288,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 288..290,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 292..371,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 299..371,
|
||||
elt: Tuple(
|
||||
ExprTuple {
|
||||
range: 300..352,
|
||||
elts: [
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 301..328,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 302..303,
|
||||
id: Name("y"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 304..327,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 314..315,
|
||||
id: Name("y"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 319..327,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 319..324,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 324..327,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 325..326,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 330..351,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 331..332,
|
||||
id: Name("z"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 333..350,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 337..338,
|
||||
id: Name("z"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 342..350,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 342..347,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 347..350,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 348..349,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: true,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 353..370,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 357..358,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 362..370,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 362..367,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 367..370,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 368..369,
|
||||
value: Int(
|
||||
5,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 372..466,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("j"),
|
||||
range: 382..383,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 383..385,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 387..466,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 394..466,
|
||||
elt: Tuple(
|
||||
ExprTuple {
|
||||
range: 395..447,
|
||||
elts: [
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 396..417,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 397..398,
|
||||
id: Name("y"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 399..416,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 403..404,
|
||||
id: Name("y"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 408..416,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 408..413,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 413..416,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 414..415,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 419..446,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 420..421,
|
||||
id: Name("z"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 422..445,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 432..433,
|
||||
id: Name("z"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 437..445,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 437..442,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 442..445,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 443..444,
|
||||
value: Int(
|
||||
2,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: true,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 448..465,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 452..453,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 457..465,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 457..462,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 462..465,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 463..464,
|
||||
value: Int(
|
||||
5,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Semantic Syntax Errors
|
||||
|
||||
|
|
||||
1 | # parse_options: {"target-version": "3.10"}
|
||||
2 | async def f(): return [[x async for x in foo(n)] for n in range(3)] # list
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)
|
||||
3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
|
||||
4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # parse_options: {"target-version": "3.10"}
|
||||
2 | async def f(): return [[x async for x in foo(n)] for n in range(3)] # list
|
||||
3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)
|
||||
4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
||||
5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)]
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
2 | async def f(): return [[x async for x in foo(n)] for n in range(3)] # list
|
||||
3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
|
||||
4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)
|
||||
5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)]
|
||||
6 | async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)]
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
3 | async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
|
||||
4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
||||
5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)
|
||||
6 | async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)]
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
4 | async def h(): return [{x async for x in foo(n)} for n in range(3)] # set
|
||||
5 | async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)]
|
||||
6 | async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ Syntax Error: cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/all_async_comprehension_py310.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..126,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 44..125,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("test"),
|
||||
range: 54..58,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 58..60,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 62..125,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 69..125,
|
||||
elt: ListComp(
|
||||
ExprListComp {
|
||||
range: 70..100,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 71..72,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 73..99,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 83..84,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 88..99,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 88..96,
|
||||
id: Name("elements"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 96..99,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 97..98,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 101..124,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 111..112,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 116..124,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 116..121,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 121..124,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 122..123,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
|
@ -0,0 +1,265 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/nested_async_comprehension_py310.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..259,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 87..159,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("f"),
|
||||
range: 97..98,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 98..100,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 106..127,
|
||||
value: ListComp(
|
||||
ExprListComp {
|
||||
range: 106..127,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 107..108,
|
||||
id: Name("_"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 109..126,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 113..114,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 118..126,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 118..123,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 123..126,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 124..125,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 132..159,
|
||||
value: ListComp(
|
||||
ExprListComp {
|
||||
range: 132..159,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 133..134,
|
||||
id: Name("_"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 135..158,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 145..146,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 150..158,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 150..155,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 155..158,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 156..157,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 195..258,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("f"),
|
||||
range: 205..206,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 206..208,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 214..226,
|
||||
is_async: false,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("g"),
|
||||
range: 218..219,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 219..221,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 223..226,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 223..226,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 231..258,
|
||||
value: ListComp(
|
||||
ExprListComp {
|
||||
range: 231..258,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 232..233,
|
||||
id: Name("_"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 234..257,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 244..245,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 249..257,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 249..254,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 254..257,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 255..256,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
|
@ -0,0 +1,401 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/nested_async_comprehension_py311.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..277,
|
||||
body: [
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 44..111,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("f"),
|
||||
range: 54..55,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 55..57,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 59..111,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 66..111,
|
||||
elt: ListComp(
|
||||
ExprListComp {
|
||||
range: 67..92,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 68..69,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 70..91,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 80..81,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 85..91,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 85..88,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 88..91,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 89..90,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 93..110,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 97..98,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 102..110,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 102..107,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 107..110,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 108..109,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 122..192,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("g"),
|
||||
range: 132..133,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 133..135,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 137..192,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 144..192,
|
||||
elt: DictComp(
|
||||
ExprDictComp {
|
||||
range: 145..173,
|
||||
key: Name(
|
||||
ExprName {
|
||||
range: 146..147,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
value: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 149..150,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 151..172,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 161..162,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 166..172,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 166..169,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 169..172,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 170..171,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 174..191,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 178..179,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 183..191,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 183..188,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 188..191,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 189..190,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
FunctionDef(
|
||||
StmtFunctionDef {
|
||||
range: 200..267,
|
||||
is_async: true,
|
||||
decorator_list: [],
|
||||
name: Identifier {
|
||||
id: Name("h"),
|
||||
range: 210..211,
|
||||
},
|
||||
type_params: None,
|
||||
parameters: Parameters {
|
||||
range: 211..213,
|
||||
posonlyargs: [],
|
||||
args: [],
|
||||
vararg: None,
|
||||
kwonlyargs: [],
|
||||
kwarg: None,
|
||||
},
|
||||
returns: None,
|
||||
body: [
|
||||
Return(
|
||||
StmtReturn {
|
||||
range: 215..267,
|
||||
value: Some(
|
||||
ListComp(
|
||||
ExprListComp {
|
||||
range: 222..267,
|
||||
elt: SetComp(
|
||||
ExprSetComp {
|
||||
range: 223..248,
|
||||
elt: Name(
|
||||
ExprName {
|
||||
range: 224..225,
|
||||
id: Name("x"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 226..247,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 236..237,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 241..247,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 241..244,
|
||||
id: Name("foo"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 244..247,
|
||||
args: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 245..246,
|
||||
id: Name("n"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
generators: [
|
||||
Comprehension {
|
||||
range: 249..266,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 253..254,
|
||||
id: Name("n"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Call(
|
||||
ExprCall {
|
||||
range: 258..266,
|
||||
func: Name(
|
||||
ExprName {
|
||||
range: 258..263,
|
||||
id: Name("range"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 263..266,
|
||||
args: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
range: 264..265,
|
||||
value: Int(
|
||||
3,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue