Skip to content

Commit

Permalink
Fix: Using --import-mode=importlib, a directory with the same name …
Browse files Browse the repository at this point in the history
…in the namespace package causes a KeyError.(pytest-dev#12592
  • Loading branch information
dongfangtianyu committed Aug 30, 2024
1 parent 419bc7a commit 098e5a6
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog/12592.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed the issue of causes ``KeyError`` when using the parameter ``--import-mode=importlib`` in pytest>=8.2 .
17 changes: 9 additions & 8 deletions src/_pytest/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,15 @@ def _import_module_using_spec(

if spec_matches_module_path(spec, module_path):
assert spec is not None

# Find spec and import this module.
mod = importlib.util.module_from_spec(spec)
sys.modules[module_name] = mod
spec.loader.exec_module(mod) # type: ignore[union-attr]

if insert_modules:
insert_missing_modules(sys.modules, module_name)

# Attempt to import the parent module, seems is our responsibility:
# https://github.com/python/cpython/blob/73906d5c908c1e0b73c5436faeff7d93698fc074/Lib/importlib/_bootstrap.py#L1308-L1311
parent_module_name, _, name = module_name.rpartition(".")
Expand All @@ -655,17 +664,9 @@ def _import_module_using_spec(
insert_modules=insert_modules,
)

# Find spec and import this module.
mod = importlib.util.module_from_spec(spec)
sys.modules[module_name] = mod
spec.loader.exec_module(mod) # type: ignore[union-attr]

# Set this module as an attribute of the parent module (#12194).
if parent_module is not None:
setattr(parent_module, name, mod)

if insert_modules:
insert_missing_modules(sys.modules, module_name)
return mod

return None
Expand Down
38 changes: 38 additions & 0 deletions testing/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,44 @@ def test_full_ns_packages_without_init_files(
tmp_path / "src/dist2/ns/a/core/foo/m.py", consider_namespace_packages=True
) == (tmp_path / "src/dist2", "ns.a.core.foo.m")

def test_ns_multiple_levels_import_same_name_directory(
self,
tmp_path: Path,
monkeypatch: MonkeyPatch,
pytester: Pytester,
) -> None:
"""Check KeyError with `--import-mode=importlib` (#12592)."""
self.setup_directories(tmp_path, monkeypatch, pytester)
code = dedent("""
def test():
assert "four lights" == "five lights"
""")

# a subdirectories with the same name in the namespace package,
# along with a tests file
test_base_path = tmp_path / "src/dist2/com/company"
test_py = test_base_path / "a/b/c/test_demo.py"
test_dir = test_base_path / "a/b/c/c"

test_dir.mkdir(parents=True)
test_py.write_text(code, encoding="UTF-8")

pkg_root, module_name = resolve_pkg_root_and_module_name(
test_py, consider_namespace_packages=True
)
assert (pkg_root, module_name) == (
tmp_path / "src/dist2",
"com.company.a.b.c.test_demo",
)

result = pytester.runpytest("--import-mode=importlib", test_py)

result.stdout.no_fnmatch_line(
"E KeyError: 'test_ns_multiple_levels_import1.src.dist2.com.company.a.b'"
)

assert "KeyError" not in result.stdout.str()


def test_is_importable(pytester: Pytester) -> None:
pytester.syspathinsert()
Expand Down

0 comments on commit 098e5a6

Please sign in to comment.