importlib: set module as attribute in its parent module

This needs to be done manually, not being done as part of the import mechanism:

73906d5c90/Lib/importlib/_bootstrap.py (L1335-L1342)

Fix #12194
This commit is contained in:
Bruno Oliveira 2024-04-12 15:53:31 -03:00 committed by Bruno Oliveira
parent ad95d59d61
commit 70dd4b0880
3 changed files with 41 additions and 0 deletions

View File

@ -0,0 +1 @@
Fixed a bug with ``--importmode=importlib`` and ``--doctest-modules`` where child modules did not appear as attributes in parent modules.

View File

@ -641,11 +641,26 @@ def _import_module_using_spec(
spec.loader.exec_module(mod) # type: ignore[union-attr]
if insert_modules:
insert_missing_modules(sys.modules, module_name)
_set_name_in_parent(mod)
return mod
return None
def _set_name_in_parent(module: ModuleType) -> None:
"""
Sets an attribute in the module's parent pointing to the module itself (#12194).
Based on https://github.com/python/cpython/blob/73906d5c908c1e0b73c5436faeff7d93698fc074/Lib/importlib/_bootstrap.py#L1335-L1342.
"""
parent, _, name = module.__name__.rpartition(".")
if not parent:
return
parent_module = sys.modules.get(parent)
if parent_module is not None:
setattr(sys.modules[parent], name, module)
def spec_matches_module_path(
module_spec: Optional[ModuleSpec], module_path: Path
) -> bool:

View File

@ -1126,6 +1126,31 @@ def test_safe_exists(tmp_path: Path) -> None:
assert safe_exists(p) is False
def test_import_sets_module_as_attribute(pytester: Pytester) -> None:
"""Regression test for #12194."""
pytester.path.joinpath("foo/bar/baz").mkdir(parents=True)
pytester.path.joinpath("foo/__init__.py").touch()
pytester.path.joinpath("foo/bar/__init__.py").touch()
pytester.path.joinpath("foo/bar/baz/__init__.py").touch()
f = pytester.makepyfile(
"""
import foo
from foo.bar import baz
foo.bar.baz
def test_foo() -> None:
pass
"""
)
pytester.syspathinsert()
result = pytester.runpython(f)
assert result.ret == 0
result = pytester.runpytest("--import-mode=importlib", "--doctest-modules")
assert result.ret == 0
class TestNamespacePackages:
"""Test import_path support when importing from properly namespace packages."""