diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index fd8c3aafee0..2346048c57d 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -302,6 +302,9 @@ PyAPI_FUNC(PyObject *) _PyEval_LazyImportName(PyThreadState *tstate, PyObject *b PyAPI_FUNC(PyObject *) _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name); PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level); +PyObject * +_PyEval_ImportNameWithImport(PyThreadState *tstate, PyObject *import_func, PyObject *globals, PyObject *locals, + PyObject *name, PyObject *fromlist, PyObject *level); PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys); PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); diff --git a/Include/internal/pycore_lazyimportobject.h b/Include/internal/pycore_lazyimportobject.h index 5a2138d3ac7..8825f6327f4 100644 --- a/Include/internal/pycore_lazyimportobject.h +++ b/Include/internal/pycore_lazyimportobject.h @@ -14,14 +14,14 @@ PyAPI_DATA(PyTypeObject) PyLazyImport_Type; typedef struct { PyObject_HEAD - PyObject *lz_builtins; + PyObject *lz_import_func; PyObject *lz_from; PyObject *lz_attr; } PyLazyImportObject; PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import); -PyAPI_FUNC(PyObject *) _PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr); +PyAPI_FUNC(PyObject *) _PyLazyImport_New(PyObject *import_func, PyObject *from, PyObject *attr); #ifdef __cplusplus } diff --git a/Objects/lazyimportobject.c b/Objects/lazyimportobject.c index 6754b238f52..cca09dcb49e 100644 --- a/Objects/lazyimportobject.c +++ b/Objects/lazyimportobject.c @@ -4,7 +4,7 @@ #include "pycore_lazyimportobject.h" PyObject * -_PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr) +_PyLazyImport_New(PyObject *import_func, PyObject *from, PyObject *attr) { PyLazyImportObject *m; if (!from || !PyUnicode_Check(from)) { @@ -19,8 +19,8 @@ _PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr) if (m == NULL) { return NULL; } - Py_XINCREF(builtins); - m->lz_builtins = builtins; + Py_XINCREF(import_func); + m->lz_import_func = import_func; Py_INCREF(from); m->lz_from = from; Py_XINCREF(attr); @@ -33,7 +33,7 @@ static void lazy_import_dealloc(PyLazyImportObject *m) { PyObject_GC_UnTrack(m); - Py_XDECREF(m->lz_builtins); + Py_XDECREF(m->lz_import_func); Py_XDECREF(m->lz_from); Py_XDECREF(m->lz_attr); Py_TYPE(m)->tp_free((PyObject *)m); @@ -68,7 +68,7 @@ lazy_import_repr(PyLazyImportObject *m) static int lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg) { - Py_VISIT(m->lz_builtins); + Py_VISIT(m->lz_import_func); Py_VISIT(m->lz_from); Py_VISIT(m->lz_attr); return 0; @@ -77,7 +77,7 @@ lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg) static int lazy_import_clear(PyLazyImportObject *m) { - Py_CLEAR(m->lz_builtins); + Py_CLEAR(m->lz_import_func); Py_CLEAR(m->lz_from); Py_CLEAR(m->lz_attr); return 0; diff --git a/Python/ceval.c b/Python/ceval.c index 28a814ebace..0a2aa88acde 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2999,13 +2999,21 @@ _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, return NULL; } + PyObject *res = _PyEval_ImportNameWithImport(tstate, import_func, globals, locals, name, fromlist, level); + Py_DECREF(import_func); + return res; +} + +PyObject * +_PyEval_ImportNameWithImport(PyThreadState *tstate, PyObject *import_func, PyObject *globals, PyObject *locals, + PyObject *name, PyObject *fromlist, PyObject *level) +{ if (locals == NULL) { locals = Py_None; } /* Fast path for not overloaded __import__. */ if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) { - Py_DECREF(import_func); int ilevel = PyLong_AsInt(level); if (ilevel == -1 && _PyErr_Occurred(tstate)) { return NULL; @@ -3020,7 +3028,6 @@ _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject* args[5] = {name, globals, locals, fromlist, level}; PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); - Py_DECREF(import_func); return res; } @@ -3029,6 +3036,7 @@ PyObject * _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level, int lazy) { + PyObject *res = NULL; // Check if global policy overrides the local syntax switch (PyImport_LazyImportsEnabled()) { case PyLazyImportsMode_ForcedOff: @@ -3047,34 +3055,42 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *glob } PyObject *import_func; - if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), &import_func) < 0) { - return NULL; + if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) { + goto error; + } else if (import_func == NULL) { + _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); + goto error; } - if (import_func == NULL) { + + PyObject *lazy_import_func; + if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), &lazy_import_func) < 0) { + goto error; + } else if (lazy_import_func == NULL) { _PyErr_SetString(tstate, PyExc_ImportError, "__lazy_import__ not found"); - return NULL; + goto error; } if (locals == NULL) { locals = Py_None; } - if (_PyImport_IsDefaultLazyImportFunc(tstate->interp, import_func)) { - Py_DECREF(import_func); - + if (_PyImport_IsDefaultLazyImportFunc(tstate->interp, lazy_import_func)) { int ilevel = PyLong_AsInt(level); if (ilevel == -1 && PyErr_Occurred()) { - return NULL; + goto error; } - return _PyImport_LazyImportModuleLevelObject( - tstate, name, builtins, globals, locals, fromlist, ilevel + res = _PyImport_LazyImportModuleLevelObject( + tstate, name, import_func, globals, locals, fromlist, ilevel ); + goto error; } - PyObject* args[5] = {name, globals, locals, fromlist, level}; - PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); - Py_DECREF(import_func); + PyObject* args[6] = {name, globals, locals, fromlist, level, import_func}; + res = PyObject_Vectorcall(lazy_import_func, args, 6, NULL); +error: + Py_XDECREF(lazy_import_func); + Py_XDECREF(import_func); return res; } @@ -3256,7 +3272,7 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) if (d->lz_attr != NULL) { if (PyUnicode_Check(d->lz_attr)) { PyObject *from = PyUnicode_FromFormat("%U.%U", d->lz_from, d->lz_attr); - ret = _PyLazyImport_New(d->lz_builtins, from, name); + ret = _PyLazyImport_New(d->lz_import_func, from, name); Py_DECREF(from); return ret; } @@ -3264,12 +3280,12 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) Py_ssize_t dot = PyUnicode_FindChar(d->lz_from, '.', 0, PyUnicode_GET_LENGTH(d->lz_from), 1); if (dot >= 0) { PyObject *from = PyUnicode_Substring(d->lz_from, 0, dot); - ret = _PyLazyImport_New(d->lz_builtins, from, name); + ret = _PyLazyImport_New(d->lz_import_func, from, name); Py_DECREF(from); return ret; } } - ret = _PyLazyImport_New(d->lz_builtins, d->lz_from, name); + ret = _PyLazyImport_New(d->lz_import_func, d->lz_from, name); return ret; } diff --git a/Python/import.c b/Python/import.c index ac03db2c821..523e7bc80c8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3737,8 +3737,8 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import) PyObject *globals = PyEval_GetGlobals(); if (full) { - obj = _PyEval_ImportName(tstate, - lz->lz_builtins, + obj = _PyEval_ImportNameWithImport(tstate, + lz->lz_import_func, globals, globals, lz->lz_from, @@ -3749,8 +3749,8 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import) if (name == NULL) { goto error; } - obj = _PyEval_ImportName(tstate, - lz->lz_builtins, + obj = _PyEval_ImportNameWithImport(tstate, + lz->lz_import_func, globals, globals, name, @@ -3906,8 +3906,20 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyErr_SetString(PyExc_RuntimeError, "no current frame"); goto error; } - final_mod = _PyImport_LazyImportModuleLevelObject(tstate, name, frame->f_builtins, globals, + + PyObject *import_func; + if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) { + return NULL; + } + + if (import_func == NULL) { + _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); + return NULL; + } + + final_mod = _PyImport_LazyImportModuleLevelObject(tstate, name, import_func, globals, locals, fromlist, level); + Py_DECREF(import_func); goto error; } } @@ -4016,7 +4028,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyObject * _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, - PyObject *name, PyObject *builtins, + PyObject *name, PyObject *import_func, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { @@ -4063,7 +4075,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, } } - PyObject *res = _PyLazyImport_New(builtins, abs_name, fromlist); + PyObject *res = _PyLazyImport_New(import_func, abs_name, fromlist); Py_DECREF(abs_name); return res; }