diff --git a/changelog/4425.bugfix.rst b/changelog/4425.bugfix.rst new file mode 100644 index 00000000000..7c869cd4c8a --- /dev/null +++ b/changelog/4425.bugfix.rst @@ -0,0 +1 @@ +Ensure we resolve the absolute path when the given ``--basetemp`` is a relative path. diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index d536b7746ab..2c81de177a5 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -13,8 +13,9 @@ import pytest from _pytest.fixtures import fixture +from _pytest.pathlib import Path -RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$") +RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$") @fixture @@ -267,6 +268,9 @@ def chdir(self, path): self._cwd = os.getcwd() if hasattr(path, "chdir"): path.chdir() + elif isinstance(path, Path): + # modern python uses the fspath protocol here LEGACY + os.chdir(str(path)) else: os.chdir(path) diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 6287c170515..860c2d4af06 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -10,6 +10,7 @@ import attr import py +import six import pytest from .pathlib import ensure_reset_dir @@ -26,7 +27,14 @@ class TempPathFactory(object): The base directory can be configured using the ``--basetemp`` option.""" - _given_basetemp = attr.ib() + _given_basetemp = attr.ib( + # using os.path.abspath() to get absolute path instead of resolve() as it + # does not work the same in all platforms (see #4427) + # Path.absolute() exists, but it is not public (see https://bugs.python.org/issue25012) + convert=attr.converters.optional( + lambda p: Path(os.path.abspath(six.text_type(p))) + ) + ) _trace = attr.ib() _basetemp = attr.ib(default=None) @@ -53,7 +61,7 @@ def getbasetemp(self): """ return base temporary directory. """ if self._basetemp is None: if self._given_basetemp is not None: - basetemp = Path(self._given_basetemp) + basetemp = self._given_basetemp ensure_reset_dir(basetemp) else: from_env = os.environ.get("PYTEST_DEBUG_TEMPROOT") diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 38b0672b706..6040d9444e5 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -4,6 +4,7 @@ import sys +import attr import six import pytest @@ -25,12 +26,29 @@ def test_ensuretemp(recwarn): assert d1.check(dir=1) +@attr.s +class FakeConfig(object): + basetemp = attr.ib() + trace = attr.ib(default=None) + + @property + def trace(self): + return self + + def get(self, key): + return lambda *k: None + + @property + def option(self): + return self + + class TestTempdirHandler(object): - def test_mktemp(self, testdir): + def test_mktemp(self, tmp_path): + from _pytest.tmpdir import TempdirFactory, TempPathFactory - config = testdir.parseconfig() - config.option.basetemp = testdir.mkdir("hello") + config = FakeConfig(tmp_path) t = TempdirFactory(TempPathFactory.from_config(config)) tmp = t.mktemp("world") assert tmp.relto(t.getbasetemp()) == "world0" @@ -40,6 +58,15 @@ def test_mktemp(self, testdir): assert tmp2.relto(t.getbasetemp()).startswith("this") assert tmp2 != tmp + @pytest.mark.issue(4425) + def test_tmppath_relative_basetemp_absolute(self, tmp_path, monkeypatch): + from _pytest.tmpdir import TempPathFactory + + monkeypatch.chdir(tmp_path) + config = FakeConfig("hello") + t = TempPathFactory.from_config(config) + assert t.getbasetemp().resolve() == (tmp_path / "hello").resolve() + class TestConfigTmpdir(object): def test_getbasetemp_custom_removes_old(self, testdir):