Skip to content

Commit 46b3b75

Browse files
authored
Merge pull request #8 from LazyImportsCabal/lazy_test
Lazy test
2 parents 2799a4d + c63198c commit 46b3b75

File tree

6 files changed

+58
-9
lines changed

6 files changed

+58
-9
lines changed

Lib/test/test_import/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,6 +2558,26 @@ def test_basic_unused(self):
25582558

25592559
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
25602560

2561+
def test_basic_unused_use_externally(self):
2562+
try:
2563+
from test.test_import.data.lazy_imports import basic_unused
2564+
except ImportError as e:
2565+
self.fail('lazy import failed')
2566+
2567+
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
2568+
x = basic_unused.test.test_import.data.lazy_imports.basic2
2569+
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
2570+
2571+
def test_basic_from_unused_use_externally(self):
2572+
try:
2573+
from test.test_import.data.lazy_imports import basic_from_unused
2574+
except ImportError as e:
2575+
self.fail('lazy import failed')
2576+
2577+
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
2578+
x = basic_from_unused.basic2
2579+
self.assertTrue("test.test_import.data.lazy_imports.basic2" in sys.modules)
2580+
25612581
def test_basic_unused_dir(self):
25622582
try:
25632583
import test.test_import.data.lazy_imports.basic_unused
@@ -2758,6 +2778,19 @@ def test_lazy_import_pkg(self):
27582778
self.assertTrue("test.test_import.data.lazy_imports.pkg" in sys.modules)
27592779
self.assertTrue("test.test_import.data.lazy_imports.pkg.bar" in sys.modules)
27602780

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)
27612794

27622795
class TestSinglePhaseSnapshot(ModuleSnapshot):
27632796
"""A representation of a single-phase init module for testing.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lazy from test.test_import.data.lazy_imports import basic2
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)