summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2021-01-03 01:11:41 (GMT)
committerGitHub <noreply@github.com>2021-01-03 01:11:41 (GMT)
commitbd2728b1e8a99ba8f8c2d481f88aeb99b8b8360f (patch)
tree45e3fc389d9dee5e63556b49995961ee7e22b48b
parent2ea320dddd553298038bb7d6789e50e199332f66 (diff)
downloadcpython-bd2728b1e8a99ba8f8c2d481f88aeb99b8b8360f.zip
cpython-bd2728b1e8a99ba8f8c2d481f88aeb99b8b8360f.tar.gz
cpython-bd2728b1e8a99ba8f8c2d481f88aeb99b8b8360f.tar.bz2
bpo-42806: Fix ast locations of f-strings inside parentheses (GH-24067)
-rw-r--r--Lib/test/test_fstring.py53
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2021-01-03-00-20-38.bpo-42806.mLAobJ.rst2
-rw-r--r--Parser/string_parser.c2
3 files changed, 56 insertions, 1 deletions
diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py
index b53661a..2345832 100644
--- a/Lib/test/test_fstring.py
+++ b/Lib/test/test_fstring.py
@@ -332,6 +332,59 @@ non-important content
self.assertEqual(binop.left.col_offset, 4)
self.assertEqual(binop.right.col_offset, 7)
+ def test_ast_line_numbers_with_parentheses(self):
+ expr = """
+x = (
+ f" {test(t)}"
+)"""
+ t = ast.parse(expr)
+ self.assertEqual(type(t), ast.Module)
+ self.assertEqual(len(t.body), 1)
+ # check the test(t) location
+ call = t.body[0].value.values[1].value
+ self.assertEqual(type(call), ast.Call)
+ self.assertEqual(call.lineno, 3)
+ self.assertEqual(call.end_lineno, 3)
+ self.assertEqual(call.col_offset, 8)
+ self.assertEqual(call.end_col_offset, 15)
+
+ expr = """
+x = (
+ 'PERL_MM_OPT', (
+ f'wat'
+ f'some_string={f(x)} '
+ f'wat'
+ ),
+)
+"""
+ t = ast.parse(expr)
+ self.assertEqual(type(t), ast.Module)
+ self.assertEqual(len(t.body), 1)
+ # check the fstring
+ fstring = t.body[0].value.elts[1]
+ self.assertEqual(type(fstring), ast.JoinedStr)
+ self.assertEqual(len(fstring.values), 3)
+ wat1, middle, wat2 = fstring.values
+ # check the first wat
+ self.assertEqual(type(wat1), ast.Constant)
+ self.assertEqual(wat1.lineno, 4)
+ self.assertEqual(wat1.end_lineno, 6)
+ self.assertEqual(wat1.col_offset, 12)
+ self.assertEqual(wat1.end_col_offset, 18)
+ # check the call
+ call = middle.value
+ self.assertEqual(type(call), ast.Call)
+ self.assertEqual(call.lineno, 5)
+ self.assertEqual(call.end_lineno, 5)
+ self.assertEqual(call.col_offset, 27)
+ self.assertEqual(call.end_col_offset, 31)
+ # check the second wat
+ self.assertEqual(type(wat2), ast.Constant)
+ self.assertEqual(wat2.lineno, 4)
+ self.assertEqual(wat2.end_lineno, 6)
+ self.assertEqual(wat2.col_offset, 12)
+ self.assertEqual(wat2.end_col_offset, 18)
+
def test_docstring(self):
def f():
f'''Not a docstring'''
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-01-03-00-20-38.bpo-42806.mLAobJ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-01-03-00-20-38.bpo-42806.mLAobJ.rst
new file mode 100644
index 0000000..10314fd
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-01-03-00-20-38.bpo-42806.mLAobJ.rst
@@ -0,0 +1,2 @@
+Fix the column offsets for f-strings :mod:`ast` nodes surrounded by
+parentheses and for nodes that spawn multiple lines. Patch by Pablo Galindo.
diff --git a/Parser/string_parser.c b/Parser/string_parser.c
index 09b8c35..a41f41c 100644
--- a/Parser/string_parser.c
+++ b/Parser/string_parser.c
@@ -405,7 +405,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
NULL, p->arena);
p2->starting_lineno = t->lineno + lines - 1;
- p2->starting_col_offset = p->tok->first_lineno == p->tok->lineno ? t->col_offset + cols : cols;
+ p2->starting_col_offset = t->col_offset + cols;
expr = _PyPegen_run_parser(p2);