[syntax-errors] Store to or delete __debug__ (#16984)

Summary
--

Detect setting or deleting `__debug__`. Assigning to `__debug__` was a
`SyntaxError` on the earliest version I tested (3.8). Deleting
`__debug__` was made a `SyntaxError` in [BPO 45000], which said it was
resolved in Python 3.10. However, `del __debug__` was also a runtime
error (`NameError`) when I tested in Python 3.9.6, so I thought it was
worth including 3.9 in this check.

I don't think it was ever a *good* idea to try `del __debug__`, so I
think there's also an argument for not making this version-dependent at
all. That would only simplify the implementation very slightly, though.

[BPO 45000]: https://github.com/python/cpython/issues/89163

Test Plan
--

New inline tests. This also required adding a `PythonVersion` field to
the `TestContext` that could be taken from the inline `ParseOptions` and
making the version field on the options accessible.
This commit is contained in:
Brent Westbrook 2025-03-29 12:07:20 -04:00 committed by GitHub
parent 8396d7cd63
commit a0819f0c51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 1372 additions and 7 deletions

View file

@ -0,0 +1,94 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_class.py
---
## AST
```
Module(
ModModule {
range: 0..82,
body: [
ClassDef(
StmtClassDef {
range: 0..20,
decorator_list: [],
name: Identifier {
id: Name("__debug__"),
range: 6..15,
},
type_params: None,
arguments: None,
body: [
Expr(
StmtExpr {
range: 17..20,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 17..20,
},
),
},
),
],
},
),
ClassDef(
StmtClassDef {
range: 35..58,
decorator_list: [],
name: Identifier {
id: Name("C"),
range: 41..42,
},
type_params: Some(
TypeParams {
range: 42..53,
type_params: [
TypeVar(
TypeParamTypeVar {
range: 43..52,
name: Identifier {
id: Name("__debug__"),
range: 43..52,
},
bound: None,
default: None,
},
),
],
},
),
arguments: None,
body: [
Expr(
StmtExpr {
range: 55..58,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 55..58,
},
),
},
),
],
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | class __debug__: ... # class name
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
2 | class C[__debug__]: ... # type parameter name
|
|
1 | class __debug__: ... # class name
2 | class C[__debug__]: ... # type parameter name
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,168 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_function.py
---
## AST
```
Module(
ModModule {
range: 0..125,
body: [
FunctionDef(
StmtFunctionDef {
range: 0..20,
is_async: false,
decorator_list: [],
name: Identifier {
id: Name("__debug__"),
range: 4..13,
},
type_params: None,
parameters: Parameters {
range: 13..15,
posonlyargs: [],
args: [],
vararg: None,
kwonlyargs: [],
kwarg: None,
},
returns: None,
body: [
Expr(
StmtExpr {
range: 17..20,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 17..20,
},
),
},
),
],
},
),
FunctionDef(
StmtFunctionDef {
range: 38..61,
is_async: false,
decorator_list: [],
name: Identifier {
id: Name("f"),
range: 42..43,
},
type_params: Some(
TypeParams {
range: 43..54,
type_params: [
TypeVar(
TypeParamTypeVar {
range: 44..53,
name: Identifier {
id: Name("__debug__"),
range: 44..53,
},
bound: None,
default: None,
},
),
],
},
),
parameters: Parameters {
range: 54..56,
posonlyargs: [],
args: [],
vararg: None,
kwonlyargs: [],
kwarg: None,
},
returns: None,
body: [
Expr(
StmtExpr {
range: 58..61,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 58..61,
},
),
},
),
],
},
),
FunctionDef(
StmtFunctionDef {
range: 85..106,
is_async: false,
decorator_list: [],
name: Identifier {
id: Name("f"),
range: 89..90,
},
type_params: None,
parameters: Parameters {
range: 90..101,
posonlyargs: [],
args: [
ParameterWithDefault {
range: 91..100,
parameter: Parameter {
range: 91..100,
name: Identifier {
id: Name("__debug__"),
range: 91..100,
},
annotation: None,
},
default: None,
},
],
vararg: None,
kwonlyargs: [],
kwarg: None,
},
returns: None,
body: [
Expr(
StmtExpr {
range: 103..106,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 103..106,
},
),
},
),
],
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | def __debug__(): ... # function name
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
2 | def f[__debug__](): ... # type parameter name
3 | def f(__debug__): ... # parameter name
|
|
1 | def __debug__(): ... # function name
2 | def f[__debug__](): ... # type parameter name
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
3 | def f(__debug__): ... # parameter name
|
|
1 | def __debug__(): ... # function name
2 | def f[__debug__](): ... # type parameter name
3 | def f(__debug__): ... # parameter name
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,133 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_import.py
---
## AST
```
Module(
ModModule {
range: 0..100,
body: [
Import(
StmtImport {
range: 0..16,
names: [
Alias {
range: 7..16,
name: Identifier {
id: Name("__debug__"),
range: 7..16,
},
asname: None,
},
],
},
),
Import(
StmtImport {
range: 17..42,
names: [
Alias {
range: 24..42,
name: Identifier {
id: Name("debug"),
range: 24..29,
},
asname: Some(
Identifier {
id: Name("__debug__"),
range: 33..42,
},
),
},
],
},
),
ImportFrom(
StmtImportFrom {
range: 43..66,
module: Some(
Identifier {
id: Name("x"),
range: 48..49,
},
),
names: [
Alias {
range: 57..66,
name: Identifier {
id: Name("__debug__"),
range: 57..66,
},
asname: None,
},
],
level: 0,
},
),
ImportFrom(
StmtImportFrom {
range: 67..99,
module: Some(
Identifier {
id: Name("x"),
range: 72..73,
},
),
names: [
Alias {
range: 81..99,
name: Identifier {
id: Name("debug"),
range: 81..86,
},
asname: Some(
Identifier {
id: Name("__debug__"),
range: 90..99,
},
),
},
],
level: 0,
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | import __debug__
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
2 | import debug as __debug__
3 | from x import __debug__
|
|
1 | import __debug__
2 | import debug as __debug__
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
3 | from x import __debug__
4 | from x import debug as __debug__
|
|
1 | import __debug__
2 | import debug as __debug__
3 | from x import __debug__
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
4 | from x import debug as __debug__
|
|
2 | import debug as __debug__
3 | from x import __debug__
4 | from x import debug as __debug__
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,64 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_match.py
---
## AST
```
Module(
ModModule {
range: 0..33,
body: [
Match(
StmtMatch {
range: 0..32,
subject: Name(
ExprName {
range: 6..7,
id: Name("x"),
ctx: Load,
},
),
cases: [
MatchCase {
range: 13..32,
pattern: MatchAs(
PatternMatchAs {
range: 18..27,
pattern: None,
name: Some(
Identifier {
id: Name("__debug__"),
range: 18..27,
},
),
},
),
guard: None,
body: [
Expr(
StmtExpr {
range: 29..32,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 29..32,
},
),
},
),
],
},
],
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | match x:
2 | case __debug__: ...
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,76 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_try.py
---
## AST
```
Module(
ModModule {
range: 0..44,
body: [
Try(
StmtTry {
range: 0..43,
body: [
Expr(
StmtExpr {
range: 5..8,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 5..8,
},
),
},
),
],
handlers: [
ExceptHandler(
ExceptHandlerExceptHandler {
range: 9..43,
type_: Some(
Name(
ExprName {
range: 16..25,
id: Name("Exception"),
ctx: Load,
},
),
),
name: Some(
Identifier {
id: Name("__debug__"),
range: 29..38,
},
),
body: [
Expr(
StmtExpr {
range: 40..43,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 40..43,
},
),
},
),
],
},
),
],
orelse: [],
finalbody: [],
is_star: false,
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | try: ...
2 | except Exception as __debug__: ...
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,99 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_type_alias.py
---
## AST
```
Module(
ModModule {
range: 0..95,
body: [
TypeAlias(
StmtTypeAlias {
range: 0..26,
name: Name(
ExprName {
range: 5..14,
id: Name("__debug__"),
ctx: Store,
},
),
type_params: None,
value: Subscript(
ExprSubscript {
range: 17..26,
value: Name(
ExprName {
range: 17..21,
id: Name("list"),
ctx: Load,
},
),
slice: Name(
ExprName {
range: 22..25,
id: Name("int"),
ctx: Load,
},
),
ctx: Load,
},
),
},
),
TypeAlias(
StmtTypeAlias {
range: 67..94,
name: Name(
ExprName {
range: 72..77,
id: Name("Debug"),
ctx: Store,
},
),
type_params: Some(
TypeParams {
range: 77..88,
type_params: [
TypeVar(
TypeParamTypeVar {
range: 78..87,
name: Identifier {
id: Name("__debug__"),
range: 78..87,
},
bound: None,
default: None,
},
),
],
},
),
value: Name(
ExprName {
range: 91..94,
id: Name("str"),
ctx: Load,
},
),
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | type __debug__ = list[int] # visited as an Expr but still flagged
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
2 | type Debug[__debug__] = str
|
|
1 | type __debug__ = list[int] # visited as an Expr but still flagged
2 | type Debug[__debug__] = str
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,89 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/debug_shadow_with.py
---
## AST
```
Module(
ModModule {
range: 0..39,
body: [
With(
StmtWith {
range: 0..38,
is_async: false,
items: [
WithItem {
range: 5..33,
context_expr: Call(
ExprCall {
range: 5..20,
func: Name(
ExprName {
range: 5..9,
id: Name("open"),
ctx: Load,
},
),
arguments: Arguments {
range: 9..20,
args: [
StringLiteral(
ExprStringLiteral {
range: 10..19,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 10..19,
value: "foo.txt",
flags: StringLiteralFlags {
quote_style: Double,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
],
keywords: [],
},
},
),
optional_vars: Some(
Name(
ExprName {
range: 24..33,
id: Name("__debug__"),
ctx: Store,
},
),
),
},
],
body: [
Expr(
StmtExpr {
range: 35..38,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 35..38,
},
),
},
),
],
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | with open("foo.txt") as __debug__: ...
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,36 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/del_debug_py39.py
---
## AST
```
Module(
ModModule {
range: 0..57,
body: [
Delete(
StmtDelete {
range: 43..56,
targets: [
Name(
ExprName {
range: 47..56,
id: Name("__debug__"),
ctx: Del,
},
),
],
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | # parse_options: {"target-version": "3.9"}
2 | del __debug__
| ^^^^^^^^^ Syntax Error: cannot delete `__debug__` on Python 3.9 (syntax was removed in 3.9)
|

View file

@ -0,0 +1,205 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/err/write_to_debug_expr.py
---
## AST
```
Module(
ModModule {
range: 0..83,
body: [
Delete(
StmtDelete {
range: 0..13,
targets: [
Name(
ExprName {
range: 4..13,
id: Name("__debug__"),
ctx: Del,
},
),
],
},
),
Delete(
StmtDelete {
range: 14..36,
targets: [
Name(
ExprName {
range: 18..19,
id: Name("x"),
ctx: Del,
},
),
Name(
ExprName {
range: 21..22,
id: Name("y"),
ctx: Del,
},
),
Name(
ExprName {
range: 24..33,
id: Name("__debug__"),
ctx: Del,
},
),
Name(
ExprName {
range: 35..36,
id: Name("z"),
ctx: Del,
},
),
],
},
),
Assign(
StmtAssign {
range: 37..50,
targets: [
Name(
ExprName {
range: 37..46,
id: Name("__debug__"),
ctx: Store,
},
),
],
value: NumberLiteral(
ExprNumberLiteral {
range: 49..50,
value: Int(
1,
),
},
),
},
),
Assign(
StmtAssign {
range: 51..82,
targets: [
Tuple(
ExprTuple {
range: 51..69,
elts: [
Name(
ExprName {
range: 51..52,
id: Name("x"),
ctx: Store,
},
),
Name(
ExprName {
range: 54..55,
id: Name("y"),
ctx: Store,
},
),
Name(
ExprName {
range: 57..66,
id: Name("__debug__"),
ctx: Store,
},
),
Name(
ExprName {
range: 68..69,
id: Name("z"),
ctx: Store,
},
),
],
ctx: Store,
parenthesized: false,
},
),
],
value: Tuple(
ExprTuple {
range: 72..82,
elts: [
NumberLiteral(
ExprNumberLiteral {
range: 72..73,
value: Int(
1,
),
},
),
NumberLiteral(
ExprNumberLiteral {
range: 75..76,
value: Int(
2,
),
},
),
NumberLiteral(
ExprNumberLiteral {
range: 78..79,
value: Int(
3,
),
},
),
NumberLiteral(
ExprNumberLiteral {
range: 81..82,
value: Int(
4,
),
},
),
],
ctx: Load,
parenthesized: false,
},
),
},
),
],
},
)
```
## Semantic Syntax Errors
|
1 | del __debug__
| ^^^^^^^^^ Syntax Error: cannot delete `__debug__` on Python 3.13 (syntax was removed in 3.9)
2 | del x, y, __debug__, z
3 | __debug__ = 1
|
|
1 | del __debug__
2 | del x, y, __debug__, z
| ^^^^^^^^^ Syntax Error: cannot delete `__debug__` on Python 3.13 (syntax was removed in 3.9)
3 | __debug__ = 1
4 | x, y, __debug__, z = 1, 2, 3, 4
|
|
1 | del __debug__
2 | del x, y, __debug__, z
3 | __debug__ = 1
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
4 | x, y, __debug__, z = 1, 2, 3, 4
|
|
2 | del x, y, __debug__, z
3 | __debug__ = 1
4 | x, y, __debug__, z = 1, 2, 3, 4
| ^^^^^^^^^ Syntax Error: cannot assign to `__debug__`
|

View file

@ -0,0 +1,84 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/ok/debug_rename_import.py
---
## AST
```
Module(
ModModule {
range: 0..86,
body: [
Import(
StmtImport {
range: 0..25,
names: [
Alias {
range: 7..25,
name: Identifier {
id: Name("__debug__"),
range: 7..16,
},
asname: Some(
Identifier {
id: Name("debug"),
range: 20..25,
},
),
},
],
},
),
ImportFrom(
StmtImportFrom {
range: 26..52,
module: Some(
Identifier {
id: Name("__debug__"),
range: 31..40,
},
),
names: [
Alias {
range: 48..52,
name: Identifier {
id: Name("Some"),
range: 48..52,
},
asname: None,
},
],
level: 0,
},
),
ImportFrom(
StmtImportFrom {
range: 53..85,
module: Some(
Identifier {
id: Name("x"),
range: 58..59,
},
),
names: [
Alias {
range: 67..85,
name: Identifier {
id: Name("__debug__"),
range: 67..76,
},
asname: Some(
Identifier {
id: Name("debug"),
range: 80..85,
},
),
},
],
level: 0,
},
),
],
},
)
```

View file

@ -0,0 +1,29 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/ok/del_debug_py38.py
---
## AST
```
Module(
ModModule {
range: 0..57,
body: [
Delete(
StmtDelete {
range: 43..56,
targets: [
Name(
ExprName {
range: 47..56,
id: Name("__debug__"),
ctx: Del,
},
),
],
},
),
],
},
)
```

View file

@ -0,0 +1,61 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/ok/read_from_debug.py
---
## AST
```
Module(
ModModule {
range: 0..32,
body: [
If(
StmtIf {
range: 0..17,
test: Name(
ExprName {
range: 3..12,
id: Name("__debug__"),
ctx: Load,
},
),
body: [
Expr(
StmtExpr {
range: 14..17,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 14..17,
},
),
},
),
],
elif_else_clauses: [],
},
),
Assign(
StmtAssign {
range: 18..31,
targets: [
Name(
ExprName {
range: 18..19,
id: Name("x"),
ctx: Store,
},
),
],
value: Name(
ExprName {
range: 22..31,
id: Name("__debug__"),
ctx: Load,
},
),
},
),
],
},
)
```