Core and Builtins
-----------------
+- Issue #21591: Correctly handle qualified exec statements in tuple form by
+ moving compatibility layer from run-time to AST transformation.
+
Library
-------
expr1 = ast_for_expr(c, CHILD(n, 1));
if (!expr1)
return NULL;
+
+ if (expr1->kind == Tuple_kind && n_children < 4 &&
+ (asdl_seq_LEN(expr1->v.Tuple.elts) == 2 ||
+ asdl_seq_LEN(expr1->v.Tuple.elts) == 3)) {
+ /* Backwards compatibility: pass exec args as a tuple */
+ globals = (expr_ty) asdl_seq_GET(expr1->v.Tuple.elts, 1);
+ if (asdl_seq_LEN(expr1->v.Tuple.elts) == 3) {
+ locals = (expr_ty) asdl_seq_GET(expr1->v.Tuple.elts, 2);
+ }
+ expr1 = (expr_ty) asdl_seq_GET(expr1->v.Tuple.elts, 0);
+ }
+
if (n_children >= 4) {
globals = ast_for_expr(c, CHILD(n, 3));
if (!globals)
exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
PyObject *locals)
{
- int n;
PyObject *v;
int plain = 0;
- if (PyTuple_Check(prog) && globals == Py_None && locals == Py_None &&
- ((n = PyTuple_Size(prog)) == 2 || n == 3)) {
- /* Backward compatibility hack */
- globals = PyTuple_GetItem(prog, 1);
- if (n == 3)
- locals = PyTuple_GetItem(prog, 2);
- prog = PyTuple_GetItem(prog, 0);
- }
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {