[syntax-errors] Parenthesized keyword argument names after Python 3.8 (#16482)

Summary
--

Unlike the other syntax errors detected so far, parenthesized keyword
arguments are only allowed *before* 3.8. It sounds like they were only
accidentally allowed before that [^1].

As an aside, you get a pretty confusing error from Python for this, so
it's nice that we can catch it:

```pycon
>>> def f(**kwargs): ...
... f((a)=1)
...
  File "<python-input-0>", line 2
    f((a)=1)
       ^^^
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
>>>
```
Test Plan
--
Inline tests.

[^1]: https://github.com/python/cpython/issues/78822
This commit is contained in:
Brent Westbrook 2025-03-06 12:18:13 -05:00 committed by GitHub
parent 6c14225c66
commit b3c884f4f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 319 additions and 22 deletions

View file

@ -0,0 +1,161 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/parenthesized_kwarg_py38.py
---
## AST
```
Module(
ModModule {
range: 0..77,
body: [
Expr(
StmtExpr {
range: 43..51,
value: Call(
ExprCall {
range: 43..51,
func: Name(
ExprName {
range: 43..44,
id: Name("f"),
ctx: Load,
},
),
arguments: Arguments {
range: 44..51,
args: [],
keywords: [
Keyword {
range: 45..50,
arg: Some(
Identifier {
id: Name("a"),
range: 46..47,
},
),
value: NumberLiteral(
ExprNumberLiteral {
range: 49..50,
value: Int(
1,
),
},
),
},
],
},
},
),
},
),
Expr(
StmtExpr {
range: 52..62,
value: Call(
ExprCall {
range: 52..62,
func: Name(
ExprName {
range: 52..53,
id: Name("f"),
ctx: Load,
},
),
arguments: Arguments {
range: 53..62,
args: [],
keywords: [
Keyword {
range: 54..61,
arg: Some(
Identifier {
id: Name("a"),
range: 55..56,
},
),
value: NumberLiteral(
ExprNumberLiteral {
range: 60..61,
value: Int(
1,
),
},
),
},
],
},
},
),
},
),
Expr(
StmtExpr {
range: 63..76,
value: Call(
ExprCall {
range: 63..76,
func: Name(
ExprName {
range: 63..64,
id: Name("f"),
ctx: Load,
},
),
arguments: Arguments {
range: 64..76,
args: [],
keywords: [
Keyword {
range: 66..75,
arg: Some(
Identifier {
id: Name("a"),
range: 68..69,
},
),
value: NumberLiteral(
ExprNumberLiteral {
range: 74..75,
value: Int(
1,
),
},
),
},
],
},
},
),
},
),
],
},
)
```
## Unsupported Syntax Errors
|
1 | # parse_options: {"target-version": "3.8"}
2 | f((a)=1)
| ^^^ Syntax Error: Cannot use parenthesized keyword argument name on Python 3.8 (syntax was removed in Python 3.8)
3 | f((a) = 1)
4 | f( ( a ) = 1)
|
|
1 | # parse_options: {"target-version": "3.8"}
2 | f((a)=1)
3 | f((a) = 1)
| ^^^ Syntax Error: Cannot use parenthesized keyword argument name on Python 3.8 (syntax was removed in Python 3.8)
4 | f( ( a ) = 1)
|
|
2 | f((a)=1)
3 | f((a) = 1)
4 | f( ( a ) = 1)
| ^^^^^ Syntax Error: Cannot use parenthesized keyword argument name on Python 3.8 (syntax was removed in Python 3.8)
|

View file

@ -0,0 +1,55 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/ok/parenthesized_kwarg_py37.py
---
## AST
```
Module(
ModModule {
range: 0..52,
body: [
Expr(
StmtExpr {
range: 43..51,
value: Call(
ExprCall {
range: 43..51,
func: Name(
ExprName {
range: 43..44,
id: Name("f"),
ctx: Load,
},
),
arguments: Arguments {
range: 44..51,
args: [],
keywords: [
Keyword {
range: 45..50,
arg: Some(
Identifier {
id: Name("a"),
range: 46..47,
},
),
value: NumberLiteral(
ExprNumberLiteral {
range: 49..50,
value: Int(
1,
),
},
),
},
],
},
},
),
},
),
],
},
)
```