Skip to content

Commit c63198c

Browse files
committed
Move eager check for from imports into import from
1 parent 7d07ae1 commit c63198c

File tree

5 files changed

+37
-9
lines changed

5 files changed

+37
-9
lines changed

Lib/test/test_import/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2778,6 +2778,19 @@ def test_lazy_import_pkg(self):
27782778
self.assertTrue("test.test_import.data.lazy_imports.pkg" in sys.modules)
27792779
self.assertTrue("test.test_import.data.lazy_imports.pkg.bar" in sys.modules)
27802780

2781+
def test_lazy_import_pkg_cross_import(self):
2782+
try:
2783+
import test.test_import.data.lazy_imports.pkg.c
2784+
except ImportError as e:
2785+
self.fail('lazy import failed')
2786+
2787+
self.assertTrue("test.test_import.data.lazy_imports.pkg" in sys.modules)
2788+
self.assertTrue("test.test_import.data.lazy_imports.pkg.c" in sys.modules)
2789+
self.assertFalse("test.test_import.data.lazy_imports.pkg.b" in sys.modules)
2790+
2791+
g = test.test_import.data.lazy_imports.pkg.c.get_globals()
2792+
self.assertEqual(type(g["x"]), int)
2793+
self.assertEqual(type(g["b"]), importlib.lazy_import)
27812794

27822795
class TestSinglePhaseSnapshot(ModuleSnapshot):
27832796
"""A representation of a single-phase init module for testing.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def foo():
2+
return 'foo'
3+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lazy from . import b, x
2+
3+
def get_globals():
4+
return globals()

Python/ceval.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,6 +3304,22 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
33043304
assert(name && PyUnicode_Check(name));
33053305
PyObject *ret;
33063306
PyLazyImportObject *d = (PyLazyImportObject *)v;
3307+
PyObject *mod = PyImport_GetModule(d->lz_from);
3308+
if (mod != NULL) {
3309+
// Check if the module already has the attribute, if so, resolve it eagerly.
3310+
if (PyModule_Check(mod)) {
3311+
PyObject *mod_dict = PyModule_GetDict(mod);
3312+
if (mod_dict != NULL) {
3313+
if (PyDict_GetItemRef(mod_dict, name, &ret) < 0) {
3314+
return NULL;
3315+
} else if (ret != NULL) {
3316+
return ret;
3317+
}
3318+
}
3319+
}
3320+
Py_DECREF(mod);
3321+
}
3322+
33073323
if (d->lz_attr != NULL) {
33083324
if (PyUnicode_Check(d->lz_attr)) {
33093325
PyObject *from = PyUnicode_FromFormat("%U.%U", d->lz_from, d->lz_attr);

Python/import.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4221,16 +4221,8 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
42214221
}
42224222

42234223
PyInterpreterState *interp = tstate->interp;
4224-
_PyInterpreterFrame *frame = _PyEval_GetFrame();
42254224
assert(frame->f_globals == frame->f_locals); // should only be called in global scope
42264225

4227-
PyObject *mod = PyImport_GetModule(abs_name);
4228-
bool already_exists = mod != NULL;
4229-
Py_XDECREF(mod);
4230-
if (mod != NULL) {
4231-
return PyImport_ImportModuleLevelObject(name, globals, locals, fromlist, level);
4232-
}
4233-
42344226
// Check if the filter disables the lazy import
42354227
PyObject *filter = LAZY_IMPORTS_FILTER(interp);
42364228
if (filter != NULL) {
@@ -4262,7 +4254,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
42624254
}
42634255

42644256
PyObject *res = _PyLazyImport_New(import_func, abs_name, fromlist);
4265-
if (!already_exists && register_lazy_on_parent(tstate, abs_name, import_func) < 0) {
4257+
if (register_lazy_on_parent(tstate, abs_name, import_func) < 0) {
42664258
Py_DECREF(res);
42674259
res = NULL;
42684260
}

0 commit comments

Comments
 (0)