]> granicus.if.org Git - python/commitdiff
bpo-32012: Disallow trailing comma after genexpr without parenthesis. (#4382)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 15 Nov 2017 06:49:40 +0000 (08:49 +0200)
committerGitHub <noreply@github.com>
Wed, 15 Nov 2017 06:49:40 +0000 (08:49 +0200)
Doc/whatsnew/3.7.rst
Lib/test/test_syntax.py
Misc/NEWS.d/next/Core and Builtins/2017-11-13-00-37-11.bpo-32012.Kprjqe.rst [new file with mode: 0644]
Python/ast.c

index f6d051de2eb25ec73c0f1f0725e3c653d0d3880e..82b4840355512598caa7aaeb93a4c85b7eaf909d 100644 (file)
@@ -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
 -------------------------
 
index 5d36581859b775066273e37192308853d0a3e677..c8cb7055c06b9082e9b1f1f394f139df7912c126 100644 (file)
@@ -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]
 
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-13-00-37-11.bpo-32012.Kprjqe.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-13-00-37-11.bpo-32012.Kprjqe.rst
new file mode 100644 (file)
index 0000000..776a261
--- /dev/null
@@ -0,0 +1,4 @@
+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.
index 79cef708a00f99a7dfc294934bff82389ead2dca..c88e7e337332a46e159c56c7a82cc02a7223dfeb 100644 (file)
@@ -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);