Skip to content

Commit

Permalink
Fix issue where working dir becomes wrong on symlinks. Fixes #5965
Browse files Browse the repository at this point in the history
This addresses subst drive on Windows and symlinks on Linux.
  • Loading branch information
fabioz committed Feb 13, 2020
1 parent dbae5a7 commit 4032fd1
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog/5965.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No longer resolve symlinks so that the current directory remains correct with drives mapped with subst on Windows or symlinks on Linux.
6 changes: 3 additions & 3 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def get_config(args=None, plugins=None):
config = Config(
pluginmanager,
invocation_params=Config.InvocationParams(
args=args or (), plugins=plugins, dir=Path().resolve()
args=args or (), plugins=plugins, dir=Path.cwd()
),
)

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

if invocation_params is None:
invocation_params = self.InvocationParams(
args=(), plugins=None, dir=Path().resolve()
args=(), plugins=None, dir=Path.cwd()
)

self.option = argparse.Namespace()
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ def getfixtureinfo(self, node, func, cls, funcargs=True):
def pytest_plugin_registered(self, plugin):
nodeid = None
try:
p = py.path.local(plugin.__file__).realpath()
p = py.path.local(plugin.__file__)
except AttributeError:
pass
else:
Expand Down
1 change: 0 additions & 1 deletion src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,6 @@ def _parsearg(self, arg):
"file or package not found: " + arg + " (missing __init__.py?)"
)
raise UsageError("file not found: " + arg)
fspath = fspath.realpath()
return (fspath, parts)

def matchnodes(self, matching, names):
Expand Down
78 changes: 78 additions & 0 deletions testing/test_link_resolve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from contextlib import contextmanager
import os.path
import subprocess
from string import ascii_lowercase
import sys
import textwrap

import py.path
from _pytest import pytester


@contextmanager
def subst_path_windows(filename):
for c in ascii_lowercase[7:]: # Create a subst drive from H-Z.
c += ":"
if not os.path.exists(c):
drive = c
break
else:
raise AssertionError("Unable to find suitable drive letter for subst.")

directory = os.path.dirname(filename)
basename = os.path.basename(filename)

args = ["subst", drive, directory]
subprocess.check_call(args)
assert os.path.exists(drive)
try:
filename = py.path.local(drive) / basename
yield filename
finally:
args = ["subst", "/D", drive]
subprocess.check_call(args)


@contextmanager
def subst_path_linux(filename):
directory = os.path.dirname(filename)
basename = os.path.basename(filename)

target = py.path.local(directory) / ".." / "sub2"
os.symlink(directory, target, target_is_directory=True)
try:
filename = target / basename
yield filename
finally:
# We don't need to unlink (it's all in the tempdir).
pass


def test_link_resolve(testdir: pytester.Testdir) -> None:
"""
See: https://github.com/pytest-dev/pytest/issues/5965
"""
sub1 = testdir.mkpydir("sub1")
p = sub1.join("test_foo.py")
p.write(
textwrap.dedent(
"""
import pytest
def test_foo():
raise AssertionError()
"""
)
)

subst = subst_path_linux
if sys.platform == "win32":
subst = subst_path_windows

with subst(p) as subst_p:
result = testdir.runpytest(subst_p, "-v")
# i.e.: Make sure that the error is reported as a relative path, not as a
# resolved path.
# See: https://github.com/pytest-dev/pytest/issues/5965
stdout = result.stdout.str()
assert str(p) not in stdout
assert str(subst_p) in stdout

0 comments on commit 4032fd1

Please sign in to comment.