Skip to content

Commit 894a296

Browse files
committed
allow normal dotted names
1 parent c41e329 commit 894a296

File tree

3 files changed

+104
-3
lines changed

3 files changed

+104
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# parse_options: { "target_version": "3.8" }
2+
@buttons.clicked.connect
3+
def spam(): ...

crates/ruff_python_parser/src/parser/statement.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -2530,11 +2530,25 @@ impl<'src> Parser<'src> {
25302530
fn try_parse_old_decorators(&mut self) -> Option<ParsedExpr> {
25312531
let errors = self.errors.len();
25322532
let start = self.node_start();
2533-
let name = self.parse_name();
2534-
if name.ctx.is_invalid() {
2533+
// initial identifier
2534+
let ident = self.parse_identifier();
2535+
if !ident.is_valid() {
25352536
return None;
25362537
}
2537-
let name = Expr::from(name);
2538+
let mut name = Expr::from(ast::ExprName {
2539+
range: self.node_range(start),
2540+
id: ident.id,
2541+
ctx: ExprContext::Load,
2542+
});
2543+
// ("." identifier)*
2544+
while self.at(TokenKind::Dot) {
2545+
let attr = self.parse_attribute_expression(name, start);
2546+
if !attr.attr.is_valid() {
2547+
return None;
2548+
}
2549+
name = Expr::from(attr);
2550+
}
2551+
// ["(" [argument_list [","]] ")"] NEWLINE
25382552
let parsed = match self.current_token_kind() {
25392553
TokenKind::Lpar => Some(Expr::Call(self.parse_call_expression(name, start)).into()),
25402554
TokenKind::Newline => Some(name.into()),
@@ -2564,6 +2578,11 @@ impl<'src> Parser<'src> {
25642578
// before 3.9 but avoid false positives on examples like the `@_` "identity function hack"
25652579
// or the "eval hack" called out in the PEP.
25662580

2581+
// test_ok decorator_expression_dotted_ident_before_py39
2582+
// # parse_options: { "target_version": "3.8" }
2583+
// @buttons.clicked.connect
2584+
// def spam(): ...
2585+
25672586
// test_ok decorator_expression_identity_hack_before_py39
25682587
// # parse_options: { "target_version": "3.8" }
25692588
// def _(x): return x
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
source: crates/ruff_python_parser/tests/fixtures.rs
3+
input_file: crates/ruff_python_parser/resources/inline/ok/decorator_expression_dotted_ident_before_py39.py
4+
---
5+
## AST
6+
7+
```
8+
Module(
9+
ModModule {
10+
range: 0..86,
11+
body: [
12+
FunctionDef(
13+
StmtFunctionDef {
14+
range: 45..85,
15+
is_async: false,
16+
decorator_list: [
17+
Decorator {
18+
range: 45..69,
19+
expression: Attribute(
20+
ExprAttribute {
21+
range: 46..69,
22+
value: Attribute(
23+
ExprAttribute {
24+
range: 46..61,
25+
value: Name(
26+
ExprName {
27+
range: 46..53,
28+
id: Name("buttons"),
29+
ctx: Load,
30+
},
31+
),
32+
attr: Identifier {
33+
id: Name("clicked"),
34+
range: 54..61,
35+
},
36+
ctx: Load,
37+
},
38+
),
39+
attr: Identifier {
40+
id: Name("connect"),
41+
range: 62..69,
42+
},
43+
ctx: Load,
44+
},
45+
),
46+
},
47+
],
48+
name: Identifier {
49+
id: Name("spam"),
50+
range: 74..78,
51+
},
52+
type_params: None,
53+
parameters: Parameters {
54+
range: 78..80,
55+
posonlyargs: [],
56+
args: [],
57+
vararg: None,
58+
kwonlyargs: [],
59+
kwarg: None,
60+
},
61+
returns: None,
62+
body: [
63+
Expr(
64+
StmtExpr {
65+
range: 82..85,
66+
value: EllipsisLiteral(
67+
ExprEllipsisLiteral {
68+
range: 82..85,
69+
},
70+
),
71+
},
72+
),
73+
],
74+
},
75+
),
76+
],
77+
},
78+
)
79+
```

0 commit comments

Comments
 (0)