Issue #21591: Handle exec backwards compatibility in the AST builder.
Instead of deferring until runtime. This makes sure we hit the right
conditions in dealing with unqualified exec statements.
Reviewed by Victor Stinner. Test follows in a later commit.
diff --git a/Misc/NEWS b/Misc/NEWS
index bdd414e..f6dda99 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
Core and Builtins
-----------------
+- Issue #21591: Correctly handle qualified exec statements in tuple form by
+ moving compatibility layer from run-time to AST transformation.
+
Library
-------
diff --git a/Python/ast.c b/Python/ast.c
index 80e6354..ffd5679 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -2679,6 +2679,18 @@
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)
diff --git a/Python/ceval.c b/Python/ceval.c
index e008608..38f51fa 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -4673,18 +4673,9 @@
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) {