Skip to content

Commit 46c0a11

Browse files
akhilramkeenicoddemus
authored andcommitted
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 ba60649 commit 46c0a11

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

src/_pytest/pathlib.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,9 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
633633
otherwise "src.tests.test_foo" is not importable by ``__import__``.
634634
"""
635635
module_parts = module_name.split(".")
636+
child_module: Union[ModuleType, None] = None
637+
module: Union[ModuleType, None] = None
638+
child_name: str = ""
636639
while module_name:
637640
if module_name not in modules:
638641
try:
@@ -642,13 +645,22 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
642645
# ourselves to fall back to creating a dummy module.
643646
if not sys.meta_path:
644647
raise ModuleNotFoundError
645-
importlib.import_module(module_name)
648+
module = importlib.import_module(module_name)
646649
except ModuleNotFoundError:
647650
module = ModuleType(
648651
module_name,
649652
doc="Empty module created by pytest's importmode=importlib.",
650653
)
654+
else:
655+
module = modules[module_name]
656+
if child_module:
657+
# Add child attribute to the parent that can reference the child
658+
# modules.
659+
if not hasattr(module, child_name):
660+
setattr(module, child_name, child_module)
651661
modules[module_name] = module
662+
# Keep track of the child module while moving up the tree.
663+
child_module, child_name = module, module_name.rpartition(".")[-1]
652664
module_parts.pop(-1)
653665
module_name = ".".join(module_parts)
654666

testing/test_pathlib.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,3 +592,15 @@ def test_insert_missing_modules(
592592
modules = {}
593593
insert_missing_modules(modules, "")
594594
assert modules == {}
595+
596+
def test_parent_contains_child_module_attribute(
597+
self, monkeypatch: MonkeyPatch, tmp_path: Path
598+
):
599+
monkeypatch.chdir(tmp_path)
600+
# Use 'xxx' and 'xxy' as parent names as they are unlikely to exist and
601+
# don't end up being imported.
602+
modules = {"xxx.tests.foo": ModuleType("xxx.tests.foo")}
603+
insert_missing_modules(modules, "xxx.tests.foo")
604+
assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"]
605+
assert modules["xxx"].tests == modules["xxx.tests"]
606+
assert modules["xxx.tests"].foo == modules["xxx.tests.foo"]

0 commit comments

Comments
 (0)