def test_set_bad_filter(self):
self.assertRaises(ValueError, _testcapi.PyImport_SetLazyImportsFilter, 42)
+ def test_dunder_lazy_import_without_frame(self):
+ # gh-151510: __lazy_import__() called with no globals and no running
+ # Python frame must raise TypeError instead of crashing.
+ with self.assertRaisesRegex(
+ TypeError,
+ r"__lazy_import__\(\) missing globals when called without a frame",
+ ):
+ _testcapi.lazy_import_without_frame(
+ "test.test_lazy_import.data.basic2"
+ )
+
if __name__ == '__main__':
unittest.main()
#include "parts.h"
#include "util.h"
+static PyObject *
+pyimport_lazyimportwithoutframe(PyObject *self, PyObject *name)
+{
+ PyObject *lazy_import = PyImport_ImportModuleAttrString("builtins",
+ "__lazy_import__");
+ if (lazy_import == NULL) {
+ return NULL;
+ }
+
+ // Simulate being called with no running Python frame (e.g. from a freshly
+ // attached C thread), so that PyEval_GetGlobals() returns NULL.
+ PyThreadState *tstate = PyThreadState_Get();
+ struct _PyInterpreterFrame *saved = tstate->current_frame;
+ tstate->current_frame = NULL;
+ PyObject *res = PyObject_CallOneArg(lazy_import, name);
+ tstate->current_frame = saved;
+
+ Py_DECREF(lazy_import);
+ return res;
+}
+
// Test PyImport_ImportModuleAttr()
static PyObject *
pyimport_importmoduleattr(PyObject *self, PyObject *args)
{"PyImport_GetLazyImportsMode", pyimport_getlazyimportsmode, METH_NOARGS},
{"PyImport_SetLazyImportsFilter", pyimport_setlazyimportsfilter, METH_VARARGS},
{"PyImport_GetLazyImportsFilter", pyimport_getlazyimportsfilter, METH_NOARGS},
+ {"lazy_import_without_frame", pyimport_lazyimportwithoutframe, METH_O},
{NULL},
};
PyThreadState *tstate = PyThreadState_GET();
if (globals == NULL) {
globals = PyEval_GetGlobals();
+ if (globals == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "__lazy_import__() missing globals "
+ "when called without a frame");
+ return NULL;
+ }
}
if (locals == NULL) {
locals = globals;