summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2020-08-05 13:52:29 (GMT)
committerGitHub <noreply@github.com>2020-08-05 13:52:29 (GMT)
commita1320989f5350439e0677450f49b36f2c10583d2 (patch)
treeec5f1413a0abf0bdc224e626320070c1846cb4ef /Lib
parentea680631b478f091a171dc802d861f5014f58c8f (diff)
downloadcpython-a1320989f5350439e0677450f49b36f2c10583d2.zip
cpython-a1320989f5350439e0677450f49b36f2c10583d2.tar.gz
cpython-a1320989f5350439e0677450f49b36f2c10583d2.tar.bz2
bpo-40726: handle uninitalized end_lineno on ast.increment_lineno (GH-20312)
(cherry picked from commit 8f4380d2f5839a321475104765221a7394a9d649) Co-authored-by: Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
Diffstat (limited to 'Lib')
-rw-r--r--Lib/ast.py13
-rw-r--r--Lib/test/test_ast.py11
2 files changed, 21 insertions, 3 deletions
diff --git a/Lib/ast.py b/Lib/ast.py
index 6a5b39e..65ebd01 100644
--- a/Lib/ast.py
+++ b/Lib/ast.py
@@ -180,7 +180,11 @@ def copy_location(new_node, old_node):
for attr in 'lineno', 'col_offset', 'end_lineno', 'end_col_offset':
if attr in old_node._attributes and attr in new_node._attributes:
value = getattr(old_node, attr, None)
- if value is not None:
+ # end_lineno and end_col_offset are optional attributes, and they
+ # should be copied whether the value is None or not.
+ if value is not None or (
+ hasattr(old_node, attr) and attr.startswith("end_")
+ ):
setattr(new_node, attr, value)
return new_node
@@ -229,8 +233,11 @@ def increment_lineno(node, n=1):
for child in walk(node):
if 'lineno' in child._attributes:
child.lineno = getattr(child, 'lineno', 0) + n
- if 'end_lineno' in child._attributes:
- child.end_lineno = getattr(child, 'end_lineno', 0) + n
+ if (
+ "end_lineno" in child._attributes
+ and (end_lineno := getattr(child, "end_lineno", 0)) is not None
+ ):
+ child.end_lineno = end_lineno + n
return node
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index 78e4a56..f5aef61 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -812,6 +812,12 @@ Module(
'lineno=1, col_offset=4, end_lineno=1, end_col_offset=5), lineno=1, '
'col_offset=0, end_lineno=1, end_col_offset=5))'
)
+ src = ast.Call(col_offset=1, lineno=1, end_lineno=1, end_col_offset=1)
+ new = ast.copy_location(src, ast.Call(col_offset=None, lineno=None))
+ self.assertIsNone(new.end_lineno)
+ self.assertIsNone(new.end_col_offset)
+ self.assertEqual(new.lineno, 1)
+ self.assertEqual(new.col_offset, 1)
def test_fix_missing_locations(self):
src = ast.parse('write("spam")')
@@ -851,6 +857,11 @@ Module(
'lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, '
'col_offset=0, end_lineno=4, end_col_offset=5))'
)
+ src = ast.Call(
+ func=ast.Name("test", ast.Load()), args=[], keywords=[], lineno=1
+ )
+ self.assertEqual(ast.increment_lineno(src).lineno, 2)
+ self.assertIsNone(ast.increment_lineno(src).end_lineno)
def test_iter_fields(self):
node = ast.parse('foo()', mode='eval')