Skip to content

Commit 0456068

Browse files
brittanyreypablogsal
authored andcommitted
Read __spec__ from the module dict when checking for initialization
1 parent 8ef4ae0 commit 0456068

2 files changed

Lines changed: 24 additions & 3 deletions

File tree

‎Lib/test/test_lazy_import/__init__.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,25 @@ def test_initializing_module_is_still_tracked(self):
13721372
""")
13731373
assert_python_ok("-c", code)
13741374

1375+
def test_module_spec_descriptor_is_not_run(self):
1376+
"""Checking whether a module is loaded must not run its descriptors."""
1377+
code = textwrap.dedent("""
1378+
import sys
1379+
import types
1380+
1381+
class RaisingSpec(types.ModuleType):
1382+
@property
1383+
def __spec__(self):
1384+
raise RuntimeError("__spec__ descriptor was run")
1385+
1386+
sys.modules["raising_spec"] = RaisingSpec("raising_spec")
1387+
lazy import raising_spec
1388+
assert "raising_spec" not in sys.lazy_modules, (
1389+
f"expected 'raising_spec' untracked, got {sys.lazy_modules}"
1390+
)
1391+
""")
1392+
assert_python_ok("-c", code)
1393+
13751394
def test_pending_submodule_is_still_tracked(self):
13761395
"""`lazy from` a submodule that is not loaded must stay tracked."""
13771396
code = textwrap.dedent("""

‎Python/import.c‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,10 +4390,12 @@ lazy_modules_add(PyThreadState *tstate, PyObject *name)
43904390
}
43914391
// A None entry blocks the import rather than satisfying it.
43924392
int loaded = (existing != NULL && existing != Py_None);
4393-
if (loaded) {
4394-
// Check if the module is still initializing.
4393+
if (loaded && PyModule_Check(existing)) {
4394+
// Check if the module is still initializing. Read __spec__ from the
4395+
// module dict so that a descriptor on a module subclass is not run.
43954396
PyObject *spec;
4396-
int rc = PyObject_GetOptionalAttr(existing, &_Py_ID(__spec__), &spec);
4397+
int rc = PyDict_GetItemRef(_PyModule_GetDict(existing),
4398+
&_Py_ID(__spec__), &spec);
43974399
if (rc > 0) {
43984400
rc = _PyModuleSpec_IsInitializing(spec);
43994401
Py_DECREF(spec);

0 commit comments

Comments
 (0)