Skip to content

Commit 5244e21

Browse files
committed
bpo-42374: Allow unparenthesized walrus in genexps (pythonGH-23319)
This fixes a regression that was introduced by the new parser. (cherry picked from commit cb3e5ed)
1 parent cf70854 commit 5244e21

File tree

4 files changed

+18
-7
lines changed

4 files changed

+18
-7
lines changed

Grammar/python.gram

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ group[expr_ty]:
503503
| '(' a=(yield_expr | named_expression) ')' { a }
504504
| invalid_group
505505
genexp[expr_ty]:
506-
| '(' a=expression ~ b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
506+
| '(' a=named_expression ~ b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
507507
| invalid_comprehension
508508
set[expr_ty]: '{' a=expressions_list '}' { _Py_Set(a, EXTRA) }
509509
setcomp[expr_ty]:

Lib/test/test_named_expressions.py

+9
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,15 @@ def g():
513513
self.assertEqual(nonlocal_var, None)
514514
f()
515515

516+
def test_named_expression_scope_in_genexp(self):
517+
a = 1
518+
b = [1, 2, 3, 4]
519+
genexp = (c := i + a for i in b)
520+
521+
self.assertNotIn("c", locals())
522+
for idx, elem in enumerate(genexp):
523+
self.assertEqual(elem, b[idx] + a)
524+
516525

517526
if __name__ == "__main__":
518527
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a regression introduced by the new parser, where an unparenthesized walrus operator
2+
was not allowed within generator expressions.

Parser/pegen/parse.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -11381,7 +11381,7 @@ group_rule(Parser *p)
1138111381
return _res;
1138211382
}
1138311383

11384-
// genexp: '(' expression ~ for_if_clauses ')' | invalid_comprehension
11384+
// genexp: '(' named_expression ~ for_if_clauses ')' | invalid_comprehension
1138511385
static expr_ty
1138611386
genexp_rule(Parser *p)
1138711387
{
@@ -11401,12 +11401,12 @@ genexp_rule(Parser *p)
1140111401
UNUSED(_start_lineno); // Only used by EXTRA macro
1140211402
int _start_col_offset = p->tokens[_mark]->col_offset;
1140311403
UNUSED(_start_col_offset); // Only used by EXTRA macro
11404-
{ // '(' expression ~ for_if_clauses ')'
11404+
{ // '(' named_expression ~ for_if_clauses ')'
1140511405
if (p->error_indicator) {
1140611406
D(p->level--);
1140711407
return NULL;
1140811408
}
11409-
D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' expression ~ for_if_clauses ')'"));
11409+
D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
1141011410
int _cut_var = 0;
1141111411
Token * _literal;
1141211412
Token * _literal_1;
@@ -11415,7 +11415,7 @@ genexp_rule(Parser *p)
1141511415
if (
1141611416
(_literal = _PyPegen_expect_token(p, 7)) // token='('
1141711417
&&
11418-
(a = expression_rule(p)) // expression
11418+
(a = named_expression_rule(p)) // named_expression
1141911419
&&
1142011420
(_cut_var = 1)
1142111421
&&
@@ -11424,7 +11424,7 @@ genexp_rule(Parser *p)
1142411424
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
1142511425
)
1142611426
{
11427-
D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' expression ~ for_if_clauses ')'"));
11427+
D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
1142811428
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
1142911429
if (_token == NULL) {
1143011430
D(p->level--);
@@ -11444,7 +11444,7 @@ genexp_rule(Parser *p)
1144411444
}
1144511445
p->mark = _mark;
1144611446
D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ',
11447-
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' expression ~ for_if_clauses ')'"));
11447+
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
1144811448
if (_cut_var) {
1144911449
D(p->level--);
1145011450
return NULL;

0 commit comments

Comments
 (0)