Skip to content

Commit 4032fd1

Browse files
committed
Fix issue where working dir becomes wrong on symlinks. Fixes #5965
This addresses subst drive on Windows and symlinks on Linux.
1 parent dbae5a7 commit 4032fd1

File tree

5 files changed

+83
-5
lines changed

5 files changed

+83
-5
lines changed

changelog/5965.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
No longer resolve symlinks so that the current directory remains correct with drives mapped with subst on Windows or symlinks on Linux.

src/_pytest/config/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def get_config(args=None, plugins=None):
208208
config = Config(
209209
pluginmanager,
210210
invocation_params=Config.InvocationParams(
211-
args=args or (), plugins=plugins, dir=Path().resolve()
211+
args=args or (), plugins=plugins, dir=Path.cwd()
212212
),
213213
)
214214

@@ -462,7 +462,7 @@ def _getconftestmodules(self, path):
462462
# and allow users to opt into looking into the rootdir parent
463463
# directories instead of requiring to specify confcutdir
464464
clist = []
465-
for parent in directory.realpath().parts():
465+
for parent in directory.parts():
466466
if self._confcutdir and self._confcutdir.relto(parent):
467467
continue
468468
conftestpath = parent.join("conftest.py")
@@ -771,7 +771,7 @@ def __init__(self, pluginmanager, *, invocation_params=None) -> None:
771771

772772
if invocation_params is None:
773773
invocation_params = self.InvocationParams(
774-
args=(), plugins=None, dir=Path().resolve()
774+
args=(), plugins=None, dir=Path.cwd()
775775
)
776776

777777
self.option = argparse.Namespace()

src/_pytest/fixtures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1288,7 +1288,7 @@ def getfixtureinfo(self, node, func, cls, funcargs=True):
12881288
def pytest_plugin_registered(self, plugin):
12891289
nodeid = None
12901290
try:
1291-
p = py.path.local(plugin.__file__).realpath()
1291+
p = py.path.local(plugin.__file__)
12921292
except AttributeError:
12931293
pass
12941294
else:

src/_pytest/main.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,6 @@ def _parsearg(self, arg):
642642
"file or package not found: " + arg + " (missing __init__.py?)"
643643
)
644644
raise UsageError("file not found: " + arg)
645-
fspath = fspath.realpath()
646645
return (fspath, parts)
647646

648647
def matchnodes(self, matching, names):

testing/test_link_resolve.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from contextlib import contextmanager
2+
import os.path
3+
import subprocess
4+
from string import ascii_lowercase
5+
import sys
6+
import textwrap
7+
8+
import py.path
9+
from _pytest import pytester
10+
11+
12+
@contextmanager
13+
def subst_path_windows(filename):
14+
for c in ascii_lowercase[7:]: # Create a subst drive from H-Z.
15+
c += ":"
16+
if not os.path.exists(c):
17+
drive = c
18+
break
19+
else:
20+
raise AssertionError("Unable to find suitable drive letter for subst.")
21+
22+
directory = os.path.dirname(filename)
23+
basename = os.path.basename(filename)
24+
25+
args = ["subst", drive, directory]
26+
subprocess.check_call(args)
27+
assert os.path.exists(drive)
28+
try:
29+
filename = py.path.local(drive) / basename
30+
yield filename
31+
finally:
32+
args = ["subst", "/D", drive]
33+
subprocess.check_call(args)
34+
35+
36+
@contextmanager
37+
def subst_path_linux(filename):
38+
directory = os.path.dirname(filename)
39+
basename = os.path.basename(filename)
40+
41+
target = py.path.local(directory) / ".." / "sub2"
42+
os.symlink(directory, target, target_is_directory=True)
43+
try:
44+
filename = target / basename
45+
yield filename
46+
finally:
47+
# We don't need to unlink (it's all in the tempdir).
48+
pass
49+
50+
51+
def test_link_resolve(testdir: pytester.Testdir) -> None:
52+
"""
53+
See: https://github.com/pytest-dev/pytest/issues/5965
54+
"""
55+
sub1 = testdir.mkpydir("sub1")
56+
p = sub1.join("test_foo.py")
57+
p.write(
58+
textwrap.dedent(
59+
"""
60+
import pytest
61+
def test_foo():
62+
raise AssertionError()
63+
"""
64+
)
65+
)
66+
67+
subst = subst_path_linux
68+
if sys.platform == "win32":
69+
subst = subst_path_windows
70+
71+
with subst(p) as subst_p:
72+
result = testdir.runpytest(subst_p, "-v")
73+
# i.e.: Make sure that the error is reported as a relative path, not as a
74+
# resolved path.
75+
# See: https://github.com/pytest-dev/pytest/issues/5965
76+
stdout = result.stdout.str()
77+
assert str(p) not in stdout
78+
assert str(subst_p) in stdout

0 commit comments

Comments
 (0)