|
| 1 | +import os.path |
| 2 | +import subprocess |
| 3 | +import sys |
| 4 | +from string import ascii_lowercase |
| 5 | + |
| 6 | +from py._path.local import LocalPath |
| 7 | + |
| 8 | +import pytest |
| 9 | +from _pytest import pytester |
| 10 | +from _pytest.fixtures import FixtureRequest |
| 11 | + |
| 12 | + |
| 13 | +class _SubstTmpdirFactory: |
| 14 | + """ |
| 15 | + A temp dir factory which may do a subst on Windows drives. |
| 16 | + """ |
| 17 | + |
| 18 | + def __init__(self, tmpdir, tmpdir_factory, subst): |
| 19 | + self.tmpdir = tmpdir |
| 20 | + self.tmpdir_factory = tmpdir_factory |
| 21 | + self.subst = subst |
| 22 | + self.subst_drives = {} |
| 23 | + |
| 24 | + def _subst_path(self, filename): |
| 25 | + |
| 26 | + if self.subst: |
| 27 | + for c in ascii_lowercase[7:]: # Create a subst drive from H-Z. |
| 28 | + c += ":" |
| 29 | + if not os.path.exists(c): |
| 30 | + drive = c |
| 31 | + break |
| 32 | + else: |
| 33 | + raise AssertionError("Unable to find suitable drive letter for subst.") |
| 34 | + |
| 35 | + directory = os.path.dirname(filename) |
| 36 | + basename = os.path.basename(filename) |
| 37 | + |
| 38 | + args = ["subst", drive, directory] |
| 39 | + subprocess.check_call(args) |
| 40 | + assert os.path.exists(drive) |
| 41 | + self.subst_drives[drive] = directory |
| 42 | + |
| 43 | + filename = LocalPath(os.path.join(drive, basename)) |
| 44 | + |
| 45 | + return filename |
| 46 | + |
| 47 | + def mktemp(self, name, numbered): |
| 48 | + filename = self.tmpdir_factory.mktemp(name, numbered=numbered) |
| 49 | + filename = self._subst_path(filename) |
| 50 | + return filename |
| 51 | + |
| 52 | + def unsubst(self): |
| 53 | + for drive in self.subst_drives: |
| 54 | + args = ["subst", "/D", drive] |
| 55 | + subprocess.check_call(args) |
| 56 | + |
| 57 | + |
| 58 | +@pytest.fixture(params=[{"subst": True}, {"subst": False}]) |
| 59 | +def _subst_tmpdir_factory(request: FixtureRequest, tmpdir, tmpdir_factory): |
| 60 | + if sys.platform != "win32": |
| 61 | + pytest.skip("Windows only test.") |
| 62 | + factory = _SubstTmpdirFactory(tmpdir, tmpdir_factory, **request.param) |
| 63 | + yield factory |
| 64 | + factory.unsubst() |
| 65 | + |
| 66 | + |
| 67 | +@pytest.fixture |
| 68 | +def _custom_testdir( |
| 69 | + request: FixtureRequest, _subst_tmpdir_factory |
| 70 | +) -> "pytester.Testdir": |
| 71 | + return pytester.Testdir(request, _subst_tmpdir_factory) |
| 72 | + |
| 73 | + |
| 74 | +def test_windows_subst_resolve(_custom_testdir, _subst_tmpdir_factory) -> None: |
| 75 | + """ |
| 76 | + Check that when we have a subst on Windows the errors reported are not |
| 77 | + in the subst target. |
| 78 | + See: https://github.com/pytest-dev/pytest/issues/5965 |
| 79 | + """ |
| 80 | + testdir = _custom_testdir |
| 81 | + testdir.makepyfile( |
| 82 | + """ |
| 83 | + import pytest |
| 84 | + def test_foo(): |
| 85 | + raise AssertionError() |
| 86 | + """ |
| 87 | + ) |
| 88 | + result = testdir.runpytest() |
| 89 | + |
| 90 | + # i.e.: Make sure that the error is reported as a relative path, not as an |
| 91 | + # absolute (resolved) path. |
| 92 | + # See: https://github.com/pytest-dev/pytest/issues/5965 |
| 93 | + for _drive, directory in _subst_tmpdir_factory.subst_drives.items(): |
| 94 | + for line in result.stdout.lines: |
| 95 | + assert directory.lower() not in line.lower() |
0 commit comments