Skip to content

Commit

Permalink
Try to import module before creating dummy modules with 'importmode=i…
Browse files Browse the repository at this point in the history
…mportlib'

The dummy modules we introduce in `insert_missing_modules` (due to pytest-dev#7856 and pytest-dev#7859)
would cause problems if the dummy modules actually end up replacing modules
which could be imported normally because they are available in `PYTHONPATH`.

Now we attempt to first import the module via normal mechanisms, and only
introduce the dummy modules if the intermediary modules don't actually exist.

Close pytest-dev#9645
  • Loading branch information
nicoddemus committed Feb 14, 2022
1 parent c01a5c1 commit 747b837
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 12 deletions.
1 change: 1 addition & 0 deletions changelog/9645.bugfix.rst
@@ -0,0 +1 @@
Fixed regression where ``--import-mode=importlib`` used together with :envvar:`PYTHONPATH` or :confval:`pythonpath` would cause import errors in test suites.
19 changes: 14 additions & 5 deletions src/_pytest/pathlib.py
Expand Up @@ -603,11 +603,20 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) ->
module_parts = module_name.split(".")
while module_name:
if module_name not in modules:
module = ModuleType(
module_name,
doc="Empty module created by pytest's importmode=importlib.",
)
modules[module_name] = module
try:
# If sys.meta_path is empty, calling import_module will issue
# a warning and raise ModuleNotFoundError. To avoid the
# warning, we check sys.meta_path explicitly and raise the error
# ourselves to fall back to creating a dummy module.
if not sys.meta_path:
raise ModuleNotFoundError
importlib.import_module(module_name)
except ModuleNotFoundError:
module = ModuleType(
module_name,
doc="Empty module created by pytest's importmode=importlib.",
)
modules[module_name] = module
module_parts.pop(-1)
module_name = ".".join(module_parts)

Expand Down
29 changes: 29 additions & 0 deletions testing/test_collection.py
Expand Up @@ -1507,6 +1507,35 @@ def test_modules_not_importable_as_side_effect(self, pytester: Pytester) -> None
]
)

def test_using_python_path(self, pytester: Pytester) -> None:
"""
Dummy modules created by insert_missing_modules should not get in
the way of modules that could be imported via python path (#9645).
"""
pytester.makeini(
"""
[pytest]
pythonpath = .
addopts = --import-mode importlib
"""
)
pytester.makepyfile(
**{
"tests/__init__.py": "",
"tests/conftest.py": "",
"tests/subpath/__init__.py": "",
"tests/subpath/helper.py": "",
"tests/subpath/test_something.py": """
import tests.subpath.helper
def test_something():
assert True
""",
}
)
result = pytester.runpytest()
result.stdout.fnmatch_lines("*1 passed in*")


def test_does_not_crash_on_error_from_decorated_function(pytester: Pytester) -> None:
"""Regression test for an issue around bad exception formatting due to
Expand Down
19 changes: 12 additions & 7 deletions testing/test_pathlib.py
Expand Up @@ -562,15 +562,20 @@ def test_module_name_from_path(self, tmp_path: Path) -> None:
result = module_name_from_path(Path("/home/foo/test_foo.py"), Path("/bar"))
assert result == "home.foo.test_foo"

def test_insert_missing_modules(self) -> None:
modules = {"src.tests.foo": ModuleType("src.tests.foo")}
insert_missing_modules(modules, "src.tests.foo")
assert sorted(modules) == ["src", "src.tests", "src.tests.foo"]
def test_insert_missing_modules(
self, monkeypatch: MonkeyPatch, tmp_path: Path
) -> None:
monkeypatch.chdir(tmp_path)
# Use 'xxx' and 'xxy' as parent names as they are unlikely to exist and
# don't end up being imported.
modules = {"xxx.tests.foo": ModuleType("xxx.tests.foo")}
insert_missing_modules(modules, "xxx.tests.foo")
assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"]

mod = ModuleType("mod", doc="My Module")
modules = {"src": mod}
insert_missing_modules(modules, "src")
assert modules == {"src": mod}
modules = {"xxy": mod}
insert_missing_modules(modules, "xxy")
assert modules == {"xxy": mod}

modules = {}
insert_missing_modules(modules, "")
Expand Down

0 comments on commit 747b837

Please sign in to comment.