mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Add __lazy_import__, check sys.modules before import
This commit is contained in:
parent
1c691ea756
commit
3b0d745e73
18 changed files with 272 additions and 40 deletions
|
|
@ -298,7 +298,7 @@ PyAPI_FUNC(void) _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *c
|
||||||
PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs);
|
PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs);
|
||||||
PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *);
|
PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
PyAPI_FUNC(PyObject *) _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
||||||
PyObject *name, PyObject *fromlist, PyObject *level);
|
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level);
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -1432,6 +1432,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__iter__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__iter__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__itruediv__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__itruediv__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__ixor__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__ixor__));
|
||||||
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__lazy_import__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__le__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__le__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__len__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__len__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__length_hint__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__length_hint__));
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ struct _Py_global_strings {
|
||||||
STRUCT_FOR_ID(__iter__)
|
STRUCT_FOR_ID(__iter__)
|
||||||
STRUCT_FOR_ID(__itruediv__)
|
STRUCT_FOR_ID(__itruediv__)
|
||||||
STRUCT_FOR_ID(__ixor__)
|
STRUCT_FOR_ID(__ixor__)
|
||||||
|
STRUCT_FOR_ID(__lazy_import__)
|
||||||
STRUCT_FOR_ID(__le__)
|
STRUCT_FOR_ID(__le__)
|
||||||
STRUCT_FOR_ID(__len__)
|
STRUCT_FOR_ID(__len__)
|
||||||
STRUCT_FOR_ID(__length_hint__)
|
STRUCT_FOR_ID(__length_hint__)
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ extern PyObject *
|
||||||
_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
|
_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
|
||||||
extern PyObject *
|
extern PyObject *
|
||||||
_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import);
|
_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import);
|
||||||
|
extern PyObject *
|
||||||
|
_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, PyObject *name, PyObject *builtins, PyObject *globals,
|
||||||
|
PyObject *locals, PyObject *fromlist,
|
||||||
|
int level);
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
|
|
@ -79,6 +83,10 @@ extern int _PyImport_IsDefaultImportFunc(
|
||||||
PyInterpreterState *interp,
|
PyInterpreterState *interp,
|
||||||
PyObject *func);
|
PyObject *func);
|
||||||
|
|
||||||
|
extern int _PyImport_IsDefaultLazyImportFunc(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
PyObject *func);
|
||||||
|
|
||||||
extern PyObject * _PyImport_GetImportlibLoader(
|
extern PyObject * _PyImport_GetImportlibLoader(
|
||||||
PyInterpreterState *interp,
|
PyInterpreterState *interp,
|
||||||
const char *loader_name);
|
const char *loader_name);
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,7 @@ struct _import_state {
|
||||||
int dlopenflags;
|
int dlopenflags;
|
||||||
#endif
|
#endif
|
||||||
PyObject *import_func;
|
PyObject *import_func;
|
||||||
|
PyObject *lazy_import_func;
|
||||||
/* The global import lock. */
|
/* The global import lock. */
|
||||||
_PyRecursiveMutex lock;
|
_PyRecursiveMutex lock;
|
||||||
/* diagnostic info in PyImport_ImportModuleLevelObject() */
|
/* diagnostic info in PyImport_ImportModuleLevelObject() */
|
||||||
|
|
|
||||||
1
Include/internal/pycore_runtime_init_generated.h
generated
1
Include/internal/pycore_runtime_init_generated.h
generated
|
|
@ -1430,6 +1430,7 @@ extern "C" {
|
||||||
INIT_ID(__iter__), \
|
INIT_ID(__iter__), \
|
||||||
INIT_ID(__itruediv__), \
|
INIT_ID(__itruediv__), \
|
||||||
INIT_ID(__ixor__), \
|
INIT_ID(__ixor__), \
|
||||||
|
INIT_ID(__lazy_import__), \
|
||||||
INIT_ID(__le__), \
|
INIT_ID(__le__), \
|
||||||
INIT_ID(__len__), \
|
INIT_ID(__len__), \
|
||||||
INIT_ID(__length_hint__), \
|
INIT_ID(__length_hint__), \
|
||||||
|
|
|
||||||
|
|
@ -408,6 +408,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
|
||||||
_PyUnicode_InternStatic(interp, &string);
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
assert(PyUnicode_GET_LENGTH(string) != 1);
|
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||||
|
string = &_Py_ID(__lazy_import__);
|
||||||
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
|
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||||
string = &_Py_ID(__le__);
|
string = &_Py_ID(__le__);
|
||||||
_PyUnicode_InternStatic(interp, &string);
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
|
|
|
||||||
|
|
@ -2540,6 +2540,31 @@ def test_disallowed_reimport(self):
|
||||||
self.assertIsNot(excsnap, None)
|
self.assertIsNot(excsnap, None)
|
||||||
|
|
||||||
|
|
||||||
|
class LazyImportTests(unittest.TestCase):
|
||||||
|
def tearDown(self):
|
||||||
|
"""Make sure no modules pre-exist in sys.modules which are being used to
|
||||||
|
test."""
|
||||||
|
for key in list(sys.modules.keys()):
|
||||||
|
if key.startswith('test.test_import.data.lazy_imports'):
|
||||||
|
del sys.modules[key]
|
||||||
|
|
||||||
|
def test_basic_unused(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.lazy_imports.basic_unused
|
||||||
|
except ImportError as e:
|
||||||
|
self.fail('lazy import failed')
|
||||||
|
|
||||||
|
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
|
||||||
|
|
||||||
|
def test_basic_used(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.lazy_imports.basic_used
|
||||||
|
except ImportError as e:
|
||||||
|
self.fail('lazy import failed')
|
||||||
|
|
||||||
|
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
|
||||||
|
|
||||||
|
|
||||||
class TestSinglePhaseSnapshot(ModuleSnapshot):
|
class TestSinglePhaseSnapshot(ModuleSnapshot):
|
||||||
"""A representation of a single-phase init module for testing.
|
"""A representation of a single-phase init module for testing.
|
||||||
|
|
||||||
|
|
|
||||||
4
Lib/test/test_import/data/lazy_imports/basic2.py
Normal file
4
Lib/test/test_import/data/lazy_imports/basic2.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
def f():
|
||||||
|
pass
|
||||||
|
|
||||||
|
x = 42
|
||||||
1
Lib/test/test_import/data/lazy_imports/basic_unused.py
Normal file
1
Lib/test/test_import/data/lazy_imports/basic_unused.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
lazy import test.test_import.data.lazy_imports.basic2
|
||||||
3
Lib/test/test_import/data/lazy_imports/basic_used.py
Normal file
3
Lib/test/test_import/data/lazy_imports/basic_used.py
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
lazy import test.test_import.data.lazy_imports.basic2 as basic2
|
||||||
|
|
||||||
|
basic2.f()
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "pycore_fileutils.h" // _PyFile_Flush
|
#include "pycore_fileutils.h" // _PyFile_Flush
|
||||||
#include "pycore_floatobject.h" // _PyFloat_ExactDealloc()
|
#include "pycore_floatobject.h" // _PyFloat_ExactDealloc()
|
||||||
#include "pycore_interp.h" // _PyInterpreterState_GetConfig()
|
#include "pycore_interp.h" // _PyInterpreterState_GetConfig()
|
||||||
|
#include "pycore_import.h" // _PyImport_LazyImportModuleLevelObject ()
|
||||||
#include "pycore_long.h" // _PyLong_CompactValue
|
#include "pycore_long.h" // _PyLong_CompactValue
|
||||||
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
|
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
|
||||||
#include "pycore_object.h" // _Py_AddToAllObjects()
|
#include "pycore_object.h" // _Py_AddToAllObjects()
|
||||||
|
|
@ -287,6 +288,47 @@ builtin___import___impl(PyObject *module, PyObject *name, PyObject *globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
__lazy_import__ as builtin___lazy_import__
|
||||||
|
|
||||||
|
name: object
|
||||||
|
globals: object(c_default="NULL") = None
|
||||||
|
locals: object(c_default="NULL") = None
|
||||||
|
fromlist: object(c_default="NULL") = ()
|
||||||
|
level: int = 0
|
||||||
|
|
||||||
|
Lazily imports a module.
|
||||||
|
|
||||||
|
Returns either the module to be imported or a imp.lazy_module object which
|
||||||
|
indicates the module to be lazily imported.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
builtin___lazy_import___impl(PyObject *module, PyObject *name,
|
||||||
|
PyObject *globals, PyObject *locals,
|
||||||
|
PyObject *fromlist, int level)
|
||||||
|
/*[clinic end generated code: output=300f1771094b9e8c input=57123e246d6c36ee]*/
|
||||||
|
{
|
||||||
|
PyObject *builtins;
|
||||||
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
if (globals == NULL) {
|
||||||
|
globals = PyEval_GetGlobals();
|
||||||
|
}
|
||||||
|
if (locals == NULL) {
|
||||||
|
locals = globals;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyMapping_GetOptionalItem(globals, &_Py_ID(__builtins__), &builtins) < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "unable to get builtins for lazy import");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *res = _PyImport_LazyImportModuleLevelObject(tstate, name, builtins,
|
||||||
|
globals, locals, fromlist, level);
|
||||||
|
Py_DECREF(builtins);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
abs as builtin_abs
|
abs as builtin_abs
|
||||||
|
|
||||||
|
|
@ -3344,6 +3386,7 @@ static PyMethodDef builtin_methods[] = {
|
||||||
{"__build_class__", _PyCFunction_CAST(builtin___build_class__),
|
{"__build_class__", _PyCFunction_CAST(builtin___build_class__),
|
||||||
METH_FASTCALL | METH_KEYWORDS, build_class_doc},
|
METH_FASTCALL | METH_KEYWORDS, build_class_doc},
|
||||||
BUILTIN___IMPORT___METHODDEF
|
BUILTIN___IMPORT___METHODDEF
|
||||||
|
BUILTIN___LAZY_IMPORT___METHODDEF
|
||||||
BUILTIN_ABS_METHODDEF
|
BUILTIN_ABS_METHODDEF
|
||||||
BUILTIN_ALL_METHODDEF
|
BUILTIN_ALL_METHODDEF
|
||||||
BUILTIN_ANY_METHODDEF
|
BUILTIN_ANY_METHODDEF
|
||||||
|
|
|
||||||
|
|
@ -2948,7 +2948,7 @@ dummy_func(
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
|
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
|
||||||
PyObject *res_o;
|
PyObject *res_o;
|
||||||
if (oparg & 0x01) {
|
if (oparg & 0x01) {
|
||||||
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), name,
|
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), LOCALS(), name,
|
||||||
PyStackRef_AsPyObjectBorrow(fromlist),
|
PyStackRef_AsPyObjectBorrow(fromlist),
|
||||||
PyStackRef_AsPyObjectBorrow(level));
|
PyStackRef_AsPyObjectBorrow(level));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3027,32 +3027,37 @@ _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
_PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
||||||
PyObject *name, PyObject *fromlist, PyObject *level)
|
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level)
|
||||||
{
|
{
|
||||||
PyObject *res = NULL;
|
PyObject *import_func;
|
||||||
PyObject *abs_name = NULL;
|
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), &import_func) < 0) {
|
||||||
int ilevel = PyLong_AsInt(level);
|
return NULL;
|
||||||
if (ilevel == -1 && PyErr_Occurred()) {
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
if (ilevel > 0) {
|
if (import_func == NULL) {
|
||||||
abs_name = _PyImport_ResolveName(tstate, name, globals, ilevel);
|
_PyErr_SetString(tstate, PyExc_ImportError, "__lazy_import__ not found");
|
||||||
if (abs_name == NULL) {
|
return NULL;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else { /* ilevel == 0 */
|
|
||||||
if (PyUnicode_GET_LENGTH(name) == 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "Empty module name");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
abs_name = name;
|
|
||||||
Py_INCREF(abs_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check sys.modules for module
|
if (locals == NULL) {
|
||||||
res = _PyLazyImport_New(builtins, abs_name, fromlist);
|
locals = Py_None;
|
||||||
error:
|
}
|
||||||
Py_XDECREF(abs_name);
|
|
||||||
|
if (_PyImport_IsDefaultLazyImportFunc(tstate->interp, import_func)) {
|
||||||
|
Py_DECREF(import_func);
|
||||||
|
|
||||||
|
int ilevel = PyLong_AsInt(level);
|
||||||
|
if (ilevel == -1 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _PyImport_LazyImportModuleLevelObject(
|
||||||
|
tstate, name, builtins, globals, locals, fromlist, ilevel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* args[5] = {name, globals, locals, fromlist, level};
|
||||||
|
PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL);
|
||||||
|
Py_DECREF(import_func);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
97
Python/clinic/bltinmodule.c.h
generated
97
Python/clinic/bltinmodule.c.h
generated
|
|
@ -113,6 +113,101 @@ exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(builtin___lazy_import____doc__,
|
||||||
|
"__lazy_import__($module, /, name, globals=None, locals=None,\n"
|
||||||
|
" fromlist=(), level=0)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Lazily imports a module.\n"
|
||||||
|
"\n"
|
||||||
|
"Returns either the module to be imported or a imp.lazy_module object which\n"
|
||||||
|
"indicates the module to be lazily imported.");
|
||||||
|
|
||||||
|
#define BUILTIN___LAZY_IMPORT___METHODDEF \
|
||||||
|
{"__lazy_import__", _PyCFunction_CAST(builtin___lazy_import__), METH_FASTCALL|METH_KEYWORDS, builtin___lazy_import____doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
builtin___lazy_import___impl(PyObject *module, PyObject *name,
|
||||||
|
PyObject *globals, PyObject *locals,
|
||||||
|
PyObject *fromlist, int level);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
builtin___lazy_import__(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||||
|
|
||||||
|
#define NUM_KEYWORDS 5
|
||||||
|
static struct {
|
||||||
|
PyGC_Head _this_is_not_used;
|
||||||
|
PyObject_VAR_HEAD
|
||||||
|
Py_hash_t ob_hash;
|
||||||
|
PyObject *ob_item[NUM_KEYWORDS];
|
||||||
|
} _kwtuple = {
|
||||||
|
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||||
|
.ob_hash = -1,
|
||||||
|
.ob_item = { &_Py_ID(name), &_Py_ID(globals), &_Py_ID(locals), &_Py_ID(fromlist), &_Py_ID(level), },
|
||||||
|
};
|
||||||
|
#undef NUM_KEYWORDS
|
||||||
|
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||||
|
|
||||||
|
#else // !Py_BUILD_CORE
|
||||||
|
# define KWTUPLE NULL
|
||||||
|
#endif // !Py_BUILD_CORE
|
||||||
|
|
||||||
|
static const char * const _keywords[] = {"name", "globals", "locals", "fromlist", "level", NULL};
|
||||||
|
static _PyArg_Parser _parser = {
|
||||||
|
.keywords = _keywords,
|
||||||
|
.fname = "__lazy_import__",
|
||||||
|
.kwtuple = KWTUPLE,
|
||||||
|
};
|
||||||
|
#undef KWTUPLE
|
||||||
|
PyObject *argsbuf[5];
|
||||||
|
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||||
|
PyObject *name;
|
||||||
|
PyObject *globals = NULL;
|
||||||
|
PyObject *locals = NULL;
|
||||||
|
PyObject *fromlist = NULL;
|
||||||
|
int level = 0;
|
||||||
|
|
||||||
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||||
|
/*minpos*/ 1, /*maxpos*/ 5, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||||
|
if (!args) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
name = args[0];
|
||||||
|
if (!noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
|
if (args[1]) {
|
||||||
|
globals = args[1];
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args[2]) {
|
||||||
|
locals = args[2];
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args[3]) {
|
||||||
|
fromlist = args[3];
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
level = PyLong_AsInt(args[4]);
|
||||||
|
if (level == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
skip_optional_pos:
|
||||||
|
return_value = builtin___lazy_import___impl(module, name, globals, locals, fromlist, level);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(builtin_abs__doc__,
|
PyDoc_STRVAR(builtin_abs__doc__,
|
||||||
"abs($module, number, /)\n"
|
"abs($module, number, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
|
@ -1274,4 +1369,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=c0b72519622c849e input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=65b2a6dfb50b64bc input=a9049054013a1b77]*/
|
||||||
|
|
|
||||||
2
Python/executor_cases.c.h
generated
2
Python/executor_cases.c.h
generated
|
|
@ -4149,7 +4149,7 @@
|
||||||
PyObject *res_o;
|
PyObject *res_o;
|
||||||
if (oparg & 0x01) {
|
if (oparg & 0x01) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), name,
|
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), LOCALS(), name,
|
||||||
PyStackRef_AsPyObjectBorrow(fromlist),
|
PyStackRef_AsPyObjectBorrow(fromlist),
|
||||||
PyStackRef_AsPyObjectBorrow(level));
|
PyStackRef_AsPyObjectBorrow(level));
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
|
|
||||||
2
Python/generated_cases.c.h
generated
2
Python/generated_cases.c.h
generated
|
|
@ -6225,7 +6225,7 @@
|
||||||
PyObject *res_o;
|
PyObject *res_o;
|
||||||
if (oparg & 0x01) {
|
if (oparg & 0x01) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), name,
|
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), LOCALS(), name,
|
||||||
PyStackRef_AsPyObjectBorrow(fromlist),
|
PyStackRef_AsPyObjectBorrow(fromlist),
|
||||||
PyStackRef_AsPyObjectBorrow(level));
|
PyStackRef_AsPyObjectBorrow(level));
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,9 @@ static struct _inittab *inittab_copy = NULL;
|
||||||
#define IMPORT_FUNC(interp) \
|
#define IMPORT_FUNC(interp) \
|
||||||
(interp)->imports.import_func
|
(interp)->imports.import_func
|
||||||
|
|
||||||
|
#define LAZY_IMPORT_FUNC(interp) \
|
||||||
|
(interp)->imports.lazy_import_func
|
||||||
|
|
||||||
#define IMPORT_LOCK(interp) \
|
#define IMPORT_LOCK(interp) \
|
||||||
(interp)->imports.lock
|
(interp)->imports.lock
|
||||||
|
|
||||||
|
|
@ -3400,6 +3403,12 @@ _PyImport_InitDefaultImportFunc(PyInterpreterState *interp)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
IMPORT_FUNC(interp) = import_func;
|
IMPORT_FUNC(interp) = import_func;
|
||||||
|
|
||||||
|
// Get the __lazy_import__ function
|
||||||
|
if (PyDict_GetItemStringRef(interp->builtins, "__lazy_import__", &import_func) <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LAZY_IMPORT_FUNC(interp) = import_func;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3409,6 +3418,11 @@ _PyImport_IsDefaultImportFunc(PyInterpreterState *interp, PyObject *func)
|
||||||
return func == IMPORT_FUNC(interp);
|
return func == IMPORT_FUNC(interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyImport_IsDefaultLazyImportFunc(PyInterpreterState *interp, PyObject *func)
|
||||||
|
{
|
||||||
|
return func == LAZY_IMPORT_FUNC(interp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Import a module, either built-in, frozen, or external, and return
|
/* Import a module, either built-in, frozen, or external, and return
|
||||||
its module object WITH INCREMENTED REFERENCE COUNT */
|
its module object WITH INCREMENTED REFERENCE COUNT */
|
||||||
|
|
@ -3685,8 +3699,6 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
PyObject *fromlist = NULL;
|
PyObject *fromlist = NULL;
|
||||||
assert(lazy_import != NULL);
|
assert(lazy_import != NULL);
|
||||||
assert(PyLazyImport_CheckExact(lazy_import));
|
assert(PyLazyImport_CheckExact(lazy_import));
|
||||||
PyObject *state_dict = _PyThreadState_GetDict(tstate);
|
|
||||||
assert(state_dict != NULL);
|
|
||||||
|
|
||||||
PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import;
|
PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import;
|
||||||
|
|
||||||
|
|
@ -3821,6 +3833,19 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
|
||||||
#undef accumulated
|
#undef accumulated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
get_abs_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level)
|
||||||
|
{
|
||||||
|
if (level > 0) {
|
||||||
|
return resolve_name(tstate, name, globals, level);
|
||||||
|
}
|
||||||
|
if (PyUnicode_GET_LENGTH(name) == 0) {
|
||||||
|
_PyErr_SetString(tstate, PyExc_ValueError, "Empty module name");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return Py_NewRef(name);
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
PyObject *locals, PyObject *fromlist,
|
PyObject *locals, PyObject *fromlist,
|
||||||
|
|
@ -3852,17 +3877,9 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level > 0) {
|
abs_name = get_abs_name(tstate, name, globals, level);
|
||||||
abs_name = resolve_name(tstate, name, globals, level);
|
if (abs_name == NULL) {
|
||||||
if (abs_name == NULL)
|
goto error;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
else { /* level == 0 */
|
|
||||||
if (PyUnicode_GET_LENGTH(name) == 0) {
|
|
||||||
_PyErr_SetString(tstate, PyExc_ValueError, "Empty module name");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
abs_name = Py_NewRef(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod = import_get_module(tstate, abs_name);
|
mod = import_get_module(tstate, abs_name);
|
||||||
|
|
@ -3966,6 +3983,28 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
return final_mod;
|
return final_mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
|
||||||
|
PyObject *name, PyObject *builtins,
|
||||||
|
PyObject *globals, PyObject *locals,
|
||||||
|
PyObject *fromlist, int level)
|
||||||
|
{
|
||||||
|
PyObject *abs_name = get_abs_name(tstate, name, globals, level);
|
||||||
|
if (abs_name == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *mod = PyImport_GetModule(abs_name);
|
||||||
|
if (mod != NULL) {
|
||||||
|
Py_DECREF(abs_name);
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *res = _PyLazyImport_New(builtins, abs_name, fromlist);
|
||||||
|
Py_DECREF(abs_name);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals,
|
PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals,
|
||||||
PyObject *fromlist, int level)
|
PyObject *fromlist, int level)
|
||||||
|
|
@ -4172,6 +4211,7 @@ _PyImport_ClearCore(PyInterpreterState *interp)
|
||||||
Py_CLEAR(MODULES_BY_INDEX(interp));
|
Py_CLEAR(MODULES_BY_INDEX(interp));
|
||||||
Py_CLEAR(IMPORTLIB(interp));
|
Py_CLEAR(IMPORTLIB(interp));
|
||||||
Py_CLEAR(IMPORT_FUNC(interp));
|
Py_CLEAR(IMPORT_FUNC(interp));
|
||||||
|
Py_CLEAR(LAZY_IMPORT_FUNC(interp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue