]> granicus.if.org Git - python/commitdiff
Issue #16546: make ast.YieldFrom argument mandatory.
authorMark Dickinson <mdickinson@enthought.com>
Sun, 25 Nov 2012 14:36:26 +0000 (14:36 +0000)
committerMark Dickinson <mdickinson@enthought.com>
Sun, 25 Nov 2012 14:36:26 +0000 (14:36 +0000)
Lib/test/test_ast.py
Misc/NEWS
Parser/Python.asdl
Python/Python-ast.c
Python/ast.c
Python/compile.c
Python/symtable.c

index a8853c7e21f4dba8ffcccce412721887ad22f299..dc24126b2194a0c63439703c865018cfe4208618 100644 (file)
@@ -399,6 +399,14 @@ class AST_Tests(unittest.TestCase):
             compile(m, "<test>", "exec")
         self.assertIn("string must be of type str", str(cm.exception))
 
+    def test_empty_yield_from(self):
+        # Issue 16546: yield from value is not optional.
+        empty_yield_from = ast.parse("def f():\n yield from g()")
+        empty_yield_from.body[0].body[0].value.value = None
+        with self.assertRaises(ValueError) as cm:
+            compile(empty_yield_from, "<test>", "exec")
+        self.assertIn("field value is required", str(cm.exception))
+
 
 class ASTHelpers_Test(unittest.TestCase):
 
index f17cfea4d35c7af2d23e2e08897c9ba008e385ec..b2e41dda9213944d4020c912fe4980cc0b873f94 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 3.3.1?
 Core and Builtins
 -----------------
 
+- Issue #16546: Fix: ast.YieldFrom argument is now mandatory.
+
 - Issue #16514: Fix regression causing a traceback when sys.path[0] is None
   (actually, any non-string or non-bytes type).
 
index 6b06dec3759dfeb365f48552cc90c92e14e1990a..c24d8406192aef341c2f50691b01375008a32f67 100644 (file)
@@ -60,7 +60,7 @@ module Python
          | GeneratorExp(expr elt, comprehension* generators)
          -- the grammar constrains where yield expressions can occur
          | Yield(expr? value)
-             | YieldFrom(expr? value)
+         | YieldFrom(expr value)
          -- need sequences for compare to distinguish between
          -- x < 4 < 3 and (x < 4) < 3
          | Compare(expr left, cmpop* ops, expr* comparators)
index 805f2b8af118d93f44e1f1cabd3bdec0960a1413..e6f1e58252e4511f91d01edada85cd6b66fbacd8 100644 (file)
@@ -1802,6 +1802,11 @@ expr_ty
 YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena)
 {
         expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for YieldFrom");
+                return NULL;
+        }
         p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
         if (!p)
                 return NULL;
@@ -5431,7 +5436,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
                         Py_XDECREF(tmp);
                         tmp = NULL;
                 } else {
-                        value = NULL;
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from YieldFrom");
+                        return 1;
                 }
                 *out = YieldFrom(value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
index 0c0c1a68d9672050901257dabc61f5f601eefaad..7657b22459f44df23774b6a76560ddc93e5552a5 100644 (file)
@@ -224,8 +224,7 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
     case Yield_kind:
         return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);
     case YieldFrom_kind:
-        return !exp->v.YieldFrom.value ||
-            validate_expr(exp->v.YieldFrom.value, Load);
+        return validate_expr(exp->v.YieldFrom.value, Load);
     case Compare_kind:
         if (!asdl_seq_LEN(exp->v.Compare.comparators)) {
             PyErr_SetString(PyExc_ValueError, "Compare with no comparators");
index 5016f99af3a84b0120ab384e4d6f9b6f72912632..3cf71ef09e2d27b3e93fbd16be1558f406d4aca7 100644 (file)
@@ -3341,27 +3341,24 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
     case DictComp_kind:
         return compiler_dictcomp(c, e);
     case Yield_kind:
-    case YieldFrom_kind: {
-        expr_ty value;
         if (c->u->u_ste->ste_type != FunctionBlock)
             return compiler_error(c, "'yield' outside function");
-        value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value;
-        if (value) {
-            VISIT(c, expr, value);
+        if (e->v.Yield.value) {
+            VISIT(c, expr, e->v.Yield.value);
         }
         else {
             ADDOP_O(c, LOAD_CONST, Py_None, consts);
         }
-        if (e->kind == YieldFrom_kind) {
-            ADDOP(c, GET_ITER);
-            ADDOP_O(c, LOAD_CONST, Py_None, consts);
-            ADDOP(c, YIELD_FROM);
-        }
-        else {
-            ADDOP(c, YIELD_VALUE);
-        }
+        ADDOP(c, YIELD_VALUE);
+        break;
+    case YieldFrom_kind:
+        if (c->u->u_ste->ste_type != FunctionBlock)
+            return compiler_error(c, "'yield' outside function");
+        VISIT(c, expr, e->v.YieldFrom.value);
+        ADDOP(c, GET_ITER);
+        ADDOP_O(c, LOAD_CONST, Py_None, consts);
+        ADDOP(c, YIELD_FROM);
         break;
-    }
     case Compare_kind:
         return compiler_compare(c, e);
     case Call_kind:
index 9dde9088322ab938688fd92a6607f83b6e8b5bc0..55898f99bf14adadba3aa73ee78483ec2ca0f4bb 100644 (file)
@@ -1371,14 +1371,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
             VISIT_QUIT(st, 0);
         break;
     case Yield_kind:
-    case YieldFrom_kind: {
-        expr_ty value;
-        value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value;
-        if (value)
-            VISIT(st, expr, value);
+        if (e->v.Yield.value)
+            VISIT(st, expr, e->v.Yield.value);
+        st->st_cur->ste_generator = 1;
+        break;
+    case YieldFrom_kind:
+        VISIT(st, expr, e->v.YieldFrom.value);
         st->st_cur->ste_generator = 1;
         break;
-    }
     case Compare_kind:
         VISIT(st, expr, e->v.Compare.left);
         VISIT_SEQ(st, expr, e->v.Compare.comparators);