mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Don't allow __lazy_imports__ to work in try/except
This commit is contained in:
parent
c8c8838b1c
commit
7c494053b0
5 changed files with 66 additions and 73 deletions
|
|
@ -2630,6 +2630,22 @@ def test_compatibility_mode_used(self):
|
||||||
|
|
||||||
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
|
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
|
||||||
|
|
||||||
|
def test_compatibility_mode_func(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.lazy_imports.compatibility_mode_func
|
||||||
|
except ImportError as e:
|
||||||
|
self.fail('lazy import failed')
|
||||||
|
|
||||||
|
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
|
||||||
|
|
||||||
|
def test_compatibility_mode_try_except(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.lazy_imports.compatibility_mode_try_except
|
||||||
|
except ImportError as e:
|
||||||
|
self.fail('lazy import failed')
|
||||||
|
|
||||||
|
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
|
||||||
|
|
||||||
def test_compatibility_mode_relative(self):
|
def test_compatibility_mode_relative(self):
|
||||||
try:
|
try:
|
||||||
import test.test_import.data.lazy_imports.basic_compatibility_mode_relative
|
import test.test_import.data.lazy_imports.basic_compatibility_mode_relative
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
__lazy_modules__ = ['test.test_import.data.lazy_imports.basic2']
|
||||||
|
import test.test_import.data.lazy_imports.basic2
|
||||||
|
test.test_import.data.lazy_imports.basic2.f()
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
__lazy_modules__ = ['test.test_import.data.lazy_imports.basic2']
|
||||||
|
def f():
|
||||||
|
import test.test_import.data.lazy_imports.basic2
|
||||||
|
|
||||||
|
f()
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
__lazy_modules__ = ['test.test_import.data.lazy_imports.basic2']
|
||||||
|
try:
|
||||||
|
import test.test_import.data.lazy_imports.basic2
|
||||||
|
except:
|
||||||
|
pass
|
||||||
110
Python/ceval.c
110
Python/ceval.c
|
|
@ -2986,81 +2986,10 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
check_lazy_import_comatibility(PyThreadState *tstate, PyObject *lazy_modules,
|
|
||||||
PyObject *builtins, PyObject *globals, PyObject *locals,
|
|
||||||
PyObject *name, PyObject *fromlist, PyObject *level,
|
|
||||||
PyObject **mod)
|
|
||||||
{
|
|
||||||
int ilevel = PyLong_AsInt(level);
|
|
||||||
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *abs_name = _PyImport_GetAbsName(tstate, name, globals, ilevel);
|
|
||||||
if (abs_name == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int contains = PySequence_Contains(lazy_modules, abs_name);
|
|
||||||
Py_DECREF(abs_name);
|
|
||||||
if (contains < 0) {
|
|
||||||
return -1;
|
|
||||||
} else if (contains == 0) {
|
|
||||||
*mod = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_PyInterpreterFrame *frame = _PyEval_GetFrame();
|
|
||||||
if (frame == NULL) {
|
|
||||||
PyErr_SetString(PyExc_RuntimeError, "no current frame");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *import_func;
|
|
||||||
if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (import_func == NULL) {
|
|
||||||
_PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *final_mod = _PyImport_LazyImportModuleLevelObject(tstate, name, import_func, globals,
|
|
||||||
locals, fromlist, ilevel);
|
|
||||||
Py_DECREF(import_func);
|
|
||||||
if (final_mod == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*mod = final_mod;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
|
_PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
|
||||||
PyObject *name, PyObject *fromlist, PyObject *level)
|
PyObject *name, PyObject *fromlist, PyObject *level)
|
||||||
{
|
{
|
||||||
// Check if this module should be imported lazily due to the compatbility mode support via
|
|
||||||
// __lazy_modules__.
|
|
||||||
PyObject *lazy_modules;
|
|
||||||
if (globals != NULL &&
|
|
||||||
PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), &lazy_modules) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *res;
|
|
||||||
if (lazy_modules != NULL) {
|
|
||||||
int lazy = check_lazy_import_comatibility(tstate, lazy_modules, builtins, globals,
|
|
||||||
locals, name, fromlist, level, &res);
|
|
||||||
Py_DECREF(lazy_modules);
|
|
||||||
if (lazy < 0) {
|
|
||||||
return NULL;
|
|
||||||
} else if (res != NULL) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *import_func;
|
PyObject *import_func;
|
||||||
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) {
|
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -3070,7 +2999,7 @@ _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = _PyEval_ImportNameWithImport(tstate, import_func, globals, locals, name, fromlist, level);
|
PyObject *res = _PyEval_ImportNameWithImport(tstate, import_func, globals, locals, name, fromlist, level);
|
||||||
Py_DECREF(import_func);
|
Py_DECREF(import_func);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -3102,10 +3031,37 @@ _PyEval_ImportNameWithImport(PyThreadState *tstate, PyObject *import_func, PyObj
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
check_lazy_import_comatibility(PyThreadState *tstate, PyObject *globals,
|
||||||
|
PyObject *name, PyObject *level)
|
||||||
|
{
|
||||||
|
// Check if this module should be imported lazily due to the compatbility mode support via
|
||||||
|
// __lazy_modules__.
|
||||||
|
PyObject *lazy_modules = NULL;
|
||||||
|
if (globals != NULL &&
|
||||||
|
PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), &lazy_modules) < 0) {
|
||||||
|
return -1;
|
||||||
|
} else if (lazy_modules == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ilevel = PyLong_AsInt(level);
|
||||||
|
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *abs_name = _PyImport_GetAbsName(tstate, name, globals, ilevel);
|
||||||
|
if (abs_name == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PySequence_Contains(lazy_modules, abs_name);
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
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;
|
PyObject *res = NULL;
|
||||||
// Check if global policy overrides the local syntax
|
// Check if global policy overrides the local syntax
|
||||||
|
|
@ -3120,6 +3076,14 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *glob
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lazy) {
|
||||||
|
// see if __lazy_imports__ forces this to be lazy
|
||||||
|
lazy = check_lazy_import_comatibility(tstate, globals, name, level);
|
||||||
|
if (lazy < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!lazy) {
|
if (!lazy) {
|
||||||
// Not a lazy import or lazy imports are disabled, fallback to the regular import
|
// Not a lazy import or lazy imports are disabled, fallback to the regular import
|
||||||
return _PyEval_ImportName(tstate, builtins, globals, locals, name, fromlist, level);
|
return _PyEval_ImportName(tstate, builtins, globals, locals, name, fromlist, level);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue