Revert "fixtures register finalizers with all fixtures before them in the stack"
This reverts commit 99180939fe.
This commit is contained in:
@@ -883,7 +883,9 @@ class FixtureDef:
|
||||
self._finalizers = []
|
||||
|
||||
def execute(self, request):
|
||||
for argname in self._dependee_fixture_argnames(request):
|
||||
# get required arguments and register our own finish()
|
||||
# with their finalization
|
||||
for argname in self.argnames:
|
||||
fixturedef = request._get_active_fixturedef(argname)
|
||||
if argname != "request":
|
||||
fixturedef.addfinalizer(functools.partial(self.finish, request=request))
|
||||
@@ -906,61 +908,6 @@ class FixtureDef:
|
||||
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
|
||||
return hook.pytest_fixture_setup(fixturedef=self, request=request)
|
||||
|
||||
def _dependee_fixture_argnames(self, request):
|
||||
"""A list of argnames for fixtures that this fixture depends on.
|
||||
|
||||
Given a request, this looks at the currently known list of fixture argnames, and
|
||||
attempts to determine what slice of the list contains fixtures that it can know
|
||||
should execute before it. This information is necessary so that this fixture can
|
||||
know what fixtures to register its finalizer with to make sure that if they
|
||||
would be torn down, they would tear down this fixture before themselves. It's
|
||||
crucial for fixtures to be torn down in the inverse order that they were set up
|
||||
in so that they don't try to clean up something that another fixture is still
|
||||
depending on.
|
||||
|
||||
When autouse fixtures are involved, it can be tricky to figure out when fixtures
|
||||
should be torn down. To solve this, this method leverages the ``fixturenames``
|
||||
list provided by the ``request`` object, as this list is at least somewhat
|
||||
sorted (in terms of the order fixtures are set up in) by the time this method is
|
||||
reached. It's sorted enough that the starting point of fixtures that depend on
|
||||
this one can be found using the ``self._parent_request`` stack.
|
||||
|
||||
If a request in the ``self._parent_request`` stack has a ``:class:FixtureDef``
|
||||
associated with it, then that fixture is dependent on this one, so any fixture
|
||||
names that appear in the list of fixture argnames that come after it can also be
|
||||
ruled out. The argnames of all fixtures associated with a request in the
|
||||
``self._parent_request`` stack are found, and the lowest index argname is
|
||||
considered the earliest point in the list of fixture argnames where everything
|
||||
from that point onward can be considered to execute after this fixture.
|
||||
Everything before this point can be considered fixtures that this fixture
|
||||
depends on, and so this fixture should register its finalizer with all of them
|
||||
to ensure that if any of them are to be torn down, they will tear this fixture
|
||||
down first.
|
||||
|
||||
This is the first part of the list of fixture argnames that is returned. The last
|
||||
part of the list is everything in ``self.argnames`` as those are explicit
|
||||
dependees of this fixture, so this fixture should definitely register its
|
||||
finalizer with them.
|
||||
"""
|
||||
all_fix_names = request.fixturenames
|
||||
try:
|
||||
current_fix_index = all_fix_names.index(self.argname)
|
||||
except ValueError:
|
||||
current_fix_index = len(request.fixturenames)
|
||||
parent_fixture_indexes = set()
|
||||
|
||||
parent_request = request._parent_request
|
||||
while hasattr(parent_request, "_parent_request"):
|
||||
if hasattr(parent_request, "_fixturedef"):
|
||||
parent_fix_name = parent_request._fixturedef.argname
|
||||
if parent_fix_name in all_fix_names:
|
||||
parent_fixture_indexes.add(all_fix_names.index(parent_fix_name))
|
||||
parent_request = parent_request._parent_request
|
||||
|
||||
stack_slice_index = min([current_fix_index, *parent_fixture_indexes])
|
||||
active_fixture_argnames = all_fix_names[:stack_slice_index]
|
||||
return {*active_fixture_argnames, *self.argnames}
|
||||
|
||||
def cache_key(self, request):
|
||||
return request.param_index if not hasattr(request, "param") else request.param
|
||||
|
||||
|
||||
Reference in New Issue
Block a user