Skip to content

Commit 9118b95

Browse files
committed
Add child modules as attributes of parent modules.
Failing to add child modules as attributes of parent module will prevent them from being accessible through parent module.
1 parent 6ad32a9 commit 9118b95

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

src/_pytest/pathlib.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
601601
otherwise "src.tests.test_foo" is not importable by ``__import__``.
602602
"""
603603
module_parts = module_name.split(".")
604+
child_module: Union[ModuleType, None] = None
605+
module: Union[ModuleType, None] = None
606+
child_name: str = ""
604607
while module_name:
605608
if module_name not in modules:
606609
try:
@@ -610,13 +613,22 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
610613
# ourselves to fall back to creating a dummy module.
611614
if not sys.meta_path:
612615
raise ModuleNotFoundError
613-
importlib.import_module(module_name)
616+
module = importlib.import_module(module_name)
614617
except ModuleNotFoundError:
615618
module = ModuleType(
616619
module_name,
617620
doc="Empty module created by pytest's importmode=importlib.",
618621
)
622+
else:
623+
module = modules[module_name]
624+
if child_module:
625+
# Add child attribute to the parent that can reference the child
626+
# modules.
627+
if not hasattr(module, child_name):
628+
setattr(module, child_name, child_module)
619629
modules[module_name] = module
630+
# Keep track of the child module while moving up the tree.
631+
child_module, child_name = module, module_name.rpartition(".")[-1]
620632
module_parts.pop(-1)
621633
module_name = ".".join(module_parts)
622634

testing/test_pathlib.py

+12
Original file line numberDiff line numberDiff line change
@@ -580,3 +580,15 @@ def test_insert_missing_modules(
580580
modules = {}
581581
insert_missing_modules(modules, "")
582582
assert modules == {}
583+
584+
def test_parent_contains_child_module_attribute(
585+
self, monkeypatch: MonkeyPatch, tmp_path: Path
586+
):
587+
monkeypatch.chdir(tmp_path)
588+
# Use 'xxx' and 'xxy' as parent names as they are unlikely to exist and
589+
# don't end up being imported.
590+
modules = {"xxx.tests.foo": ModuleType("xxx.tests.foo")}
591+
insert_missing_modules(modules, "xxx.tests.foo")
592+
assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"]
593+
assert modules["xxx"].tests == modules["xxx.tests"]
594+
assert modules["xxx.tests"].foo == modules["xxx.tests.foo"]

0 commit comments

Comments
 (0)