Skip to content

Commit 41ab092

Browse files
committed
Add compatiblity mode
1 parent de281fd commit 41ab092

File tree

8 files changed

+53
-7
lines changed

8 files changed

+53
-7
lines changed

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ struct _Py_global_strings {
156156
STRUCT_FOR_ID(__itruediv__)
157157
STRUCT_FOR_ID(__ixor__)
158158
STRUCT_FOR_ID(__lazy_import__)
159+
STRUCT_FOR_ID(__lazy_modules__)
159160
STRUCT_FOR_ID(__le__)
160161
STRUCT_FOR_ID(__len__)
161162
STRUCT_FOR_ID(__length_hint__)
@@ -574,7 +575,6 @@ struct _Py_global_strings {
574575
STRUCT_FOR_ID(last_type)
575576
STRUCT_FOR_ID(last_value)
576577
STRUCT_FOR_ID(latin1)
577-
STRUCT_FOR_ID(lazy)
578578
STRUCT_FOR_ID(leaf_size)
579579
STRUCT_FOR_ID(legacy)
580580
STRUCT_FOR_ID(len)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_import/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2614,6 +2614,23 @@ def test_global_filter_from_true(self):
26142614

26152615
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
26162616

2617+
def test_compatibility_mode(self):
2618+
try:
2619+
import test.test_import.data.lazy_imports.basic_compatibility_mode
2620+
except ImportError as e:
2621+
self.fail('lazy import failed')
2622+
2623+
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
2624+
2625+
def test_compatibility_mode_relative(self):
2626+
try:
2627+
import test.test_import.data.lazy_imports.basic_compatibility_mode_relative
2628+
except ImportError as e:
2629+
self.fail('lazy import failed')
2630+
2631+
self.assertFalse("test.test_import.data.lazy_imports.basic2" in sys.modules)
2632+
2633+
26172634

26182635
class TestSinglePhaseSnapshot(ModuleSnapshot):
26192636
"""A representation of a single-phase init module for testing.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__lazy_modules__ = ['test.test_import.data.lazy_imports.basic2']
2+
import test.test_import.data.lazy_imports.basic2
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__lazy_modules__ = ['test.test_import.data.lazy_imports.basic2']
2+
lazy from .basic2 import f

Python/import.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3862,6 +3862,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
38623862
PyObject *final_mod = NULL;
38633863
PyObject *mod = NULL;
38643864
PyObject *package = NULL;
3865+
PyObject *lazy_modules = NULL;
38653866
PyInterpreterState *interp = tstate->interp;
38663867
int has_from;
38673868

@@ -3870,6 +3871,11 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
38703871
goto error;
38713872
}
38723873

3874+
if (globals != NULL &&
3875+
PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), &lazy_modules) < 0) {
3876+
goto error;
3877+
}
3878+
38733879
/* The below code is importlib.__import__() & _gcd_import(), ported to C
38743880
for added performance. */
38753881

@@ -3888,6 +3894,24 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
38883894
goto error;
38893895
}
38903896

3897+
if (lazy_modules != NULL) {
3898+
// Check and see if the module is opting in w/o syntax for backwards compatibility
3899+
// with older Python versions.
3900+
int contains = PySequence_Contains(lazy_modules, name);
3901+
if (contains < 0) {
3902+
goto error;
3903+
} else if (contains == 1) {
3904+
_PyInterpreterFrame *frame = _PyEval_GetFrame();
3905+
if (frame == NULL) {
3906+
PyErr_SetString(PyExc_RuntimeError, "no current frame");
3907+
goto error;
3908+
}
3909+
final_mod = _PyImport_LazyImportModuleLevelObject(tstate, name, frame->f_builtins, globals,
3910+
locals, fromlist, level);
3911+
goto error;
3912+
}
3913+
}
3914+
38913915
mod = import_get_module(tstate, abs_name);
38923916
if (mod == NULL && _PyErr_Occurred(tstate)) {
38933917
goto error;
@@ -3980,6 +4004,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
39804004
}
39814005

39824006
error:
4007+
Py_XDECREF(lazy_modules);
39834008
Py_XDECREF(abs_name);
39844009
Py_XDECREF(mod);
39854010
Py_XDECREF(package);

0 commit comments

Comments
 (0)