Skip to content

Commit

Permalink
Merge pull request #8123 from nicoddemus/import-mismatch-unc
Browse files Browse the repository at this point in the history
Compare also paths on Windows when considering ImportPathMismatchError
  • Loading branch information
nicoddemus committed Dec 13, 2020
1 parent c475106 commit f854cf6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
2 changes: 2 additions & 0 deletions changelog/7678.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed bug where ``ImportPathMismatchError`` would be raised for files compiled in
the host and loaded later from an UNC mounted path (Windows).
16 changes: 15 additions & 1 deletion src/_pytest/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ def import_path(
module_file = module_file[: -(len(os.path.sep + "__init__.py"))]

try:
is_same = os.path.samefile(str(path), module_file)
is_same = _is_same(str(path), module_file)
except FileNotFoundError:
is_same = False

Expand All @@ -553,6 +553,20 @@ def import_path(
return mod


# Implement a special _is_same function on Windows which returns True if the two filenames
# compare equal, to circumvent os.path.samefile returning False for mounts in UNC (#7678).
if sys.platform.startswith("win"):

def _is_same(f1: str, f2: str) -> bool:
return Path(f1) == Path(f2) or os.path.samefile(f1, f2)


else:

def _is_same(f1: str, f2: str) -> bool:
return os.path.samefile(f1, f2)


def resolve_package_path(path: Path) -> Optional[Path]:
"""Return the Python package path by looking for the last
directory upwards which still contains an __init__.py.
Expand Down
21 changes: 21 additions & 0 deletions testing/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import py

import pytest
from _pytest.monkeypatch import MonkeyPatch
from _pytest.pathlib import bestrelpath
from _pytest.pathlib import commonpath
from _pytest.pathlib import ensure_deletable
Expand Down Expand Up @@ -414,3 +415,23 @@ def test_visit_ignores_errors(tmpdir) -> None:
"bar",
"foo",
]


@pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows only")
def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> None:
"""
import_file() should not raise ImportPathMismatchError if the paths are exactly
equal on Windows. It seems directories mounted as UNC paths make os.path.samefile
return False, even when they are clearly equal.
"""
module_path = tmp_path.joinpath("my_module.py")
module_path.write_text("def foo(): return 42")
monkeypatch.syspath_prepend(tmp_path)

with monkeypatch.context() as mp:
# Forcibly make os.path.samefile() return False here to ensure we are comparing
# the paths too. Using a context to narrow the patch as much as possible given
# this is an important system function.
mp.setattr(os.path, "samefile", lambda x, y: False)
module = import_path(module_path)
assert getattr(module, "foo")() == 42

0 comments on commit f854cf6

Please sign in to comment.