Skip to content

Commit ddbce13

Browse files
bpo-32023: Disallow genexprs without parenthesis in class definitions. (#4400)
1 parent edad8ee commit ddbce13

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

Doc/whatsnew/3.7.rst

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

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

641+
class C(1 for x in [1]):
642+
pass
643+
641644
Python 3.7 now correctly raises a :exc:`SyntaxError`, as a generator
642645
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`.)
646+
and cannot have a comma on either side, and the duplication of the
647+
parentheses can be omitted only on calls.
648+
(Contributed by Serhiy Storchaka in :issue:`32012` and :issue:`32023`.)
645649

646650

647651
Changes in the Python API

Lib/test/test_syntax.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@
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+
>>> class C(x for x in L):
157+
... pass
158+
Traceback (most recent call last):
159+
SyntaxError: invalid syntax
156160
157161
>>> def g(*args, **kwargs):
158162
... print(args, sorted(kwargs.items()))
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SyntaxError is now correctly raised when a generator expression without
2+
parenthesis is used instead of an inheritance list in a class definition.
3+
The duplication of the parentheses can be omitted only on calls.

Python/ast.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "pythonrun.h"
1212

1313
#include <assert.h>
14+
#include <stdbool.h>
1415

1516
static int validate_stmts(asdl_seq *);
1617
static int validate_exprs(asdl_seq *, expr_context_ty, int);
@@ -611,7 +612,7 @@ static stmt_ty ast_for_with_stmt(struct compiling *, const node *, int);
611612
static stmt_ty ast_for_for_stmt(struct compiling *, const node *, int);
612613

613614
/* Note different signature for ast_for_call */
614-
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
615+
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty, bool);
615616

616617
static PyObject *parsenumber(struct compiling *, const char *);
617618
static expr_ty parsestrplus(struct compiling *, const node *n);
@@ -1545,7 +1546,7 @@ ast_for_decorator(struct compiling *c, const node *n)
15451546
name_expr = NULL;
15461547
}
15471548
else {
1548-
d = ast_for_call(c, CHILD(n, 3), name_expr);
1549+
d = ast_for_call(c, CHILD(n, 3), name_expr, true);
15491550
if (!d)
15501551
return NULL;
15511552
name_expr = NULL;
@@ -2368,7 +2369,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
23682369
return Call(left_expr, NULL, NULL, LINENO(n),
23692370
n->n_col_offset, c->c_arena);
23702371
else
2371-
return ast_for_call(c, CHILD(n, 1), left_expr);
2372+
return ast_for_call(c, CHILD(n, 1), left_expr, true);
23722373
}
23732374
else if (TYPE(CHILD(n, 0)) == DOT) {
23742375
PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));
@@ -2705,7 +2706,7 @@ ast_for_expr(struct compiling *c, const node *n)
27052706
}
27062707

27072708
static expr_ty
2708-
ast_for_call(struct compiling *c, const node *n, expr_ty func)
2709+
ast_for_call(struct compiling *c, const node *n, expr_ty func, bool allowgen)
27092710
{
27102711
/*
27112712
arglist: argument (',' argument)* [',']
@@ -2728,6 +2729,10 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
27282729
nargs++;
27292730
else if (TYPE(CHILD(ch, 1)) == comp_for) {
27302731
nargs++;
2732+
if (!allowgen) {
2733+
ast_error(c, ch, "invalid syntax");
2734+
return NULL;
2735+
}
27312736
if (NCH(n) > 1) {
27322737
ast_error(c, ch, "Generator expression must be parenthesized");
27332738
return NULL;
@@ -3973,7 +3978,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
39733978
if (!dummy_name)
39743979
return NULL;
39753980
dummy = Name(dummy_name, Load, LINENO(n), n->n_col_offset, c->c_arena);
3976-
call = ast_for_call(c, CHILD(n, 3), dummy);
3981+
call = ast_for_call(c, CHILD(n, 3), dummy, false);
39773982
if (!call)
39783983
return NULL;
39793984
}

0 commit comments

Comments
 (0)