Skip to content

Commit 9165f77

Browse files
bpo-32012: Disallow trailing comma after genexpr without parenthesis. (#4382)
1 parent 3bda022 commit 9165f77

File tree

4 files changed

+45
-13
lines changed

4 files changed

+45
-13
lines changed

Doc/whatsnew/3.7.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,20 @@ This section lists previously described changes and other bugfixes
630630
that may require changes to your code.
631631

632632

633+
Changes in Python behavior
634+
--------------------------
635+
636+
* Due to an oversight, earlier Python versions erroneously accepted the
637+
following syntax::
638+
639+
f(1 for x in [1],)
640+
641+
Python 3.7 now correctly raises a :exc:`SyntaxError`, as a generator
642+
expression always needs to be directly inside a set of parentheses
643+
and cannot have a comma on either side.
644+
(Contributed by Serhiy Storchaka in :issue:`32012`.)
645+
646+
633647
Changes in the Python API
634648
-------------------------
635649

Lib/test/test_syntax.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,32 @@
125125
126126
From ast_for_call():
127127
128-
>>> def f(it, *varargs):
128+
>>> def f(it, *varargs, **kwargs):
129129
... return list(it)
130130
>>> L = range(10)
131131
>>> f(x for x in L)
132132
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
133133
>>> f(x for x in L, 1)
134134
Traceback (most recent call last):
135-
SyntaxError: Generator expression must be parenthesized if not sole argument
135+
SyntaxError: Generator expression must be parenthesized
136+
>>> f(x for x in L, y=1)
137+
Traceback (most recent call last):
138+
SyntaxError: Generator expression must be parenthesized
139+
>>> f(x for x in L, *[])
140+
Traceback (most recent call last):
141+
SyntaxError: Generator expression must be parenthesized
142+
>>> f(x for x in L, **{})
143+
Traceback (most recent call last):
144+
SyntaxError: Generator expression must be parenthesized
145+
>>> f(L, x for x in L)
146+
Traceback (most recent call last):
147+
SyntaxError: Generator expression must be parenthesized
136148
>>> f(x for x in L, y for y in L)
137149
Traceback (most recent call last):
138-
SyntaxError: Generator expression must be parenthesized if not sole argument
150+
SyntaxError: Generator expression must be parenthesized
151+
>>> f(x for x in L,)
152+
Traceback (most recent call last):
153+
SyntaxError: Generator expression must be parenthesized
139154
>>> f((x for x in L), 1)
140155
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
141156
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SyntaxError is now correctly raised when a generator expression without
2+
parenthesis is passed as an argument, but followed by a trailing comma.
3+
A generator expression always needs to be directly inside a set of parentheses
4+
and cannot have a comma on either side.

Python/ast.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,7 +2712,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
27122712
argument: ( test [comp_for] | '*' test | test '=' test | '**' test )
27132713
*/
27142714

2715-
int i, nargs, nkeywords, ngens;
2715+
int i, nargs, nkeywords;
27162716
int ndoublestars;
27172717
asdl_seq *args;
27182718
asdl_seq *keywords;
@@ -2721,28 +2721,27 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
27212721

27222722
nargs = 0;
27232723
nkeywords = 0;
2724-
ngens = 0;
27252724
for (i = 0; i < NCH(n); i++) {
27262725
node *ch = CHILD(n, i);
27272726
if (TYPE(ch) == argument) {
27282727
if (NCH(ch) == 1)
27292728
nargs++;
2730-
else if (TYPE(CHILD(ch, 1)) == comp_for)
2731-
ngens++;
2729+
else if (TYPE(CHILD(ch, 1)) == comp_for) {
2730+
nargs++;
2731+
if (NCH(n) > 1) {
2732+
ast_error(c, ch, "Generator expression must be parenthesized");
2733+
return NULL;
2734+
}
2735+
}
27322736
else if (TYPE(CHILD(ch, 0)) == STAR)
27332737
nargs++;
27342738
else
27352739
/* TYPE(CHILD(ch, 0)) == DOUBLESTAR or keyword argument */
27362740
nkeywords++;
27372741
}
27382742
}
2739-
if (ngens > 1 || (ngens && (nargs || nkeywords))) {
2740-
ast_error(c, n, "Generator expression must be parenthesized "
2741-
"if not sole argument");
2742-
return NULL;
2743-
}
27442743

2745-
args = _Py_asdl_seq_new(nargs + ngens, c->c_arena);
2744+
args = _Py_asdl_seq_new(nargs, c->c_arena);
27462745
if (!args)
27472746
return NULL;
27482747
keywords = _Py_asdl_seq_new(nkeywords, c->c_arena);

0 commit comments

Comments
 (0)