Skip to content

Commit 06b0abd

Browse files
Disallow other improper syntax with generator expressions.
1 parent 3d8c9bc commit 06b0abd

4 files changed

Lines changed: 36 additions & 10 deletions

File tree

Doc/whatsnew/3.7.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,18 @@ Changes in Python behavior
638638

639639
f(1 for x in [1],)
640640

641+
@deco(1 for x in [1])
642+
def f():
643+
pass
644+
645+
class C(1 for x in [1]):
646+
pass
647+
641648
Python 3.7 now correctly raises a :exc:`SyntaxError`, as a generator
642649
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:`XXXXX`.)
650+
and cannot have a comma on either side, and the duplication of the
651+
parentheses can be omitted only on calls.
652+
(Contributed by Serhiy Storchaka in :issue:`32012`.)
645653

646654

647655
Changes in the Python API

Lib/test/test_syntax.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,17 @@
153153
SyntaxError: Generator expression must be parenthesized
154154
>>> f((x for x in L), 1)
155155
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
156+
>>> def deco(*args):
157+
... return lambda f: f
158+
>>> @deco(x for x in L)
159+
... def g(*args, **kwargs):
160+
... pass
161+
Traceback (most recent call last):
162+
SyntaxError: invalid syntax
163+
>>> class C(x for x in L):
164+
... pass
165+
Traceback (most recent call last):
166+
SyntaxError: invalid syntax
156167
157168
>>> def g(*args, **kwargs):
158169
... print(args, sorted(kwargs.items()))
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
SyntaxError is now raised when a generator expression without parenthesis is
2-
passed as an argument but followed by a trailing comma. A generator expression
1+
SyntaxError is now correctly raised when a generator expression without
2+
parenthesis is passed as an argument, but followed by a trailing comma, or
3+
it is used instead of an argument list in a decorator expression, or
4+
instead of an inheritance list in a class definition. A generator expression
35
always needs to be directly inside a set of parentheses and cannot have a
4-
comma on either side.
6+
comma on either side. The duplication of the parentheses can be omitted
7+
only on calls.

Python/ast.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ static stmt_ty ast_for_with_stmt(struct compiling *, const node *, int);
611611
static stmt_ty ast_for_for_stmt(struct compiling *, const node *, int);
612612

613613
/* Note different signature for ast_for_call */
614-
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
614+
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty, int);
615615

616616
static PyObject *parsenumber(struct compiling *, const char *);
617617
static expr_ty parsestrplus(struct compiling *, const node *n);
@@ -1545,7 +1545,7 @@ ast_for_decorator(struct compiling *c, const node *n)
15451545
name_expr = NULL;
15461546
}
15471547
else {
1548-
d = ast_for_call(c, CHILD(n, 3), name_expr);
1548+
d = ast_for_call(c, CHILD(n, 3), name_expr, 0);
15491549
if (!d)
15501550
return NULL;
15511551
name_expr = NULL;
@@ -2368,7 +2368,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
23682368
return Call(left_expr, NULL, NULL, LINENO(n),
23692369
n->n_col_offset, c->c_arena);
23702370
else
2371-
return ast_for_call(c, CHILD(n, 1), left_expr);
2371+
return ast_for_call(c, CHILD(n, 1), left_expr, 1);
23722372
}
23732373
else if (TYPE(CHILD(n, 0)) == DOT) {
23742374
PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));
@@ -2705,7 +2705,7 @@ ast_for_expr(struct compiling *c, const node *n)
27052705
}
27062706

27072707
static expr_ty
2708-
ast_for_call(struct compiling *c, const node *n, expr_ty func)
2708+
ast_for_call(struct compiling *c, const node *n, expr_ty func, int allowgen)
27092709
{
27102710
/*
27112711
arglist: argument (',' argument)* [',']
@@ -2728,6 +2728,10 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
27282728
nargs++;
27292729
else if (TYPE(CHILD(ch, 1)) == comp_for) {
27302730
nargs++;
2731+
if (!allowgen) {
2732+
ast_error(c, ch, "invalid syntax");
2733+
return NULL;
2734+
}
27312735
if (NCH(n) > 1) {
27322736
ast_error(c, ch, "Generator expression must be parenthesized");
27332737
return NULL;
@@ -3973,7 +3977,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
39733977
if (!dummy_name)
39743978
return NULL;
39753979
dummy = Name(dummy_name, Load, LINENO(n), n->n_col_offset, c->c_arena);
3976-
call = ast_for_call(c, CHILD(n, 3), dummy);
3980+
call = ast_for_call(c, CHILD(n, 3), dummy, 0);
39773981
if (!call)
39783982
return NULL;
39793983
}

0 commit comments

Comments
 (0)