bpo-41979: Accept star-unpacking on with-item targets (GH-22611)
Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
This commit is contained in:
parent
666f583e9e
commit
48f305fd12
|
@ -182,7 +182,7 @@ with_stmt[stmt_ty]:
|
||||||
| ASYNC 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
|
| ASYNC 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
|
||||||
CHECK_VERSION(5, "Async with statements are", _Py_AsyncWith(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
|
CHECK_VERSION(5, "Async with statements are", _Py_AsyncWith(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
|
||||||
with_item[withitem_ty]:
|
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
|
| invalid_with_item
|
||||||
| e=expression { _Py_withitem(e, NULL, p->arena) }
|
| e=expression { _Py_withitem(e, NULL, p->arena) }
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ __email__ = "mbland at acm dot org"
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from contextlib import _GeneratorContextManager, contextmanager
|
from contextlib import _GeneratorContextManager, contextmanager, nullcontext
|
||||||
|
|
||||||
|
|
||||||
class MockContextManager(_GeneratorContextManager):
|
class MockContextManager(_GeneratorContextManager):
|
||||||
|
@ -641,6 +641,12 @@ class AssignmentTargetTestCase(unittest.TestCase):
|
||||||
self.assertEqual(blah.two, 2)
|
self.assertEqual(blah.two, 2)
|
||||||
self.assertEqual(blah.three, 3)
|
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):
|
class ExitSwallowsExceptionTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Star-unpacking is now allowed for with item's targets in the PEG parser.
|
|
@ -4290,7 +4290,10 @@ with_stmt_rule(Parser *p)
|
||||||
return _res;
|
return _res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// with_item: expression 'as' target &(',' | ')' | ':') | invalid_with_item | expression
|
// with_item:
|
||||||
|
// | expression 'as' star_target &(',' | ')' | ':')
|
||||||
|
// | invalid_with_item
|
||||||
|
// | expression
|
||||||
static withitem_ty
|
static withitem_ty
|
||||||
with_item_rule(Parser *p)
|
with_item_rule(Parser *p)
|
||||||
{
|
{
|
||||||
|
@ -4301,12 +4304,12 @@ with_item_rule(Parser *p)
|
||||||
}
|
}
|
||||||
withitem_ty _res = NULL;
|
withitem_ty _res = NULL;
|
||||||
int _mark = p->mark;
|
int _mark = p->mark;
|
||||||
{ // expression 'as' target &(',' | ')' | ':')
|
{ // expression 'as' star_target &(',' | ')' | ':')
|
||||||
if (p->error_indicator) {
|
if (p->error_indicator) {
|
||||||
D(p->level--);
|
D(p->level--);
|
||||||
return NULL;
|
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;
|
Token * _keyword;
|
||||||
expr_ty e;
|
expr_ty e;
|
||||||
expr_ty t;
|
expr_ty t;
|
||||||
|
@ -4315,12 +4318,12 @@ with_item_rule(Parser *p)
|
||||||
&&
|
&&
|
||||||
(_keyword = _PyPegen_expect_token(p, 520)) // token='as'
|
(_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)
|
_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 );
|
_res = _Py_withitem ( e , t , p -> arena );
|
||||||
if (_res == NULL && PyErr_Occurred()) {
|
if (_res == NULL && PyErr_Occurred()) {
|
||||||
p->error_indicator = 1;
|
p->error_indicator = 1;
|
||||||
|
@ -4331,7 +4334,7 @@ with_item_rule(Parser *p)
|
||||||
}
|
}
|
||||||
p->mark = _mark;
|
p->mark = _mark;
|
||||||
D(fprintf(stderr, "%*c%s with_item[%d-%d]: %s failed!\n", p->level, ' ',
|
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
|
{ // invalid_with_item
|
||||||
if (p->error_indicator) {
|
if (p->error_indicator) {
|
||||||
|
|
Loading…
Reference in New Issue