From 110a47c4f42cf4db88edc1876899fff8f05190fb Mon Sep 17 00:00:00 2001 From: Carl Friedrich Bolz-Tereick Date: Mon, 8 Jul 2019 23:17:56 +0200 Subject: [PATCH] bpo-18374: fix wrong col_offset of some ast.BinOp instances (GH-14607) Nested BinOp instances (e.g. a+b+c) had a wrong col_offset for the second BinOp (e.g. 2 instead of 0 in the example). Fix it by using the correct st node to copy the line and col_offset from in ast.c. --- Lib/test/test_ast.py | 30 +++++++++++++++++++ Misc/ACKS | 1 + .../2019-07-05-21-46-45.bpo-18374.qgE0H3.rst | 2 ++ Python/ast.c | 2 +- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2019-07-05-21-46-45.bpo-18374.qgE0H3.rst diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index e251e254afd..1e07c573c84 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -576,6 +576,36 @@ class AST_Tests(unittest.TestCase): with support.swap_attr(unicodedata, 'normalize', bad_normalize): self.assertRaises(TypeError, ast.parse, '\u03D5') + def test_issue18374_binop_col_offset(self): + tree = ast.parse('4+5+6+7') + parent_binop = tree.body[0].value + child_binop = parent_binop.left + grandchild_binop = child_binop.left + self.assertEqual(parent_binop.col_offset, 0) + self.assertEqual(parent_binop.end_col_offset, 7) + self.assertEqual(child_binop.col_offset, 0) + self.assertEqual(child_binop.end_col_offset, 5) + self.assertEqual(grandchild_binop.col_offset, 0) + self.assertEqual(grandchild_binop.end_col_offset, 3) + + tree = ast.parse('4+5-\\\n 6-7') + parent_binop = tree.body[0].value + child_binop = parent_binop.left + grandchild_binop = child_binop.left + self.assertEqual(parent_binop.col_offset, 0) + self.assertEqual(parent_binop.lineno, 1) + self.assertEqual(parent_binop.end_col_offset, 4) + self.assertEqual(parent_binop.end_lineno, 2) + + self.assertEqual(child_binop.col_offset, 0) + self.assertEqual(parent_binop.lineno, 1) + self.assertEqual(child_binop.end_col_offset, 2) + self.assertEqual(parent_binop.end_lineno, 2) + + self.assertEqual(grandchild_binop.col_offset, 0) + self.assertEqual(parent_binop.lineno, 1) + self.assertEqual(grandchild_binop.end_col_offset, 3) + self.assertEqual(parent_binop.end_lineno, 2) class ASTHelpers_Test(unittest.TestCase): maxDiff = None diff --git a/Misc/ACKS b/Misc/ACKS index 36fe727c842..d916c45a8e4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -178,6 +178,7 @@ Nikolay Bogoychev David Bolen Wouter Bolsterlee Gawain Bolton +Carl Friedrich Bolz-Tereick Forest Bond Gregory Bond Médéric Boquien diff --git a/Misc/NEWS.d/next/Library/2019-07-05-21-46-45.bpo-18374.qgE0H3.rst b/Misc/NEWS.d/next/Library/2019-07-05-21-46-45.bpo-18374.qgE0H3.rst new file mode 100644 index 00000000000..f9e99e0474a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-05-21-46-45.bpo-18374.qgE0H3.rst @@ -0,0 +1,2 @@ +Fix the ``.col_offset`` attribute of nested :class:`ast.BinOp` instances +which had a too large value in some situations. diff --git a/Python/ast.c b/Python/ast.c index 16895ce62ec..8dc86c23d62 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2645,7 +2645,7 @@ ast_for_binop(struct compiling *c, const node *n) return NULL; tmp_result = BinOp(result, newoperator, tmp, - LINENO(next_oper), next_oper->n_col_offset, + LINENO(n), n->n_col_offset, CHILD(n, i * 2 + 2)->n_end_lineno, CHILD(n, i * 2 + 2)->n_end_col_offset, c->c_arena);