mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
[3.14] gh-135443: Sometimes Fall Back to __main__.__dict__ For Globals (gh-135593)
For several builtin functions, we now fall back to __main__.__dict__ for the globals
when there is no current frame and _PyInterpreterState_IsRunningMain() returns
true. This allows those functions to be run with Interpreter.call().
The affected builtins:
* exec()
* eval()
* globals()
* locals()
* vars()
* dir()
We take a similar approach with "stateless" functions, which don't use any
global variables.
(cherry picked from commit a450a0ddec, AKA gh-135491)
Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
This commit is contained in:
parent
7aeddeaf93
commit
2b1c0a76dc
7 changed files with 394 additions and 68 deletions
|
|
@ -958,6 +958,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
|
|||
PyObject *locals)
|
||||
/*[clinic end generated code: output=0a0824aa70093116 input=7c7bce5299a89062]*/
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject *result = NULL, *source_copy;
|
||||
const char *str;
|
||||
|
||||
|
|
@ -971,35 +972,46 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
|
|||
: "globals must be a dict");
|
||||
return NULL;
|
||||
}
|
||||
if (globals == Py_None) {
|
||||
globals = PyEval_GetGlobals();
|
||||
if (locals == Py_None) {
|
||||
locals = _PyEval_GetFrameLocals();
|
||||
if (locals == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
Py_INCREF(locals);
|
||||
}
|
||||
|
||||
int fromframe = 0;
|
||||
if (globals != Py_None) {
|
||||
Py_INCREF(globals);
|
||||
}
|
||||
else if (_PyEval_GetFrame() != NULL) {
|
||||
fromframe = 1;
|
||||
globals = PyEval_GetGlobals();
|
||||
assert(globals != NULL);
|
||||
Py_INCREF(globals);
|
||||
}
|
||||
else if (locals == Py_None)
|
||||
locals = Py_NewRef(globals);
|
||||
else {
|
||||
globals = _PyEval_GetGlobalsFromRunningMain(tstate);
|
||||
if (globals == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"eval must be given globals and locals "
|
||||
"when called without a frame");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(globals);
|
||||
}
|
||||
|
||||
if (locals != Py_None) {
|
||||
Py_INCREF(locals);
|
||||
}
|
||||
|
||||
if (globals == NULL || locals == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"eval must be given globals and locals "
|
||||
"when called without a frame");
|
||||
goto error;
|
||||
else if (fromframe) {
|
||||
locals = _PyEval_GetFrameLocals();
|
||||
if (locals == NULL) {
|
||||
assert(PyErr_Occurred());
|
||||
Py_DECREF(globals);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
locals = Py_NewRef(globals);
|
||||
}
|
||||
|
||||
int r = PyDict_Contains(globals, &_Py_ID(__builtins__));
|
||||
if (r == 0) {
|
||||
r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());
|
||||
}
|
||||
if (r < 0) {
|
||||
if (_PyEval_EnsureBuiltins(tstate, globals, NULL) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -1040,6 +1052,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
|
|||
}
|
||||
|
||||
error:
|
||||
Py_XDECREF(globals);
|
||||
Py_XDECREF(locals);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1070,29 +1083,44 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
|
|||
PyObject *locals, PyObject *closure)
|
||||
/*[clinic end generated code: output=7579eb4e7646743d input=25e989b6d87a3a21]*/
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject *v;
|
||||
|
||||
if (globals == Py_None) {
|
||||
int fromframe = 0;
|
||||
if (globals != Py_None) {
|
||||
Py_INCREF(globals);
|
||||
}
|
||||
else if (_PyEval_GetFrame() != NULL) {
|
||||
fromframe = 1;
|
||||
globals = PyEval_GetGlobals();
|
||||
if (locals == Py_None) {
|
||||
locals = _PyEval_GetFrameLocals();
|
||||
if (locals == NULL)
|
||||
return NULL;
|
||||
assert(globals != NULL);
|
||||
Py_INCREF(globals);
|
||||
}
|
||||
else {
|
||||
globals = _PyEval_GetGlobalsFromRunningMain(tstate);
|
||||
if (globals == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"globals and locals cannot be NULL");
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
else {
|
||||
Py_INCREF(locals);
|
||||
}
|
||||
if (!globals || !locals) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"globals and locals cannot be NULL");
|
||||
Py_INCREF(globals);
|
||||
}
|
||||
|
||||
if (locals != Py_None) {
|
||||
Py_INCREF(locals);
|
||||
}
|
||||
else if (fromframe) {
|
||||
locals = _PyEval_GetFrameLocals();
|
||||
if (locals == NULL) {
|
||||
assert(PyErr_Occurred());
|
||||
Py_DECREF(globals);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (locals == Py_None) {
|
||||
locals = Py_NewRef(globals);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(locals);
|
||||
locals = Py_NewRef(globals);
|
||||
}
|
||||
|
||||
if (!PyDict_Check(globals)) {
|
||||
|
|
@ -1106,11 +1134,8 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
|
|||
Py_TYPE(locals)->tp_name);
|
||||
goto error;
|
||||
}
|
||||
int r = PyDict_Contains(globals, &_Py_ID(__builtins__));
|
||||
if (r == 0) {
|
||||
r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());
|
||||
}
|
||||
if (r < 0) {
|
||||
|
||||
if (_PyEval_EnsureBuiltins(tstate, globals, NULL) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -1187,11 +1212,13 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
|
|||
}
|
||||
if (v == NULL)
|
||||
goto error;
|
||||
Py_DECREF(globals);
|
||||
Py_DECREF(locals);
|
||||
Py_DECREF(v);
|
||||
Py_RETURN_NONE;
|
||||
|
||||
error:
|
||||
Py_XDECREF(globals);
|
||||
Py_XDECREF(locals);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1241,10 +1268,21 @@ static PyObject *
|
|||
builtin_globals_impl(PyObject *module)
|
||||
/*[clinic end generated code: output=e5dd1527067b94d2 input=9327576f92bb48ba]*/
|
||||
{
|
||||
PyObject *d;
|
||||
|
||||
d = PyEval_GetGlobals();
|
||||
return Py_XNewRef(d);
|
||||
PyObject *globals;
|
||||
if (_PyEval_GetFrame() != NULL) {
|
||||
globals = PyEval_GetGlobals();
|
||||
assert(globals != NULL);
|
||||
return Py_NewRef(globals);
|
||||
}
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
globals = _PyEval_GetGlobalsFromRunningMain(tstate);
|
||||
if (globals == NULL) {
|
||||
if (_PyErr_Occurred(tstate)) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return Py_NewRef(globals);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1888,7 +1926,21 @@ static PyObject *
|
|||
builtin_locals_impl(PyObject *module)
|
||||
/*[clinic end generated code: output=b46c94015ce11448 input=7874018d478d5c4b]*/
|
||||
{
|
||||
return _PyEval_GetFrameLocals();
|
||||
PyObject *locals;
|
||||
if (_PyEval_GetFrame() != NULL) {
|
||||
locals = _PyEval_GetFrameLocals();
|
||||
assert(locals != NULL || PyErr_Occurred());
|
||||
return locals;
|
||||
}
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
locals = _PyEval_GetGlobalsFromRunningMain(tstate);
|
||||
if (locals == NULL) {
|
||||
if (_PyErr_Occurred(tstate)) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return Py_NewRef(locals);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2624,7 +2676,22 @@ builtin_vars(PyObject *self, PyObject *args)
|
|||
if (!PyArg_UnpackTuple(args, "vars", 0, 1, &v))
|
||||
return NULL;
|
||||
if (v == NULL) {
|
||||
d = _PyEval_GetFrameLocals();
|
||||
if (_PyEval_GetFrame() != NULL) {
|
||||
d = _PyEval_GetFrameLocals();
|
||||
}
|
||||
else {
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
d = _PyEval_GetGlobalsFromRunningMain(tstate);
|
||||
if (d == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
d = _PyEval_GetFrameLocals();
|
||||
assert(_PyErr_Occurred(tstate));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_INCREF(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (PyObject_GetOptionalAttr(v, &_Py_ID(__dict__), &d) == 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue