Pytest: Regression in 3.7.0: AttributeError for _collectfile

Created on 31 Jul 2018  路  17Comments  路  Source: pytest-dev/pytest

I get AttributeError: 'FlakesItem' object has no attribute '_collectfile' when running devpi-server tests with tox (tox -e py27 is enough) since pytest 3.7.0. When I pin to pytest<3.7dev it works (using 3.6.4).

It seems to be related to the current working directory. The tox config switches to test_devpi_server. When I run pytest in server it's fine, when i run in server/test_devpi_server it breaks.

critical bug regression

All 17 comments

Not sure if this is an issue in pytest itself, or the pytest-flakes plugin.

GitMate.io thinks possibly related issues are https://github.com/pytest-dev/pytest/issues/707 (pytest-xdist regression since execnet 1.3.0), https://github.com/pytest-dev/pytest/issues/2968 (Memory usage in 3.3.0), https://github.com/pytest-dev/pytest/issues/1083 (Regression with parallel tests on 2.7.3 and 2.8), https://github.com/pytest-dev/pytest/issues/386 (tests fail with pexpect-3.0), and https://github.com/pytest-dev/pytest/issues/1572 (Making _CallOutcome.result private in 3.0).

this is a regression made by pytest - root._collectfile got introduced in #3389

this triggered a unintentional regression as now a private api is used in more places and on objects that dont belong to it

Hello! Thank you for this great library! The Mozilla release engineering team relies on it for several projects :smiley:

I just found a similar regression:

AttributeError: 'async_generator' object has no attribute 'put'

This async generator is a regular aiohttp.ClientSession() and is initialized here. This might be an integration issue with the pytest-asyncio plugin.

I rolled pytest back to 3.6.4 and things are back working. You can see both the failure and the workaround in

@JohanLorenzo this is a different issue - related to fixture definitions, please open a new issue

Thanks for the quick answer. I opened https://github.com/pytest-dev/pytest/issues/3747

Same here with flake8:

$ py.test --flake8 package
=========================================================================================== test session starts ============================================================================================
platform darwin -- Python 3.6.2, pytest-3.7.0, py-1.5.3, pluggy-0.7.1
rootdir: /Users/Thomas/Work/stuff, inifile: setup.cfg
plugins: flake8-1.0.1, cov-2.5.1, hypothesis-3.57.0
collected 0 items / 1 errors                                                                                                                                                                               

================================================================================================== ERRORS ==================================================================================================
____________________________________________________________________________________________ ERROR collecting  _____________________________________________________________________________________________
../../../../.local/miniconda3/envs/test/lib/python3.6/site-packages/_pytest/runner.py:201: in __init__
    self.result = func()
../../../../.local/miniconda3/envs/test/lib/python3.6/site-packages/_pytest/runner.py:261: in <lambda>
    call = CallInfo(lambda: list(collector.collect()), "collect")
../../../../.local/miniconda3/envs/test/lib/python3.6/site-packages/_pytest/main.py:475: in collect
    for x in self._collect(arg):
../../../../.local/miniconda3/envs/test/lib/python3.6/site-packages/_pytest/main.py:519: in _collect
    for x in root._collectfile(pkginit):
E   AttributeError: 'Flake8Item' object has no attribute '_collectfile'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================================================================= 1 error in 0.17 seconds ==========================================================================================

Getting the same with PEP8

============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.7.0, py-1.5.4, pluggy-0.7.1
rootdir: /var/lib/jenkins/jobs/Simplereg/workspace, inifile:
plugins: xdist-1.22.5, twisted-1.8, pep8-1.0.6, forked-0.2, cov-2.5.1
collected 0 items / 1 errors

==================================== ERRORS ====================================
______________________________ ERROR collecting  _______________________________
.tox/py36/lib/python3.6/site-packages/_pytest/runner.py:201: in __init__
    self.result = func()
.tox/py36/lib/python3.6/site-packages/_pytest/runner.py:261: in <lambda>
    call = CallInfo(lambda: list(collector.collect()), "collect")
.tox/py36/lib/python3.6/site-packages/_pytest/main.py:475: in collect
    for x in self._collect(arg):
.tox/py36/lib/python3.6/site-packages/_pytest/main.py:519: in _collect
    for x in root._collectfile(pkginit):
E   AttributeError: 'Pep8Item' object has no attribute '_collectfile

We're seeing this error after the update pytest 3.6 -> 3.7:

__________________________ ERROR collecting  _______________________________
/home/travis/miniconda/envs/test/lib/python2.7/site-packages/_pytest/runner.py:201: in __init__
    self.result = func()
/home/travis/miniconda/envs/test/lib/python2.7/site-packages/_pytest/runner.py:261: in <lambda>
    call = CallInfo(lambda: list(collector.collect()), "collect")
/home/travis/miniconda/envs/test/lib/python2.7/site-packages/_pytest/main.py:475: in collect
    for x in self._collect(arg):
/home/travis/miniconda/envs/test/lib/python2.7/site-packages/_pytest/main.py:519: in _collect
    for x in root._collectfile(pkginit):
E   AttributeError: 'Pair' object has no attribute '_collectfile'
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!

https://travis-ci.org/gammapy/gammapy/jobs/410288389#L2253

Same issue or a different one?

same all issues that are triggered by _collectfile missing on 3rd party items are due to this one
its an entirely unintended issue

In our team we're suffering the same problem, we had to fix the pytest version to 3.6.4 to avoid this regression.

I'm seeing this with pytest-flake8 and pytest 3.7.0 as well.

../../../virtualenv/python2.7.14/lib/python2.7/site-packages/_pytest/runner.py:201: in __init__
    self.result = func()
../../../virtualenv/python2.7.14/lib/python2.7/site-packages/_pytest/runner.py:261: in <lambda>
    call = CallInfo(lambda: list(collector.collect()), "collect")
../../../virtualenv/python2.7.14/lib/python2.7/site-packages/_pytest/main.py:475: in collect
    for x in self._collect(arg):
../../../virtualenv/python2.7.14/lib/python2.7/site-packages/_pytest/main.py:519: in _collect
    for x in root._collectfile(pkginit):
E   AttributeError: 'Flake8Item' object has no attribute '_collectfile'

this is a work-around:

diff --git a/src/_pytest/main.py b/src/_pytest/main.py
index 9599fa16..3ba66986 100644
--- a/src/_pytest/main.py
+++ b/src/_pytest/main.py
@@ -516,12 +516,12 @@ class Session(nodes.FSCollector):
             ):
                 pkginit = path.dirpath().join("__init__.py")
                 if pkginit.exists() and not any(x in pkginit.parts() for x in paths):
-                    for x in root._collectfile(pkginit):
+                    for x in self._collectfile(pkginit):
                         yield x
                         paths.append(x.fspath.dirpath())

                 if not any(x in path.parts() for x in paths):
-                    for x in root._collectfile(path):
+                    for x in self._collectfile(path):
                         if (type(x), x.fspath) in self._node_cache:
                             yield self._node_cache[(type(x), x.fspath)]
                         else:

, or we can use pytest v3.6.4.

as far as i can tell the code paths considering the change of root are incorrect, falling back to self is only hiding the issue

I don't understand why __collectfile with the last root is called.

I got the same error if I run tests like this pytest tests/unit/*.py

E   AttributeError: 'list' object has no attribute '_collectfile'

But if I run like this pytest tests/unit/, it passes.

Was this page helpful?
0 / 5 - 0 ratings