summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_ast.py8
-rw-r--r--Misc/NEWS2
-rw-r--r--Parser/Python.asdl2
-rw-r--r--Python/Python-ast.c8
-rw-r--r--Python/ast.c3
-rw-r--r--Python/compile.c25
-rw-r--r--Python/symtable.c12
7 files changed, 36 insertions, 24 deletions
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index a8853c7..dc24126 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -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):
diff --git a/Misc/NEWS b/Misc/NEWS
index f17cfea..b2e41dd 100644
--- 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).
diff --git a/Parser/Python.asdl b/Parser/Python.asdl
index 6b06dec..c24d840 100644
--- a/Parser/Python.asdl
+++ b/Parser/Python.asdl
@@ -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)
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index 805f2b8..e6f1e58 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -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;
diff --git a/Python/ast.c b/Python/ast.c
index 0c0c1a6..7657b22 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -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");
diff --git a/Python/compile.c b/Python/compile.c
index 5016f99..3cf71ef 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -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:
diff --git a/Python/symtable.c b/Python/symtable.c
index 9dde908..55898f9 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -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);