Skip to content

Commit 6e619c4

Browse files
bpo-39474: Fix AST pos for expressions like (a)(b), (a)[b] and (a).b. (GH-18477)
1 parent 674935b commit 6e619c4

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

Lib/test/test_ast.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,33 @@ def test_attribute_spaces(self):
17071707
self._check_content(s, call, s)
17081708
self._check_content(s, call.args[0], 'x. y .z')
17091709

1710+
def test_redundant_parenthesis(self):
1711+
s = '( ( ( a + b ) ) )'
1712+
v = ast.parse(s).body[0].value
1713+
self.assertEqual(type(v).__name__, 'BinOp')
1714+
self._check_content(s, v, 'a + b')
1715+
s2 = 'await ' + s
1716+
v = ast.parse(s2).body[0].value.value
1717+
self.assertEqual(type(v).__name__, 'BinOp')
1718+
self._check_content(s2, v, 'a + b')
1719+
1720+
def test_trailers_with_redundant_parenthesis(self):
1721+
tests = (
1722+
('( ( ( a ) ) ) ( )', 'Call'),
1723+
('( ( ( a ) ) ) ( b )', 'Call'),
1724+
('( ( ( a ) ) ) [ b ]', 'Subscript'),
1725+
('( ( ( a ) ) ) . b', 'Attribute'),
1726+
)
1727+
for s, t in tests:
1728+
with self.subTest(s):
1729+
v = ast.parse(s).body[0].value
1730+
self.assertEqual(type(v).__name__, t)
1731+
self._check_content(s, v, s)
1732+
s2 = 'await ' + s
1733+
v = ast.parse(s2).body[0].value.value
1734+
self.assertEqual(type(v).__name__, t)
1735+
self._check_content(s2, v, s)
1736+
17101737
def test_displays(self):
17111738
s1 = '[{}, {1, }, {1, 2,} ]'
17121739
s2 = '{a: b, f (): g () ,}'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed starting position of AST for expressions like ``(a)(b)``, ``(a)[b]``
2+
and ``(a).b``.

Python/ast.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ static stmt_ty ast_for_for_stmt(struct compiling *, const node *, bool);
583583

584584
/* Note different signature for ast_for_call */
585585
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty,
586-
const node *, const node *);
586+
const node *, const node *, const node *);
587587

588588
static PyObject *parsenumber(struct compiling *, const char *);
589589
static expr_ty parsestrplus(struct compiling *, const node *n);
@@ -1757,7 +1757,8 @@ ast_for_decorator(struct compiling *c, const node *n)
17571757
name_expr = NULL;
17581758
}
17591759
else {
1760-
d = ast_for_call(c, CHILD(n, 3), name_expr, CHILD(n, 2), CHILD(n, 4));
1760+
d = ast_for_call(c, CHILD(n, 3), name_expr,
1761+
CHILD(n, 1), CHILD(n, 2), CHILD(n, 4));
17611762
if (!d)
17621763
return NULL;
17631764
name_expr = NULL;
@@ -2658,7 +2659,7 @@ ast_for_binop(struct compiling *c, const node *n)
26582659
}
26592660

26602661
static expr_ty
2661-
ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
2662+
ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr, const node *start)
26622663
{
26632664
/* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
26642665
subscriptlist: subscript (',' subscript)* [',']
@@ -2668,17 +2669,18 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
26682669
REQ(n, trailer);
26692670
if (TYPE(CHILD(n, 0)) == LPAR) {
26702671
if (NCH(n) == 2)
2671-
return Call(left_expr, NULL, NULL, LINENO(n), n->n_col_offset,
2672+
return Call(left_expr, NULL, NULL, LINENO(start), start->n_col_offset,
26722673
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
26732674
else
2674-
return ast_for_call(c, CHILD(n, 1), left_expr, CHILD(n, 0), CHILD(n, 2));
2675+
return ast_for_call(c, CHILD(n, 1), left_expr,
2676+
start, CHILD(n, 0), CHILD(n, 2));
26752677
}
26762678
else if (TYPE(CHILD(n, 0)) == DOT) {
26772679
PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));
26782680
if (!attr_id)
26792681
return NULL;
26802682
return Attribute(left_expr, attr_id, Load,
2681-
LINENO(n), n->n_col_offset,
2683+
LINENO(start), start->n_col_offset,
26822684
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
26832685
}
26842686
else {
@@ -2689,7 +2691,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
26892691
slice_ty slc = ast_for_slice(c, CHILD(n, 0));
26902692
if (!slc)
26912693
return NULL;
2692-
return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset,
2694+
return Subscript(left_expr, slc, Load, LINENO(start), start->n_col_offset,
26932695
n_copy->n_end_lineno, n_copy->n_end_col_offset,
26942696
c->c_arena);
26952697
}
@@ -2716,7 +2718,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
27162718
}
27172719
if (!simple) {
27182720
return Subscript(left_expr, ExtSlice(slices, c->c_arena),
2719-
Load, LINENO(n), n->n_col_offset,
2721+
Load, LINENO(start), start->n_col_offset,
27202722
n_copy->n_end_lineno, n_copy->n_end_col_offset, c->c_arena);
27212723
}
27222724
/* extract Index values and put them in a Tuple */
@@ -2733,7 +2735,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
27332735
if (!e)
27342736
return NULL;
27352737
return Subscript(left_expr, Index(e, c->c_arena),
2736-
Load, LINENO(n), n->n_col_offset,
2738+
Load, LINENO(start), start->n_col_offset,
27372739
n_copy->n_end_lineno, n_copy->n_end_col_offset, c->c_arena);
27382740
}
27392741
}
@@ -2771,7 +2773,7 @@ static expr_ty
27712773
ast_for_atom_expr(struct compiling *c, const node *n)
27722774
{
27732775
int i, nch, start = 0;
2774-
expr_ty e, tmp;
2776+
expr_ty e;
27752777

27762778
REQ(n, atom_expr);
27772779
nch = NCH(n);
@@ -2800,12 +2802,9 @@ ast_for_atom_expr(struct compiling *c, const node *n)
28002802
node *ch = CHILD(n, i);
28012803
if (TYPE(ch) != trailer)
28022804
break;
2803-
tmp = ast_for_trailer(c, ch, e);
2804-
if (!tmp)
2805+
e = ast_for_trailer(c, ch, e, CHILD(n, start));
2806+
if (!e)
28052807
return NULL;
2806-
tmp->lineno = e->lineno;
2807-
tmp->col_offset = e->col_offset;
2808-
e = tmp;
28092808
}
28102809

28112810
if (start) {
@@ -3035,7 +3034,7 @@ ast_for_expr(struct compiling *c, const node *n)
30353034

30363035
static expr_ty
30373036
ast_for_call(struct compiling *c, const node *n, expr_ty func,
3038-
const node *maybegenbeg, const node *closepar)
3037+
const node *start, const node *maybegenbeg, const node *closepar)
30393038
{
30403039
/*
30413040
arglist: argument (',' argument)* [',']
@@ -3239,7 +3238,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
32393238
}
32403239
}
32413240

3242-
return Call(func, args, keywords, func->lineno, func->col_offset,
3241+
return Call(func, args, keywords, LINENO(start), start->n_col_offset,
32433242
closepar->n_end_lineno, closepar->n_end_col_offset, c->c_arena);
32443243
}
32453244

@@ -4486,7 +4485,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
44864485
dummy = Name(dummy_name, Load, LINENO(n), n->n_col_offset,
44874486
CHILD(n, 1)->n_end_lineno, CHILD(n, 1)->n_end_col_offset,
44884487
c->c_arena);
4489-
call = ast_for_call(c, CHILD(n, 3), dummy, NULL, CHILD(n, 4));
4488+
call = ast_for_call(c, CHILD(n, 3), dummy,
4489+
CHILD(n, 1), NULL, CHILD(n, 4));
44904490
if (!call)
44914491
return NULL;
44924492
}

0 commit comments

Comments
 (0)