Fix PytestPluginManager._is_in_confcutdir on Windows
On Windows two paths might be in different drives, so if a path is not one of the parents of the confcutdir, it does not necessarily mean it is inside the confcutdir either. Use `Path.is_relative_to` instead which directly answers that question for us. The previous implementation could cause pytest to inspect all the parent paths of a path from one drive if pytest was invoked from another drive. Moved the implementation to a function because it would be too convoluted to test the `PytestPluginManager._is_in_confcutdir` method directly.
This commit is contained in:
parent
5f241f388b
commit
f829a1ef06
|
@ -580,11 +580,9 @@ class PytestPluginManager(PluginManager):
|
|||
def _is_in_confcutdir(self, path: Path) -> bool:
|
||||
"""Whether a path is within the confcutdir.
|
||||
|
||||
When false, should not load conftest.
|
||||
When false, should not load conftest or recurse into path for collection.
|
||||
"""
|
||||
if self._confcutdir is None:
|
||||
return True
|
||||
return path not in self._confcutdir.parents
|
||||
return path_within_confcutdir(path=path, confcutdir=self._confcutdir)
|
||||
|
||||
def _try_load_conftest(
|
||||
self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path
|
||||
|
@ -609,9 +607,6 @@ class PytestPluginManager(PluginManager):
|
|||
if directory in self._dirpath2confmods:
|
||||
return
|
||||
|
||||
# XXX these days we may rather want to use config.rootpath
|
||||
# and allow users to opt into looking into the rootdir parent
|
||||
# directories instead of requiring to specify confcutdir.
|
||||
clist = []
|
||||
for parent in reversed((directory, *directory.parents)):
|
||||
if self._is_in_confcutdir(parent):
|
||||
|
@ -1908,3 +1903,10 @@ def apply_warning_filters(
|
|||
|
||||
for arg in cmdline_filters:
|
||||
warnings.filterwarnings(*parse_warning_filter(arg, escape=True))
|
||||
|
||||
|
||||
def path_within_confcutdir(*, path: Path, confcutdir: Optional[Path]) -> bool:
|
||||
# Extracted into a function for unit-testing.
|
||||
if confcutdir is None:
|
||||
return True
|
||||
return path.is_relative_to(confcutdir)
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import types
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.config import path_within_confcutdir
|
||||
from _pytest.config import PytestPluginManager
|
||||
from _pytest.config.exceptions import UsageError
|
||||
from _pytest.main import Session
|
||||
|
@ -404,7 +407,7 @@ class TestPytestPluginManager:
|
|||
pytestpm.consider_conftest(mod, registration_name="unused")
|
||||
|
||||
|
||||
class TestPytestPluginManagerBootstrapming:
|
||||
class TestPytestPluginManagerBootstrapping:
|
||||
def test_preparse_args(self, pytestpm: PytestPluginManager) -> None:
|
||||
pytest.raises(
|
||||
ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"])
|
||||
|
@ -464,3 +467,53 @@ class TestPytestPluginManagerBootstrapming:
|
|||
assert pytestpm.has_plugin("abc")
|
||||
assert not pytestpm.is_blocked("abc")
|
||||
assert not pytestpm.is_blocked("pytest_abc")
|
||||
|
||||
|
||||
skip_if_win = pytest.mark.skipif(
|
||||
not sys.platform.startswith("win"), reason="Windows only"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path, confcutdir, expected",
|
||||
[
|
||||
(Path("/projects/app/tests"), Path("/projects/app"), True),
|
||||
(Path("/projects/app"), Path("/projects/app"), True),
|
||||
(Path("/projects"), Path("/projects/app"), False),
|
||||
(Path("/"), Path("/projects/app"), False),
|
||||
pytest.param(
|
||||
Path("e:/projects/app/tests"),
|
||||
Path("e:/projects/app"),
|
||||
True,
|
||||
marks=skip_if_win,
|
||||
),
|
||||
pytest.param(
|
||||
Path("e:/projects/app"),
|
||||
Path("e:/projects/app"),
|
||||
True,
|
||||
marks=skip_if_win,
|
||||
),
|
||||
pytest.param(
|
||||
Path("e:/"),
|
||||
Path("e:/projects/app"),
|
||||
False,
|
||||
marks=skip_if_win,
|
||||
),
|
||||
pytest.param(
|
||||
Path("c:/testing"),
|
||||
Path("e:/projects/app"),
|
||||
False,
|
||||
marks=skip_if_win,
|
||||
),
|
||||
pytest.param(
|
||||
Path("c:/projects/app"),
|
||||
Path("e:/projects/app"),
|
||||
False,
|
||||
marks=skip_if_win,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_path_within_confcutdir(
|
||||
path: Path, confcutdir: Optional[Path], expected: bool
|
||||
) -> None:
|
||||
assert path_within_confcutdir(path=path, confcutdir=confcutdir) == expected
|
||||
|
|
Loading…
Reference in New Issue