mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:56 +00:00
[syntax-errors] Tuple unpacking in for
statement iterator clause before Python 3.9 (#16558)
Summary -- This PR reuses a slightly modified version of the `check_tuple_unpacking` method added for detecting unpacking in `return` and `yield` statements to detect the same issue in the iterator clause of `for` loops. I ran into the same issue with a bare `for x in *rest: ...` example (invalid even on Python 3.13) and added it as a comment on https://github.com/astral-sh/ruff/issues/16520. I considered just making this an additional `StarTupleKind` variant as well, but this change was in a different version of Python, so I kept it separate. Test Plan -- New inline tests.
This commit is contained in:
parent
27e9d1fe3e
commit
2382fe1f25
9 changed files with 673 additions and 6 deletions
|
@ -0,0 +1,220 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/err/for_iter_unpack_py38.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..106,
|
||||
body: [
|
||||
For(
|
||||
StmtFor {
|
||||
range: 43..63,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 52..58,
|
||||
elts: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 52..54,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 53..54,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 57..58,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 60..63,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 60..63,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
For(
|
||||
StmtFor {
|
||||
range: 64..84,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 68..69,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 74..79,
|
||||
elts: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 74..75,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 77..79,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 78..79,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 81..84,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 81..84,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
For(
|
||||
StmtFor {
|
||||
range: 85..105,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 89..90,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 94..100,
|
||||
elts: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 94..96,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 95..96,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 98..100,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 99..100,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 102..105,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 102..105,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Unsupported Syntax Errors
|
||||
|
||||
|
|
||||
1 | # parse_options: {"target-version": "3.8"}
|
||||
2 | for x in *a, b: ...
|
||||
| ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9)
|
||||
3 | for x in a, *b: ...
|
||||
4 | for x in *a, *b: ...
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # parse_options: {"target-version": "3.8"}
|
||||
2 | for x in *a, b: ...
|
||||
3 | for x in a, *b: ...
|
||||
| ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9)
|
||||
4 | for x in *a, *b: ...
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
2 | for x in *a, b: ...
|
||||
3 | for x in a, *b: ...
|
||||
4 | for x in *a, *b: ...
|
||||
| ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9)
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
2 | for x in *a, b: ...
|
||||
3 | for x in a, *b: ...
|
||||
4 | for x in *a, *b: ...
|
||||
| ^^ Syntax Error: Cannot use iterable unpacking in `for` statements on Python 3.8 (syntax was added in Python 3.9)
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/for_iter_unpack_py38.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..112,
|
||||
body: [
|
||||
For(
|
||||
StmtFor {
|
||||
range: 43..65,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 52..60,
|
||||
elts: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 53..55,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 54..55,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 58..59,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: true,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 62..65,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 62..65,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
For(
|
||||
StmtFor {
|
||||
range: 66..88,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 70..71,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 75..83,
|
||||
elts: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 77..78,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 80..82,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 81..82,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: true,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 85..88,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 85..88,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
For(
|
||||
StmtFor {
|
||||
range: 89..111,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 93..94,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 98..106,
|
||||
elts: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 99..101,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 100..101,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 103..105,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 104..105,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: true,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 108..111,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 108..111,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/for_iter_unpack_py39.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
range: 0..106,
|
||||
body: [
|
||||
For(
|
||||
StmtFor {
|
||||
range: 43..63,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 47..48,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 52..58,
|
||||
elts: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 52..54,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 53..54,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Name(
|
||||
ExprName {
|
||||
range: 57..58,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 60..63,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 60..63,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
For(
|
||||
StmtFor {
|
||||
range: 64..84,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 68..69,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 74..79,
|
||||
elts: [
|
||||
Name(
|
||||
ExprName {
|
||||
range: 74..75,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 77..79,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 78..79,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 81..84,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 81..84,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
For(
|
||||
StmtFor {
|
||||
range: 85..105,
|
||||
is_async: false,
|
||||
target: Name(
|
||||
ExprName {
|
||||
range: 89..90,
|
||||
id: Name("x"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
iter: Tuple(
|
||||
ExprTuple {
|
||||
range: 94..100,
|
||||
elts: [
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 94..96,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 95..96,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Starred(
|
||||
ExprStarred {
|
||||
range: 98..100,
|
||||
value: Name(
|
||||
ExprName {
|
||||
range: 99..100,
|
||||
id: Name("b"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
range: 102..105,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
range: 102..105,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
orelse: [],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue