Issue #16546: make ast.YieldFrom argument mandatory.
This commit is contained in:
parent
9982c53c2f
commit
ded35aeb9d
|
@ -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):
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue