Skip to content

Commit 51cef8b

Browse files
authored
bpo-44142: drop redundant parantheses when unparsing tuples as assignment targets (GH-26156)
1 parent 1a08c5a commit 51cef8b

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

Lib/ast.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,8 @@ class Param(expr_context):
640640
class _Precedence:
641641
"""Precedence table that originated from python grammar."""
642642

643-
TUPLE = auto()
643+
NAMED_EXPR = auto() # <target> := <expr1>
644+
TUPLE = auto() # <expr1>, <expr2>
644645
YIELD = auto() # 'yield', 'yield from'
645646
TEST = auto() # 'if'-'else', 'lambda'
646647
OR = auto() # 'or'
@@ -838,7 +839,7 @@ def visit_Expr(self, node):
838839
self.traverse(node.value)
839840

840841
def visit_NamedExpr(self, node):
841-
with self.require_parens(_Precedence.TUPLE, node):
842+
with self.require_parens(_Precedence.NAMED_EXPR, node):
842843
self.set_precedence(_Precedence.ATOM, node.target, node.value)
843844
self.traverse(node.target)
844845
self.write(" := ")
@@ -859,6 +860,7 @@ def visit_ImportFrom(self, node):
859860
def visit_Assign(self, node):
860861
self.fill()
861862
for target in node.targets:
863+
self.set_precedence(_Precedence.TUPLE, target)
862864
self.traverse(target)
863865
self.write(" = ")
864866
self.traverse(node.value)
@@ -1030,6 +1032,7 @@ def visit_AsyncFor(self, node):
10301032

10311033
def _for_helper(self, fill, node):
10321034
self.fill(fill)
1035+
self.set_precedence(_Precedence.TUPLE, node.target)
10331036
self.traverse(node.target)
10341037
self.write(" in ")
10351038
self.traverse(node.iter)
@@ -1315,7 +1318,7 @@ def write_item(item):
13151318
)
13161319

13171320
def visit_Tuple(self, node):
1318-
with self.delimit("(", ")"):
1321+
with self.require_parens(_Precedence.TUPLE, node):
13191322
self.items_view(self.traverse, node.elts)
13201323

13211324
unop = {"Invert": "~", "Not": "not", "UAdd": "+", "USub": "-"}

Lib/test/test_ast.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,8 @@ def test_constant_as_name(self):
702702
def test_precedence_enum(self):
703703
class _Precedence(enum.IntEnum):
704704
"""Precedence table that originated from python grammar."""
705-
TUPLE = enum.auto()
705+
NAMED_EXPR = enum.auto() # <target> := <expr1>
706+
TUPLE = enum.auto() # <expr1>, <expr2>
706707
YIELD = enum.auto() # 'yield', 'yield from'
707708
TEST = enum.auto() # 'if'-'else', 'lambda'
708709
OR = enum.auto() # 'or'

Lib/test/test_unparse.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,43 @@ def test_lambda_parameters(self):
541541
self.check_src_roundtrip("lambda x, y, /, z, q, *, u: None")
542542
self.check_src_roundtrip("lambda x, *y, **z: None")
543543

544+
def test_star_expr_assign_target(self):
545+
for source_type, source in [
546+
("single assignment", "{target} = foo"),
547+
("multiple assignment", "{target} = {target} = bar"),
548+
("for loop", "for {target} in foo:\n pass"),
549+
("async for loop", "async for {target} in foo:\n pass")
550+
]:
551+
for target in [
552+
"a",
553+
"a,",
554+
"a, b",
555+
"a, *b, c",
556+
"a, (b, c), d",
557+
"a, (b, c, d), *e",
558+
"a, (b, *c, d), e",
559+
"a, (b, *c, (d, e), f), g",
560+
"[a]",
561+
"[a, b]",
562+
"[a, *b, c]",
563+
"[a, [b, c], d]",
564+
"[a, [b, c, d], *e]",
565+
"[a, [b, *c, d], e]",
566+
"[a, [b, *c, [d, e], f], g]",
567+
"a, [b, c], d",
568+
"[a, b, (c, d), (e, f)]",
569+
"a, b, [*c], d, e"
570+
]:
571+
with self.subTest(source_type=source_type, target=target):
572+
self.check_src_roundtrip(source.format(target=target))
573+
574+
def test_star_expr_assign_target_multiple(self):
575+
self.check_src_roundtrip("a = b = c = d")
576+
self.check_src_roundtrip("a, b = c, d = e, f = g")
577+
self.check_src_roundtrip("[a, b] = [c, d] = [e, f] = g")
578+
self.check_src_roundtrip("a, b = [c, d] = e, f = g")
579+
580+
544581

545582
class DirectoryTestCase(ASTTestCase):
546583
"""Test roundtrip behaviour on all files in Lib and Lib/test."""
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`ast.unparse` will now drop the redundant parentheses when tuples used
2+
as assignment targets (e.g in for loops).

0 commit comments

Comments
 (0)