From 45f7ffdd17654f4093a7d00e481bed53e299c52b Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Sun, 17 May 2020 18:08:36 +0300 Subject: [PATCH 1/3] bpo-38870: Only ignore parens when the inside expression is simple --- Lib/ast.py | 6 +++++- Lib/test/test_unparse.py | 10 +++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py index 61fbe030a78252..889a162577a3bf 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -1349,7 +1349,11 @@ def visit_Subscript(self, node): self.set_precedence(_Precedence.ATOM, node.value) self.traverse(node.value) with self.delimit("[", "]"): - if isinstance(node.slice, Tuple) and node.slice.elts: + if ( + isinstance(node.slice, Tuple) + and node.slice.elts + and not any(isinstance(elt, Starred) for elt in node.slice.elts) + ): self.items_view(self.traverse, node.slice.elts) else: self.traverse(node.slice) diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index 67dcb1dae79ff2..3e270402dc7c2b 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -279,10 +279,13 @@ def test_dict_unpacking_in_dict(self): self.check_ast_roundtrip(r"""{**{'y': 2}, 'x': 1}""") self.check_ast_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""") - def test_ext_slices(self): + def test_slices(self): self.check_ast_roundtrip("a[i]") self.check_ast_roundtrip("a[i,]") self.check_ast_roundtrip("a[i, j]") + self.check_ast_roundtrip("a[(*a,)]") + self.check_ast_roundtrip("a[(a:=b)]") + self.check_ast_roundtrip("a[(a:=b,c)]") self.check_ast_roundtrip("a[()]") self.check_ast_roundtrip("a[i:j]") self.check_ast_roundtrip("a[:j]") @@ -466,6 +469,11 @@ def test_unary_op_factor(self): for prefix in ("not",): self.check_src_roundtrip(f"{prefix} 1") + def test_slices(self): + self.check_src_roundtrip("a[1]") + self.check_src_roundtrip("a[1, 2]") + self.check_src_roundtrip("a[(1, *a)]") + class DirectoryTestCase(ASTTestCase): """Test roundtrip behaviour on all files in Lib and Lib/test.""" From 6d45f39a13a27a5e4606e727e8dd2a26961f3377 Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Mon, 18 May 2020 21:50:27 +0300 Subject: [PATCH 2/3] extract to the function --- Lib/ast.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py index 889a162577a3bf..894d158666b658 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -1346,14 +1346,20 @@ def visit_Call(self, node): self.traverse(e) def visit_Subscript(self, node): + def is_simple_tuple(slice_value): + # return True if the slice is a non-empty tuple + # and there aren't any starred expression inside + # of the elements + return ( + isinstance(slice_value, Tuple) + and slice_value.elts + and not any(isinstance(elt, Starred) for elt in slice_value.elts) + ) + self.set_precedence(_Precedence.ATOM, node.value) self.traverse(node.value) with self.delimit("[", "]"): - if ( - isinstance(node.slice, Tuple) - and node.slice.elts - and not any(isinstance(elt, Starred) for elt in node.slice.elts) - ): + if is_simple_tuple(node.slice): self.items_view(self.traverse, node.slice.elts) else: self.traverse(node.slice) From f5b3508c55ded8bb5ee332e0c552dfa4b97a7daa Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Mon, 18 May 2020 22:04:31 +0300 Subject: [PATCH 3/3] tell why instead of how in the comments --- Lib/ast.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py index 894d158666b658..e191b71c293673 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -1347,9 +1347,9 @@ def visit_Call(self, node): def visit_Subscript(self, node): def is_simple_tuple(slice_value): - # return True if the slice is a non-empty tuple - # and there aren't any starred expression inside - # of the elements + # when unparsing a non-empty tuple, the parantheses can be safely + # omitted if there aren't any elements that explicitly requires + # parantheses (such as starred expressions). return ( isinstance(slice_value, Tuple) and slice_value.elts