From e2acc1a99b4e7d0942d7a9de57a7490ac9a3978d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 10 Sep 2023 09:57:40 -0300 Subject: [PATCH] Fix --import-mode=importlib when root contains `__init__.py` file (#11420) We cannot have an empty module name when importing a `__init__.py` file that is at the rootdir. Fixes #11417 --- src/_pytest/pathlib.py | 5 +++-- testing/test_pathlib.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 68372f67c..e39b3dc8e 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -623,8 +623,9 @@ def module_name_from_path(path: Path, root: Path) -> str: # Use the parts for the relative path to the root path. path_parts = relative_path.parts - # Module name for packages do not contain the __init__ file. - if path_parts[-1] == "__init__": + # Module name for packages do not contain the __init__ file, unless + # the `__init__.py` file is at the root. + if len(path_parts) >= 2 and path_parts[-1] == "__init__": path_parts = path_parts[:-1] return ".".join(path_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 50c1d5967..2c5432cef 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -28,6 +28,7 @@ from _pytest.pathlib import resolve_package_path from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit +from _pytest.pytester import Pytester from _pytest.tmpdir import TempPathFactory @@ -592,6 +593,10 @@ class TestImportLibMode: result = module_name_from_path(tmp_path / "src/app/__init__.py", tmp_path) assert result == "src.app" + # Unless __init__.py file is at the root, in which case we cannot have an empty module name. + result = module_name_from_path(tmp_path / "__init__.py", tmp_path) + assert result == "__init__" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -663,6 +668,22 @@ class TestImportLibMode: mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) assert len(mod.instance.INSTANCES) == 1 + def test_importlib_root_is_package(self, pytester: Pytester) -> None: + """ + Regression for importing a `__init__`.py file that is at the root + (#11417). + """ + pytester.makepyfile(__init__="") + pytester.makepyfile( + """ + def test_my_test(): + assert True + """ + ) + + result = pytester.runpytest("--import-mode=importlib") + result.stdout.fnmatch_lines("* 1 passed *") + def test_safe_exists(tmp_path: Path) -> None: d = tmp_path.joinpath("some_dir")