Merge pull request #2127 from malinoff/fix-2124
Use session.config.hook instead of ihook. Fixes #2124
This commit is contained in:
commit
685387a43e
|
@ -1,13 +1,15 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import functools
|
||||
import inspect
|
||||
import sys
|
||||
import warnings
|
||||
from collections import OrderedDict
|
||||
|
||||
import attr
|
||||
import py
|
||||
from py._code.code import FormattedExcinfo
|
||||
|
||||
import attr
|
||||
import _pytest
|
||||
from _pytest import nodes
|
||||
from _pytest._code.code import TerminalRepr
|
||||
|
@ -22,9 +24,6 @@ from _pytest.compat import (
|
|||
from _pytest.outcomes import fail, TEST_OUTCOME
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
import _pytest.python
|
||||
|
||||
|
@ -519,7 +518,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
val = fixturedef.execute(request=subrequest)
|
||||
finally:
|
||||
# if fixture function failed it might have registered finalizers
|
||||
self.session._setupstate.addfinalizer(fixturedef.finish,
|
||||
self.session._setupstate.addfinalizer(functools.partial(fixturedef.finish, request=subrequest),
|
||||
subrequest.node)
|
||||
return val
|
||||
|
||||
|
@ -573,7 +572,6 @@ class SubRequest(FixtureRequest):
|
|||
self.param_index = param_index
|
||||
self.scope = scope
|
||||
self._fixturedef = fixturedef
|
||||
self.addfinalizer = fixturedef.addfinalizer
|
||||
self._pyfuncitem = request._pyfuncitem
|
||||
self._fixture_values = request._fixture_values
|
||||
self._fixture_defs = request._fixture_defs
|
||||
|
@ -584,6 +582,9 @@ class SubRequest(FixtureRequest):
|
|||
def __repr__(self):
|
||||
return "<SubRequest %r for %r>" % (self.fixturename, self._pyfuncitem)
|
||||
|
||||
def addfinalizer(self, finalizer):
|
||||
self._fixturedef.addfinalizer(finalizer)
|
||||
|
||||
|
||||
class ScopeMismatchError(Exception):
|
||||
""" A fixture function tries to use a different fixture function which
|
||||
|
@ -734,17 +735,17 @@ class FixtureDef:
|
|||
self.argnames = getfuncargnames(func, is_method=unittest)
|
||||
self.unittest = unittest
|
||||
self.ids = ids
|
||||
self._finalizer = []
|
||||
self._finalizers = []
|
||||
|
||||
def addfinalizer(self, finalizer):
|
||||
self._finalizer.append(finalizer)
|
||||
self._finalizers.append(finalizer)
|
||||
|
||||
def finish(self):
|
||||
def finish(self, request):
|
||||
exceptions = []
|
||||
try:
|
||||
while self._finalizer:
|
||||
while self._finalizers:
|
||||
try:
|
||||
func = self._finalizer.pop()
|
||||
func = self._finalizers.pop()
|
||||
func()
|
||||
except: # noqa
|
||||
exceptions.append(sys.exc_info())
|
||||
|
@ -754,12 +755,15 @@ class FixtureDef:
|
|||
py.builtin._reraise(*e)
|
||||
|
||||
finally:
|
||||
ihook = self._fixturemanager.session.ihook
|
||||
ihook.pytest_fixture_post_finalizer(fixturedef=self)
|
||||
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
|
||||
hook.pytest_fixture_post_finalizer(fixturedef=self, request=request)
|
||||
# even if finalization fails, we invalidate
|
||||
# the cached fixture value
|
||||
# the cached fixture value and remove
|
||||
# all finalizers because they may be bound methods which will
|
||||
# keep instances alive
|
||||
if hasattr(self, "cached_result"):
|
||||
del self.cached_result
|
||||
self._finalizers = []
|
||||
|
||||
def execute(self, request):
|
||||
# get required arguments and register our own finish()
|
||||
|
@ -767,7 +771,7 @@ class FixtureDef:
|
|||
for argname in self.argnames:
|
||||
fixturedef = request._get_active_fixturedef(argname)
|
||||
if argname != "request":
|
||||
fixturedef.addfinalizer(self.finish)
|
||||
fixturedef.addfinalizer(functools.partial(self.finish, request=request))
|
||||
|
||||
my_cache_key = request.param_index
|
||||
cached_result = getattr(self, "cached_result", None)
|
||||
|
@ -780,11 +784,11 @@ class FixtureDef:
|
|||
return result
|
||||
# we have a previous but differently parametrized fixture instance
|
||||
# so we need to tear it down before creating a new one
|
||||
self.finish()
|
||||
self.finish(request)
|
||||
assert not hasattr(self, "cached_result")
|
||||
|
||||
ihook = self._fixturemanager.session.ihook
|
||||
return ihook.pytest_fixture_setup(fixturedef=self, request=request)
|
||||
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
|
||||
return hook.pytest_fixture_setup(fixturedef=self, request=request)
|
||||
|
||||
def __repr__(self):
|
||||
return ("<FixtureDef name=%r scope=%r baseid=%r >" %
|
||||
|
|
|
@ -296,7 +296,7 @@ def pytest_fixture_setup(fixturedef, request):
|
|||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_fixture_post_finalizer(fixturedef):
|
||||
def pytest_fixture_post_finalizer(fixturedef, request):
|
||||
""" called after fixture teardown, but before the cache is cleared so
|
||||
the fixture result cache ``fixturedef.cached_result`` can
|
||||
still be accessed."""
|
||||
|
|
|
@ -499,8 +499,16 @@ class FSCollector(Collector):
|
|||
super(FSCollector, self).__init__(name, parent, config, session)
|
||||
self.fspath = fspath
|
||||
|
||||
def _check_initialpaths_for_relpath(self):
|
||||
for initialpath in self.session._initialpaths:
|
||||
if self.fspath.common(initialpath) == initialpath:
|
||||
return self.fspath.relto(initialpath.dirname)
|
||||
|
||||
def _makeid(self):
|
||||
relpath = self.fspath.relto(self.config.rootdir)
|
||||
|
||||
if not relpath:
|
||||
relpath = self._check_initialpaths_for_relpath()
|
||||
if os.sep != nodes.SEP:
|
||||
relpath = relpath.replace(os.sep, nodes.SEP)
|
||||
return relpath
|
||||
|
|
|
@ -56,11 +56,6 @@ def pytest_sessionfinish(session):
|
|||
session._setupstate.teardown_all()
|
||||
|
||||
|
||||
class NodeInfo:
|
||||
def __init__(self, location):
|
||||
self.location = location
|
||||
|
||||
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
item.ihook.pytest_runtest_logstart(
|
||||
nodeid=item.nodeid, location=item.location,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
``pytest_fixture_setup`` and ``pytest_fixture_post_finalizer`` hooks are now called for all ``conftest.py`` files.
|
|
@ -0,0 +1 @@
|
|||
``pytest_fixture_post_finalizer`` hook can now receive a ``request`` argument.
|
|
@ -0,0 +1 @@
|
|||
Fix the bug where running pytest with "--pyargs" will result in Items with empty "parent.nodeid" if run from a different root directory.
|
|
@ -624,8 +624,10 @@ class TestInvocationVariants(object):
|
|||
for p in search_path:
|
||||
monkeypatch.syspath_prepend(p)
|
||||
|
||||
os.chdir('world')
|
||||
# mixed module and filenames:
|
||||
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "world/ns_pkg")
|
||||
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world")
|
||||
testdir.chdir()
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*test_hello.py::test_hello*PASSED",
|
||||
|
|
|
@ -3121,3 +3121,43 @@ class TestParameterizedSubRequest(object):
|
|||
E*{1}:5
|
||||
*1 failed*
|
||||
""".format(fixfile.strpath, testfile.basename))
|
||||
|
||||
|
||||
def test_pytest_fixture_setup_and_post_finalizer_hook(testdir):
|
||||
testdir.makeconftest("""
|
||||
from __future__ import print_function
|
||||
def pytest_fixture_setup(fixturedef, request):
|
||||
print('ROOT setup hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
|
||||
def pytest_fixture_post_finalizer(fixturedef, request):
|
||||
print('ROOT finalizer hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
|
||||
""")
|
||||
testdir.makepyfile(**{
|
||||
'tests/conftest.py': """
|
||||
from __future__ import print_function
|
||||
def pytest_fixture_setup(fixturedef, request):
|
||||
print('TESTS setup hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
|
||||
def pytest_fixture_post_finalizer(fixturedef, request):
|
||||
print('TESTS finalizer hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
|
||||
""",
|
||||
'tests/test_hooks.py': """
|
||||
from __future__ import print_function
|
||||
import pytest
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture():
|
||||
return 'some'
|
||||
|
||||
def test_func(my_fixture):
|
||||
print('TEST test_func')
|
||||
assert my_fixture == 'some'
|
||||
"""
|
||||
})
|
||||
result = testdir.runpytest("-s")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*TESTS setup hook called for my_fixture from test_func*",
|
||||
"*ROOT setup hook called for my_fixture from test_func*",
|
||||
"*TEST test_func*",
|
||||
"*TESTS finalizer hook called for my_fixture from test_func*",
|
||||
"*ROOT finalizer hook called for my_fixture from test_func*",
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue