Commit 9165f77d authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-32012: Disallow trailing comma after genexpr without parenthesis. (#4382)

parent 3bda0222
......@@ -630,6 +630,20 @@ This section lists previously described changes and other bugfixes
that may require changes to your code.
Changes in Python behavior
--------------------------
* Due to an oversight, earlier Python versions erroneously accepted the
following syntax::
f(1 for x in [1],)
Python 3.7 now correctly raises a :exc:`SyntaxError`, as a generator
expression always needs to be directly inside a set of parentheses
and cannot have a comma on either side.
(Contributed by Serhiy Storchaka in :issue:`32012`.)
Changes in the Python API
-------------------------
......
......@@ -125,17 +125,32 @@ SyntaxError: invalid syntax
From ast_for_call():
>>> def f(it, *varargs):
>>> def f(it, *varargs, **kwargs):
... return list(it)
>>> L = range(10)
>>> f(x for x in L)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> f(x for x in L, 1)
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized if not sole argument
SyntaxError: Generator expression must be parenthesized
>>> f(x for x in L, y=1)
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized
>>> f(x for x in L, *[])
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized
>>> f(x for x in L, **{})
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized
>>> f(L, x for x in L)
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized
>>> f(x for x in L, y for y in L)
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized if not sole argument
SyntaxError: Generator expression must be parenthesized
>>> f(x for x in L,)
Traceback (most recent call last):
SyntaxError: Generator expression must be parenthesized
>>> f((x for x in L), 1)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
......
SyntaxError is now correctly raised when a generator expression without
parenthesis is passed as an argument, but followed by a trailing comma.
A generator expression always needs to be directly inside a set of parentheses
and cannot have a comma on either side.
......@@ -2712,7 +2712,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
argument: ( test [comp_for] | '*' test | test '=' test | '**' test )
*/
int i, nargs, nkeywords, ngens;
int i, nargs, nkeywords;
int ndoublestars;
asdl_seq *args;
asdl_seq *keywords;
......@@ -2721,14 +2721,18 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
nargs = 0;
nkeywords = 0;
ngens = 0;
for (i = 0; i < NCH(n); i++) {
node *ch = CHILD(n, i);
if (TYPE(ch) == argument) {
if (NCH(ch) == 1)
nargs++;
else if (TYPE(CHILD(ch, 1)) == comp_for)
ngens++;
else if (TYPE(CHILD(ch, 1)) == comp_for) {
nargs++;
if (NCH(n) > 1) {
ast_error(c, ch, "Generator expression must be parenthesized");
return NULL;
}
}
else if (TYPE(CHILD(ch, 0)) == STAR)
nargs++;
else
......@@ -2736,13 +2740,8 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
nkeywords++;
}
}
if (ngens > 1 || (ngens && (nargs || nkeywords))) {
ast_error(c, n, "Generator expression must be parenthesized "
"if not sole argument");
return NULL;
}
args = _Py_asdl_seq_new(nargs + ngens, c->c_arena);
args = _Py_asdl_seq_new(nargs, c->c_arena);
if (!args)
return NULL;
keywords = _Py_asdl_seq_new(nkeywords, c->c_arena);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment