collect: python: fix `AssertionError` with broken symlinks
Fixes https://github.com/pytest-dev/pytest/issues/4782.
This commit is contained in:
parent
8726be27a6
commit
407d4a0cf0
|
@ -0,0 +1 @@
|
||||||
|
Fix ``AssertionError`` with collection of broken symlinks with packages.
|
|
@ -597,7 +597,12 @@ class Session(nodes.FSCollector):
|
||||||
yield y
|
yield y
|
||||||
|
|
||||||
def _collectfile(self, path, handle_dupes=True):
|
def _collectfile(self, path, handle_dupes=True):
|
||||||
assert path.isfile()
|
assert path.isfile(), "%r is not a file (isdir=%r, exists=%r, islink=%r)" % (
|
||||||
|
path,
|
||||||
|
path.isdir(),
|
||||||
|
path.exists(),
|
||||||
|
path.islink(),
|
||||||
|
)
|
||||||
ihook = self.gethookproxy(path)
|
ihook = self.gethookproxy(path)
|
||||||
if not self.isinitpath(path):
|
if not self.isinitpath(path):
|
||||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||||
|
|
|
@ -599,7 +599,12 @@ class Package(Module):
|
||||||
return proxy
|
return proxy
|
||||||
|
|
||||||
def _collectfile(self, path, handle_dupes=True):
|
def _collectfile(self, path, handle_dupes=True):
|
||||||
assert path.isfile()
|
assert path.isfile(), "%r is not a file (isdir=%r, exists=%r, islink=%r)" % (
|
||||||
|
path,
|
||||||
|
path.isdir(),
|
||||||
|
path.exists(),
|
||||||
|
path.islink(),
|
||||||
|
)
|
||||||
ihook = self.gethookproxy(path)
|
ihook = self.gethookproxy(path)
|
||||||
if not self.isinitpath(path):
|
if not self.isinitpath(path):
|
||||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||||
|
@ -632,7 +637,8 @@ class Package(Module):
|
||||||
pkg_prefixes = set()
|
pkg_prefixes = set()
|
||||||
for path in this_path.visit(rec=self._recurse, bf=True, sort=True):
|
for path in this_path.visit(rec=self._recurse, bf=True, sort=True):
|
||||||
# We will visit our own __init__.py file, in which case we skip it.
|
# We will visit our own __init__.py file, in which case we skip it.
|
||||||
if path.isfile():
|
is_file = path.isfile()
|
||||||
|
if is_file:
|
||||||
if path.basename == "__init__.py" and path.dirpath() == this_path:
|
if path.basename == "__init__.py" and path.dirpath() == this_path:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -643,12 +649,14 @@ class Package(Module):
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if path.isdir():
|
if is_file:
|
||||||
if path.join("__init__.py").check(file=1):
|
|
||||||
pkg_prefixes.add(path)
|
|
||||||
else:
|
|
||||||
for x in self._collectfile(path):
|
for x in self._collectfile(path):
|
||||||
yield x
|
yield x
|
||||||
|
elif not path.isdir():
|
||||||
|
# Broken symlink or invalid/missing file.
|
||||||
|
continue
|
||||||
|
elif path.join("__init__.py").check(file=1):
|
||||||
|
pkg_prefixes.add(path)
|
||||||
|
|
||||||
|
|
||||||
def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):
|
def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):
|
||||||
|
|
|
@ -1186,3 +1186,30 @@ def test_collect_pkg_init_and_file_in_args(testdir):
|
||||||
"*2 passed in*",
|
"*2 passed in*",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
not hasattr(py.path.local, "mksymlinkto"),
|
||||||
|
reason="symlink not available on this platform",
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize("use_pkg", (True, False))
|
||||||
|
def test_collect_sub_with_symlinks(use_pkg, testdir):
|
||||||
|
sub = testdir.mkdir("sub")
|
||||||
|
if use_pkg:
|
||||||
|
sub.ensure("__init__.py")
|
||||||
|
sub.ensure("test_file.py").write("def test_file(): pass")
|
||||||
|
|
||||||
|
# Create a broken symlink.
|
||||||
|
sub.join("test_broken.py").mksymlinkto("test_doesnotexist.py")
|
||||||
|
|
||||||
|
# Symlink that gets collected.
|
||||||
|
sub.join("test_symlink.py").mksymlinkto("test_file.py")
|
||||||
|
|
||||||
|
result = testdir.runpytest("-v", str(sub))
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"sub/test_file.py::test_file PASSED*",
|
||||||
|
"sub/test_symlink.py::test_file PASSED*",
|
||||||
|
"*2 passed in*",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue