diff --git a/changelog/3771.bugfix.rst b/changelog/3771.bugfix.rst new file mode 100644 index 000000000..09c953aa2 --- /dev/null +++ b/changelog/3771.bugfix.rst @@ -0,0 +1 @@ +Fix infinite recursion during collection if a ``pytest_ignore_collect`` returns ``False`` instead of ``None``. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 5b8305e77..2657bff63 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -561,7 +561,7 @@ class Package(Module): def _recurse(self, path): ihook = self.gethookproxy(path.dirpath()) if ihook.pytest_ignore_collect(path=path, config=self.config): - return + return False for pat in self._norecursepatterns: if path.check(fnmatch=pat): return False @@ -594,9 +594,12 @@ class Package(Module): return path in self.session._initialpaths def collect(self): - path = self.fspath.dirpath() + this_path = self.fspath.dirpath() pkg_prefix = None - for path in path.visit(fil=lambda x: 1, 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 + if path.basename == "__init__.py" and path.dirpath() == this_path: + continue if pkg_prefix and pkg_prefix in path.parts(): continue for x in self._collectfile(path): diff --git a/testing/example_scripts/collect/package_infinite_recursion/conftest.py b/testing/example_scripts/collect/package_infinite_recursion/conftest.py new file mode 100644 index 000000000..9629fa646 --- /dev/null +++ b/testing/example_scripts/collect/package_infinite_recursion/conftest.py @@ -0,0 +1,2 @@ +def pytest_ignore_collect(path): + return False diff --git a/testing/example_scripts/collect/package_infinite_recursion/tests/__init__.py b/testing/example_scripts/collect/package_infinite_recursion/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py b/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py new file mode 100644 index 000000000..f17482385 --- /dev/null +++ b/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py @@ -0,0 +1,2 @@ +def test(): + pass diff --git a/testing/python/collect.py b/testing/python/collect.py index a76cecada..907b368eb 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1577,3 +1577,9 @@ def test_keep_duplicates(testdir): ) result = testdir.runpytest("--keep-duplicates", a.strpath, a.strpath) result.stdout.fnmatch_lines(["*collected 2 item*"]) + + +def test_package_collection_infinite_recursion(testdir): + testdir.copy_example("collect/package_infinite_recursion") + result = testdir.runpytest() + result.stdout.fnmatch_lines("*1 passed*")