Fix assertion rewriter crash if cwd changes mid-testing

Unfortunately we need to get a `py.path.local` object to perform the fnmatch
operation, it is different from the standard `fnmatch` module because it
implements its own custom logic. So we need to use `py.path` to perform
the fnmatch for backward compatibility reasons.

Ideally we should be able to use a "pure path" in `pathlib` terms (a path
not bound to the file system), but we don't have those in pylib.

Fix #3973
This commit is contained in:
Bruno Oliveira 2018-09-13 18:50:05 -03:00
parent bb57186dd4
commit 1df6d28080
3 changed files with 30 additions and 1 deletions

View File

@ -0,0 +1 @@
Fix crash of the assertion rewriter if a test changed the current working directory without restoring it afterwards.

View File

@ -199,7 +199,11 @@ class AssertionRewritingHook(object):
# For matching the name it must be as if it was a filename. # For matching the name it must be as if it was a filename.
parts[-1] = parts[-1] + ".py" parts[-1] = parts[-1] + ".py"
fn_pypath = py.path.local(os.path.sep.join(parts)) try:
fn_pypath = py.path.local(os.path.sep.join(parts))
except EnvironmentError:
return False
for pat in self.fnpats: for pat in self.fnpats:
# if the pattern contains subdirectories ("tests/**.py" for example) we can't bail out based # if the pattern contains subdirectories ("tests/**.py" for example) we can't bail out based
# on the name alone because we need to match against the full path # on the name alone because we need to match against the full path

View File

@ -1232,3 +1232,27 @@ class TestEarlyRewriteBailout(object):
hook.fnpats[:] = ["tests/**.py"] hook.fnpats[:] = ["tests/**.py"]
assert hook.find_module("file") is not None assert hook.find_module("file") is not None
assert self.find_module_calls == ["file"] assert self.find_module_calls == ["file"]
@pytest.mark.skipif(
sys.platform.startswith("win32"), reason="cannot remove cwd on Windows"
)
def test_cwd_changed(self, testdir):
testdir.makepyfile(
**{
"test_bar.py": """
import os
import shutil
import tempfile
d = tempfile.mkdtemp()
os.chdir(d)
shutil.rmtree(d)
""",
"test_foo.py": """
def test():
pass
""",
}
)
result = testdir.runpytest()
result.stdout.fnmatch_lines("* 1 passed in *")