Flow import func through to lazy imports object and __lazy_import__

This commit is contained in:
Dino Viehland 2025-09-22 07:42:54 -07:00
parent 41ab092407
commit 058bc6e884
5 changed files with 64 additions and 33 deletions

View file

@ -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_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name);
PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals, PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
PyObject *name, PyObject *fromlist, PyObject *level); 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_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(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);

View file

@ -14,14 +14,14 @@ PyAPI_DATA(PyTypeObject) PyLazyImport_Type;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *lz_builtins; PyObject *lz_import_func;
PyObject *lz_from; PyObject *lz_from;
PyObject *lz_attr; PyObject *lz_attr;
} PyLazyImportObject; } PyLazyImportObject;
PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import); 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 #ifdef __cplusplus
} }

View file

@ -4,7 +4,7 @@
#include "pycore_lazyimportobject.h" #include "pycore_lazyimportobject.h"
PyObject * PyObject *
_PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr) _PyLazyImport_New(PyObject *import_func, PyObject *from, PyObject *attr)
{ {
PyLazyImportObject *m; PyLazyImportObject *m;
if (!from || !PyUnicode_Check(from)) { if (!from || !PyUnicode_Check(from)) {
@ -19,8 +19,8 @@ _PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr)
if (m == NULL) { if (m == NULL) {
return NULL; return NULL;
} }
Py_XINCREF(builtins); Py_XINCREF(import_func);
m->lz_builtins = builtins; m->lz_import_func = import_func;
Py_INCREF(from); Py_INCREF(from);
m->lz_from = from; m->lz_from = from;
Py_XINCREF(attr); Py_XINCREF(attr);
@ -33,7 +33,7 @@ static void
lazy_import_dealloc(PyLazyImportObject *m) lazy_import_dealloc(PyLazyImportObject *m)
{ {
PyObject_GC_UnTrack(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_from);
Py_XDECREF(m->lz_attr); Py_XDECREF(m->lz_attr);
Py_TYPE(m)->tp_free((PyObject *)m); Py_TYPE(m)->tp_free((PyObject *)m);
@ -68,7 +68,7 @@ lazy_import_repr(PyLazyImportObject *m)
static int static int
lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg) 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_from);
Py_VISIT(m->lz_attr); Py_VISIT(m->lz_attr);
return 0; return 0;
@ -77,7 +77,7 @@ lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg)
static int static int
lazy_import_clear(PyLazyImportObject *m) 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_from);
Py_CLEAR(m->lz_attr); Py_CLEAR(m->lz_attr);
return 0; return 0;

View file

@ -2999,13 +2999,21 @@ _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
return NULL; 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) { if (locals == NULL) {
locals = Py_None; locals = Py_None;
} }
/* Fast path for not overloaded __import__. */ /* Fast path for not overloaded __import__. */
if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) { if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) {
Py_DECREF(import_func);
int ilevel = PyLong_AsInt(level); int ilevel = PyLong_AsInt(level);
if (ilevel == -1 && _PyErr_Occurred(tstate)) { if (ilevel == -1 && _PyErr_Occurred(tstate)) {
return NULL; return NULL;
@ -3020,7 +3028,6 @@ _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
PyObject* args[5] = {name, globals, locals, fromlist, level}; PyObject* args[5] = {name, globals, locals, fromlist, level};
PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL);
Py_DECREF(import_func);
return res; return res;
} }
@ -3029,6 +3036,7 @@ PyObject *
_PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level, int lazy) PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level, int lazy)
{ {
PyObject *res = NULL;
// Check if global policy overrides the local syntax // Check if global policy overrides the local syntax
switch (PyImport_LazyImportsEnabled()) { switch (PyImport_LazyImportsEnabled()) {
case PyLazyImportsMode_ForcedOff: case PyLazyImportsMode_ForcedOff:
@ -3047,34 +3055,42 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *glob
} }
PyObject *import_func; PyObject *import_func;
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), &import_func) < 0) { if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) {
return NULL; 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"); _PyErr_SetString(tstate, PyExc_ImportError, "__lazy_import__ not found");
return NULL; goto error;
} }
if (locals == NULL) { if (locals == NULL) {
locals = Py_None; locals = Py_None;
} }
if (_PyImport_IsDefaultLazyImportFunc(tstate->interp, import_func)) { if (_PyImport_IsDefaultLazyImportFunc(tstate->interp, lazy_import_func)) {
Py_DECREF(import_func);
int ilevel = PyLong_AsInt(level); int ilevel = PyLong_AsInt(level);
if (ilevel == -1 && PyErr_Occurred()) { if (ilevel == -1 && PyErr_Occurred()) {
return NULL; goto error;
} }
return _PyImport_LazyImportModuleLevelObject( res = _PyImport_LazyImportModuleLevelObject(
tstate, name, builtins, globals, locals, fromlist, ilevel tstate, name, import_func, globals, locals, fromlist, ilevel
); );
goto error;
} }
PyObject* args[5] = {name, globals, locals, fromlist, level}; PyObject* args[6] = {name, globals, locals, fromlist, level, import_func};
PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); res = PyObject_Vectorcall(lazy_import_func, args, 6, NULL);
Py_DECREF(import_func); error:
Py_XDECREF(lazy_import_func);
Py_XDECREF(import_func);
return res; return res;
} }
@ -3256,7 +3272,7 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
if (d->lz_attr != NULL) { if (d->lz_attr != NULL) {
if (PyUnicode_Check(d->lz_attr)) { if (PyUnicode_Check(d->lz_attr)) {
PyObject *from = PyUnicode_FromFormat("%U.%U", d->lz_from, 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); Py_DECREF(from);
return ret; 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); Py_ssize_t dot = PyUnicode_FindChar(d->lz_from, '.', 0, PyUnicode_GET_LENGTH(d->lz_from), 1);
if (dot >= 0) { if (dot >= 0) {
PyObject *from = PyUnicode_Substring(d->lz_from, 0, dot); 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); Py_DECREF(from);
return ret; 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; return ret;
} }

View file

@ -3737,8 +3737,8 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
PyObject *globals = PyEval_GetGlobals(); PyObject *globals = PyEval_GetGlobals();
if (full) { if (full) {
obj = _PyEval_ImportName(tstate, obj = _PyEval_ImportNameWithImport(tstate,
lz->lz_builtins, lz->lz_import_func,
globals, globals,
globals, globals,
lz->lz_from, lz->lz_from,
@ -3749,8 +3749,8 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
if (name == NULL) { if (name == NULL) {
goto error; goto error;
} }
obj = _PyEval_ImportName(tstate, obj = _PyEval_ImportNameWithImport(tstate,
lz->lz_builtins, lz->lz_import_func,
globals, globals,
globals, globals,
name, name,
@ -3906,8 +3906,20 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
PyErr_SetString(PyExc_RuntimeError, "no current frame"); PyErr_SetString(PyExc_RuntimeError, "no current frame");
goto error; 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); locals, fromlist, level);
Py_DECREF(import_func);
goto error; goto error;
} }
} }
@ -4016,7 +4028,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
PyObject * PyObject *
_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
PyObject *name, PyObject *builtins, PyObject *name, PyObject *import_func,
PyObject *globals, PyObject *locals, PyObject *globals, PyObject *locals,
PyObject *fromlist, int level) 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); Py_DECREF(abs_name);
return res; return res;
} }