diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 5d77fa983a7..3a0eca546a3 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -30,16 +30,13 @@ from _pytest.compat import importlib_metadata from _pytest.outcomes import fail from _pytest.outcomes import Skipped +from _pytest.pathlib import unique_path from _pytest.warning_types import PytestConfigWarning hookimpl = HookimplMarker("pytest") hookspec = HookspecMarker("pytest") -def _uniquepath(path): - return type(path)(os.path.normcase(str(path.realpath()))) - - class ConftestImportFailure(Exception): def __init__(self, path, excinfo): Exception.__init__(self, path, excinfo) @@ -370,7 +367,7 @@ def _set_initial_conftests(self, namespace): """ current = py.path.local() self._confcutdir = ( - _uniquepath(current.join(namespace.confcutdir, abs=True)) + unique_path(current.join(namespace.confcutdir, abs=True)) if namespace.confcutdir else None ) @@ -409,7 +406,7 @@ def _getconftestmodules(self, path): else: directory = path - directory = _uniquepath(directory) + directory = unique_path(directory) # XXX these days we may rather want to use config.rootdir # and allow users to opt into looking into the rootdir parent @@ -438,7 +435,7 @@ def _importconftest(self, conftestpath): # Use realpath to avoid loading the same conftest twice # with build systems that create build directories containing # symlinks to actual files. - conftestpath = _uniquepath(conftestpath) + conftestpath = unique_path(conftestpath) try: return self._conftestpath2mod[conftestpath] except KeyError: diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 19f9c062f89..0403b694737 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -11,6 +11,7 @@ from os.path import expanduser from os.path import expandvars from os.path import isabs +from os.path import normcase from os.path import sep from posixpath import sep as posix_sep @@ -334,3 +335,12 @@ def fnmatch_ex(pattern, path): def parts(s): parts = s.split(sep) return {sep.join(parts[: i + 1]) or sep for i in range(len(parts))} + + +def unique_path(path): + """Returns a unique path in case-insensitive (but case-preserving) file + systems such as Windows. + + This is needed only for ``py.path.local``; ``pathlib.Path`` handles this + natively with ``resolve()``.""" + return type(path)(normcase(str(path.realpath()))) diff --git a/testing/test_conftest.py b/testing/test_conftest.py index a9af649d000..9888f5457f3 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -4,9 +4,9 @@ import py import pytest -from _pytest.config import _uniquepath from _pytest.config import PytestPluginManager from _pytest.main import ExitCode +from _pytest.pathlib import unique_path def ConftestWithSetinitial(path): @@ -143,11 +143,11 @@ def test_conftestcutdir(testdir): # but we can still import a conftest directly conftest._importconftest(conf) values = conftest._getconftestmodules(conf.dirpath()) - assert values[0].__file__.startswith(str(_uniquepath(conf))) + assert values[0].__file__.startswith(str(unique_path(conf))) # and all sub paths get updated properly values = conftest._getconftestmodules(p) assert len(values) == 1 - assert values[0].__file__.startswith(str(_uniquepath(conf))) + assert values[0].__file__.startswith(str(unique_path(conf))) def test_conftestcutdir_inplace_considered(testdir): @@ -156,7 +156,7 @@ def test_conftestcutdir_inplace_considered(testdir): conftest_setinitial(conftest, [conf.dirpath()], confcutdir=conf.dirpath()) values = conftest._getconftestmodules(conf.dirpath()) assert len(values) == 1 - assert values[0].__file__.startswith(str(_uniquepath(conf))) + assert values[0].__file__.startswith(str(unique_path(conf))) @pytest.mark.parametrize("name", "test tests whatever .dotdir".split()) @@ -166,7 +166,7 @@ def test_setinitial_conftest_subdirs(testdir, name): conftest = PytestPluginManager() conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir) if name not in ("whatever", ".dotdir"): - assert _uniquepath(subconftest) in conftest._conftestpath2mod + assert unique_path(subconftest) in conftest._conftestpath2mod assert len(conftest._conftestpath2mod) == 1 else: assert subconftest not in conftest._conftestpath2mod