Skip to content

Commit

Permalink
fix AttributeError crash when using --import-mode=importlib (#13029
Browse files Browse the repository at this point in the history
…) (#13037)

Only parent modules with the `__path__` attribute can be used by the `find_spec` function, and most of the standard library does not meet this condition.

Fixes #13026 .

(cherry picked from commit 8cff128)

Co-authored-by: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com>
  • Loading branch information
patchback[bot] and dongfangtianyu authored Dec 7, 2024
1 parent ade10c1 commit 179b690
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog/13026.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library.
5 changes: 4 additions & 1 deletion src/_pytest/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,10 @@ def _import_module_using_spec(
parent_module: ModuleType | None = None
if parent_module_name:
parent_module = sys.modules.get(parent_module_name)
if parent_module is None:
# If the parent_module lacks the `__path__` attribute, AttributeError when finding a submodule's spec,
# requiring re-import according to the path.
need_reimport = not hasattr(parent_module, "__path__")
if parent_module is None or need_reimport:
# Get parent_location based on location, get parent_path based on path.
if module_path.name == "__init__.py":
# If the current module is in a package,
Expand Down
31 changes: 31 additions & 0 deletions testing/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,37 @@ def test_my_test():
result = pytester.runpytest("--import-mode=importlib")
result.stdout.fnmatch_lines("* 1 passed *")

@pytest.mark.parametrize("name", ["code", "time", "math"])
def test_importlib_same_name_as_stl(
self, pytester, ns_param: bool, tmp_path: Path, name: str
):
"""Import a namespace package with the same name as the standard library (#13026)."""
file_path = pytester.path / f"{name}/foo/test_demo.py"
file_path.parent.mkdir(parents=True)
file_path.write_text(
dedent(
"""
def test_demo():
pass
"""
),
encoding="utf-8",
)

# unit test
__import__(name) # import standard library

import_path( # import user files
file_path,
mode=ImportMode.importlib,
root=pytester.path,
consider_namespace_packages=ns_param,
)

# E2E test
result = pytester.runpytest("--import-mode=importlib")
result.stdout.fnmatch_lines("* 1 passed *")

def create_installed_doctests_and_tests_dir(
self, path: Path, monkeypatch: MonkeyPatch
) -> tuple[Path, Path, Path]:
Expand Down

0 comments on commit 179b690

Please sign in to comment.