# HG changeset patch # Parent d384bf58f5f8afd2a4cccea63d0cbac31f236e18 Issue #23275: Allow () = iterable assignment syntax; fix the documentation Patch by Berker Peksag. diff -r d384bf58f5f8 Doc/reference/simple_stmts.rst --- a/Doc/reference/simple_stmts.rst Mon May 16 23:20:32 2016 -0700 +++ b/Doc/reference/simple_stmts.rst Tue May 17 10:48:55 2016 +0000 @@ -84,8 +84,8 @@ assignment_stmt: (`target_list` "=")+ (`expression_list` | `yield_expression`) target_list: `target` ("," `target`)* [","] target: `identifier` - : | "(" `target_list` ")" - : | "[" `target_list` "]" + : | "(" [`target_list`] ")" + : | "[" [`target_list`] "]" : | `attributeref` : | `subscription` : | `slicing` @@ -115,21 +115,25 @@ Assignment of an object to a target list, optionally enclosed in parentheses or square brackets, is recursively defined as follows. -* If the target list is a single target: The object is assigned to that target. +* If the target list is empty: The object must also be an empty iterable. -* If the target list is a comma-separated list of targets: The object must be an +* If the target list is a single target in parentheses: The object + is assigned to that target. + +* If the target list is a comma-separated list of targets, + or a single target in square brackets: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets. * If the target list contains one target prefixed with an asterisk, called a - "starred" target: The object must be a sequence with at least as many items + "starred" target: The object must be an iterable with at least as many items as there are targets in the target list, minus one. The first items of the - sequence are assigned, from left to right, to the targets before the starred - target. The final items of the sequence are assigned to the targets after - the starred target. A list of the remaining items in the sequence is then + iterable are assigned, from left to right, to the targets before the starred + target. The final items of the iterable are assigned to the targets after + the starred target. A list of the remaining items in the iterable is then assigned to the starred target (the list can be empty). - * Else: The object must be a sequence with the same number of items as there + * Else: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets. @@ -150,11 +154,6 @@ count for the object previously bound to the name to reach zero, causing the object to be deallocated and its destructor (if it has one) to be called. -* If the target is a target list enclosed in parentheses or in square brackets: - The object must be an iterable with the same number of items as there are - targets in the target list, and its items are assigned, from left to right, - to the corresponding targets. - .. index:: pair: attribute; assignment * If the target is an attribute reference: The primary expression in the diff -r d384bf58f5f8 Lib/test/test_codeop.py --- a/Lib/test/test_codeop.py Mon May 16 23:20:32 2016 -0700 +++ b/Lib/test/test_codeop.py Tue May 17 10:48:55 2016 +0000 @@ -282,7 +282,6 @@ ai("if (a == 1 and b = 2): pass") ai("del 1") - ai("del ()") ai("del (1,)") ai("del [1]") ai("del '1'") diff -r d384bf58f5f8 Lib/test/test_syntax.py --- a/Lib/test/test_syntax.py Mon May 16 23:20:32 2016 -0700 +++ b/Lib/test/test_syntax.py Tue May 17 10:48:55 2016 +0000 @@ -35,14 +35,6 @@ Traceback (most recent call last): SyntaxError: can't assign to keyword -It's a syntax error to assign to the empty tuple. Why isn't it an -error to assign to the empty list? It will always raise some error at -runtime. - ->>> () = 1 -Traceback (most recent call last): -SyntaxError: can't assign to () - >>> f() = 1 Traceback (most recent call last): SyntaxError: can't assign to function call @@ -491,10 +483,6 @@ ... SyntaxError: keyword argument repeated ->>> del () -Traceback (most recent call last): -SyntaxError: can't delete () - >>> {1, 2, 3} = 42 Traceback (most recent call last): SyntaxError: can't assign to literal diff -r d384bf58f5f8 Lib/test/test_unpack.py --- a/Lib/test/test_unpack.py Mon May 16 23:20:32 2016 -0700 +++ b/Lib/test/test_unpack.py Tue May 17 10:48:55 2016 +0000 @@ -117,6 +117,27 @@ ... test.test_unpack.BozoError +Allow unpacking empty iterables + + >>> () = [] + >>> [] = () + >>> [] = [] + >>> () = () + +Unpacking non-iterables should raise TypeError + + >>> () = 42 + Traceback (most recent call last): + ... + TypeError: 'int' object is not iterable + +Unpacking to an empty iterable should raise ValueError + + >>> () = [42] + Traceback (most recent call last): + ... + ValueError: too many values to unpack (expected 0) + """ __test__ = {'doctests' : doctests} diff -r d384bf58f5f8 Lib/test/test_with.py --- a/Lib/test/test_with.py Mon May 16 23:20:32 2016 -0700 +++ b/Lib/test/test_with.py Tue May 17 10:48:55 2016 +0000 @@ -140,11 +140,6 @@ 'with mock as (None):\n' ' pass') - def testAssignmentToEmptyTupleError(self): - self.assertRaisesSyntaxError( - 'with mock as ():\n' - ' pass') - def testAssignmentToTupleOnlyContainingNoneError(self): self.assertRaisesSyntaxError('with mock as None,:\n pass') self.assertRaisesSyntaxError( diff -r d384bf58f5f8 Misc/NEWS --- a/Misc/NEWS Mon May 16 23:20:32 2016 -0700 +++ b/Misc/NEWS Tue May 17 10:48:55 2016 +0000 @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23275: Allow assigning to an empty target list in round brackets: + () = iterable. + - Issue #26991: Fix possible refleak when creating a function with annotations. - Issue #27039: Fixed bytearray.remove() for values greater than 127. Based on diff -r d384bf58f5f8 Python/ast.c --- a/Python/ast.c Mon May 16 23:20:32 2016 -0700 +++ b/Python/ast.c Tue May 17 10:48:55 2016 +0000 @@ -990,13 +990,8 @@ s = e->v.List.elts; break; case Tuple_kind: - if (asdl_seq_LEN(e->v.Tuple.elts)) { - e->v.Tuple.ctx = ctx; - s = e->v.Tuple.elts; - } - else { - expr_name = "()"; - } + e->v.Tuple.ctx = ctx; + s = e->v.Tuple.elts; break; case Lambda_kind: expr_name = "lambda";