Skip to content

Commit bfc413c

Browse files
authored
[3.9] bpo-42806: Fix ast locations of f-strings inside parentheses (GH-24067) (GH-24069)
(cherry picked from commit bd2728b) Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
1 parent 9a608ac commit bfc413c

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

Lib/test/test_fstring.py

+53
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,59 @@ def test_ast_line_numbers_multiline_fstring(self):
332332
self.assertEqual(binop.left.col_offset, 4)
333333
self.assertEqual(binop.right.col_offset, 7)
334334

335+
def test_ast_line_numbers_with_parentheses(self):
336+
expr = """
337+
x = (
338+
f" {test(t)}"
339+
)"""
340+
t = ast.parse(expr)
341+
self.assertEqual(type(t), ast.Module)
342+
self.assertEqual(len(t.body), 1)
343+
# check the test(t) location
344+
call = t.body[0].value.values[1].value
345+
self.assertEqual(type(call), ast.Call)
346+
self.assertEqual(call.lineno, 3)
347+
self.assertEqual(call.end_lineno, 3)
348+
self.assertEqual(call.col_offset, 8)
349+
self.assertEqual(call.end_col_offset, 15)
350+
351+
expr = """
352+
x = (
353+
'PERL_MM_OPT', (
354+
f'wat'
355+
f'some_string={f(x)} '
356+
f'wat'
357+
),
358+
)
359+
"""
360+
t = ast.parse(expr)
361+
self.assertEqual(type(t), ast.Module)
362+
self.assertEqual(len(t.body), 1)
363+
# check the fstring
364+
fstring = t.body[0].value.elts[1]
365+
self.assertEqual(type(fstring), ast.JoinedStr)
366+
self.assertEqual(len(fstring.values), 3)
367+
wat1, middle, wat2 = fstring.values
368+
# check the first wat
369+
self.assertEqual(type(wat1), ast.Constant)
370+
self.assertEqual(wat1.lineno, 4)
371+
self.assertEqual(wat1.end_lineno, 6)
372+
self.assertEqual(wat1.col_offset, 12)
373+
self.assertEqual(wat1.end_col_offset, 18)
374+
# check the call
375+
call = middle.value
376+
self.assertEqual(type(call), ast.Call)
377+
self.assertEqual(call.lineno, 5)
378+
self.assertEqual(call.end_lineno, 5)
379+
self.assertEqual(call.col_offset, 27)
380+
self.assertEqual(call.end_col_offset, 31)
381+
# check the second wat
382+
self.assertEqual(type(wat2), ast.Constant)
383+
self.assertEqual(wat2.lineno, 4)
384+
self.assertEqual(wat2.end_lineno, 6)
385+
self.assertEqual(wat2.col_offset, 12)
386+
self.assertEqual(wat2.end_col_offset, 18)
387+
335388
def test_docstring(self):
336389
def f():
337390
f'''Not a docstring'''
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix the column offsets for f-strings :mod:`ast` nodes surrounded by
2+
parentheses and for nodes that spawn multiple lines. Patch by Pablo Galindo.

Parser/pegen/parse_string.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
410410
Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
411411
NULL, p->arena);
412412
p2->starting_lineno = t->lineno + lines - 1;
413-
p2->starting_col_offset = p->tok->first_lineno == p->tok->lineno ? t->col_offset + cols : cols;
413+
p2->starting_col_offset = t->col_offset + cols;
414414

415415
expr = _PyPegen_run_parser(p2);
416416

0 commit comments

Comments
 (0)