]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #23275: Allow () = iterable assignment syntax
authorBerker Peksag <berker.peksag@gmail.com>
Wed, 18 May 2016 05:44:29 +0000 (08:44 +0300)
committerBerker Peksag <berker.peksag@gmail.com>
Wed, 18 May 2016 05:44:29 +0000 (08:44 +0300)
Documentation updates by Martin Panter.

Doc/reference/simple_stmts.rst
Lib/test/test_codeop.py
Lib/test/test_syntax.py
Lib/test/test_unpack.py
Lib/test/test_with.py
Misc/NEWS
Python/ast.c

index ff5b1cabc60b4dd29fbb4bac633daf6c70288a21..59493c3aedd82ade3608bea3dafa95abf9c1e16a 100644 (file)
@@ -84,8 +84,8 @@ attributes or items of mutable objects:
    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 @@ given with the definition of the object types (see section :ref:`types`).
 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
-  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 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 @@ Assignment of an object to a single target is recursively defined as follows.
   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
index 509bf5dfd21e76cd3c378e6d8f559e2d0de99a62..98da26fa5dab13a2e0c7a21f62eac97045e4b78e 100644 (file)
@@ -282,7 +282,6 @@ class CodeopTests(unittest.TestCase):
         ai("if (a == 1 and b = 2): pass")
 
         ai("del 1")
-        ai("del ()")
         ai("del (1,)")
         ai("del [1]")
         ai("del '1'")
index 057441c83c0f7109a3d7565efb4359836533dbd5..38fc4175241a655c41a32702150ec0489005a66f 100644 (file)
@@ -35,14 +35,6 @@ SyntaxError: invalid syntax
 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 @@ Traceback (most recent call last):
    ...
 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
index d1ccb38937b7422178e362894bc61875d3d6ba8a..3fcb18fb43af301bec022c4043fd732ef7fe7704 100644 (file)
@@ -117,6 +117,27 @@ error)
       ...
     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}
index 3815062a588df901641b4eaae4c209f45ca00375..e247ff6a6171e3044f364900c15b9170e58e0cf1 100644 (file)
@@ -140,11 +140,6 @@ class FailureTestCase(unittest.TestCase):
             '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(
index cbea5fdccdbba8faec21244f5bd8cb4125107560..213a864588097525d5d6a066534eb2b01fe03fc9 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,9 @@ Release date: 2016-05-16
 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
index ad771cf702355f642f281684055e7f817efd5c4e..1efd0b7daa36b64bb77de15bf4c1fce567ec1124 100644 (file)
@@ -990,13 +990,8 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
             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";