[Python-checkins] [3.9] bpo-41979: Accept star-unpacking on with-item targets (GH-22611) (GH-22612)

Batuhan Taskaya webhook-mailer at python.org
Fri Oct 9 06:31:16 EDT 2020


https://github.com/python/cpython/commit/42157b9eaa7f4de69a5f5f65d4403d70efa6a5c2
commit: 42157b9eaa7f4de69a5f5f65d4403d70efa6a5c2
branch: 3.9
author: Batuhan Taskaya <batuhanosmantaskaya at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-10-09T03:31:07-07:00
summary:

[3.9] bpo-41979: Accept star-unpacking on with-item targets (GH-22611) (GH-22612)



Co-authored-by: Batuhan Taskaya <batuhanosmantaskaya at gmail.com>

Automerge-Triggered-By: @pablogsal

files:
A Misc/NEWS.d/next/Core and Builtins/2020-10-09-10-55-50.bpo-41979.ImXIk2.rst
M Grammar/python.gram
M Lib/test/test_with.py
M Parser/pegen/parse.c

diff --git a/Grammar/python.gram b/Grammar/python.gram
index 334a7f56f0107..8f4d250dc3ae4 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -182,7 +182,7 @@ with_stmt[stmt_ty]:
     | ASYNC 'with' a=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
        CHECK_VERSION(5, "Async with statements are", _Py_AsyncWith(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
 with_item[withitem_ty]:
-    | e=expression 'as' t=target &(',' | ')' | ':') { _Py_withitem(e, t, p->arena) }
+    | e=expression 'as' t=star_target &(',' | ')' | ':') { _Py_withitem(e, t, p->arena) }
     | invalid_with_item
     | e=expression { _Py_withitem(e, NULL, p->arena) }
 
diff --git a/Lib/test/test_with.py b/Lib/test/test_with.py
index b1d7a15b5e4ee..f21bf65fed849 100644
--- a/Lib/test/test_with.py
+++ b/Lib/test/test_with.py
@@ -7,7 +7,7 @@
 import sys
 import unittest
 from collections import deque
-from contextlib import _GeneratorContextManager, contextmanager
+from contextlib import _GeneratorContextManager, contextmanager, nullcontext
 
 
 class MockContextManager(_GeneratorContextManager):
@@ -641,6 +641,12 @@ class B: pass
             self.assertEqual(blah.two, 2)
             self.assertEqual(blah.three, 3)
 
+    def testWithExtendedTargets(self):
+        with nullcontext(range(1, 5)) as (a, *b, c):
+            self.assertEqual(a, 1)
+            self.assertEqual(b, [2, 3])
+            self.assertEqual(c, 4)
+
 
 class ExitSwallowsExceptionTestCase(unittest.TestCase):
 
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-10-09-10-55-50.bpo-41979.ImXIk2.rst b/Misc/NEWS.d/next/Core and Builtins/2020-10-09-10-55-50.bpo-41979.ImXIk2.rst
new file mode 100644
index 0000000000000..3250309ca22cd
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-10-09-10-55-50.bpo-41979.ImXIk2.rst	
@@ -0,0 +1 @@
+Star-unpacking is now allowed for with item's targets in the PEG parser.
diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c
index f74b6f297b040..1a4df757eae33 100644
--- a/Parser/pegen/parse.c
+++ b/Parser/pegen/parse.c
@@ -4289,7 +4289,10 @@ with_stmt_rule(Parser *p)
     return _res;
 }
 
-// with_item: expression 'as' target &(',' | ')' | ':') | invalid_with_item | expression
+// with_item:
+//     | expression 'as' star_target &(',' | ')' | ':')
+//     | invalid_with_item
+//     | expression
 static withitem_ty
 with_item_rule(Parser *p)
 {
@@ -4300,12 +4303,12 @@ with_item_rule(Parser *p)
     }
     withitem_ty _res = NULL;
     int _mark = p->mark;
-    { // expression 'as' target &(',' | ')' | ':')
+    { // expression 'as' star_target &(',' | ')' | ':')
         if (p->error_indicator) {
             D(p->level--);
             return NULL;
         }
-        D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' target &(',' | ')' | ':')"));
+        D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')"));
         Token * _keyword;
         expr_ty e;
         expr_ty t;
@@ -4314,12 +4317,12 @@ with_item_rule(Parser *p)
             &&
             (_keyword = _PyPegen_expect_token(p, 520))  // token='as'
             &&
-            (t = target_rule(p))  // target
+            (t = star_target_rule(p))  // star_target
             &&
             _PyPegen_lookahead(1, _tmp_47_rule, p)
         )
         {
-            D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' target &(',' | ')' | ':')"));
+            D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')"));
             _res = _Py_withitem ( e , t , p -> arena );
             if (_res == NULL && PyErr_Occurred()) {
                 p->error_indicator = 1;
@@ -4330,7 +4333,7 @@ with_item_rule(Parser *p)
         }
         p->mark = _mark;
         D(fprintf(stderr, "%*c%s with_item[%d-%d]: %s failed!\n", p->level, ' ',
-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression 'as' target &(',' | ')' | ':')"));
+                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')"));
     }
     { // invalid_with_item
         if (p->error_indicator) {



More information about the Python-checkins mailing list