diff --git a/changelog/3749.bugfix.rst b/changelog/3749.bugfix.rst new file mode 100644 index 000000000..395ff12f5 --- /dev/null +++ b/changelog/3749.bugfix.rst @@ -0,0 +1,3 @@ +Fix the following error during collection of tests inside packages:: + + TypeError: object of type 'Package' has no len() diff --git a/src/_pytest/main.py b/src/_pytest/main.py index f5078b9e7..ce07285a4 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -504,13 +504,14 @@ class Session(nodes.FSCollector): pkginit = parent.join("__init__.py") if pkginit.isfile(): if pkginit in self._node_cache: - root = self._node_cache[pkginit] + root = self._node_cache[pkginit][0] else: col = root._collectfile(pkginit) if col: if isinstance(col[0], Package): root = col[0] - self._node_cache[root.fspath] = root + # always store a list in the cache, matchnodes expects it + self._node_cache[root.fspath] = [root] # If it's a directory argument, recurse and look for any Subpackages. # Let the Package collector deal with subnodes, don't collect here. @@ -530,8 +531,8 @@ class Session(nodes.FSCollector): if (type(x), x.fspath) in self._node_cache: yield self._node_cache[(type(x), x.fspath)] else: - yield x self._node_cache[(type(x), x.fspath)] = x + yield x else: assert argpath.check(file=1) diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py new file mode 100644 index 000000000..f17482385 --- /dev/null +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py @@ -0,0 +1,2 @@ +def test(): + pass diff --git a/testing/python/collect.py b/testing/python/collect.py index c92de12a0..cbfc4a9d2 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1591,6 +1591,13 @@ def test_package_collection_infinite_recursion(testdir): result.stdout.fnmatch_lines("*1 passed*") +def test_package_collection_init_given_as_argument(testdir): + """Regression test for #3749""" + p = testdir.copy_example("collect/package_init_given_as_arg") + result = testdir.runpytest(p / "pkg" / "__init__.py") + result.stdout.fnmatch_lines("*1 passed*") + + def test_package_with_modules(testdir): """ .