Skip to content

Commit cdaa9c0

Browse files
authored
Revert "fixtures register finalizers with all fixtures before t… (#6496)
Revert "fixtures register finalizers with all fixtures before them in the stack"
2 parents f9bed82 + 0dc82e8 commit cdaa9c0

File tree

4 files changed

+5
-189
lines changed

4 files changed

+5
-189
lines changed

AUTHORS

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ Ceridwen
5454
Charles Cloud
5555
Charnjit SiNGH (CCSJ)
5656
Chris Lamb
57-
Chris NeJame
5857
Christian Boelsen
5958
Christian Fetzer
6059
Christian Neumüller

changelog/6496.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Revert `#6436 <https://github.com/pytest-dev/pytest/issues/6436>`__: unfortunately this change has caused a number of regressions in many suites,
2+
so the team decided to revert this change and make a new release while we continue to look for a solution.

src/_pytest/fixtures.py

+3-56
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,9 @@ def finish(self, request):
886886
self._finalizers = []
887887

888888
def execute(self, request):
889-
for argname in self._dependee_fixture_argnames(request):
889+
# get required arguments and register our own finish()
890+
# with their finalization
891+
for argname in self.argnames:
890892
fixturedef = request._get_active_fixturedef(argname)
891893
if argname != "request":
892894
fixturedef.addfinalizer(functools.partial(self.finish, request=request))
@@ -909,61 +911,6 @@ def execute(self, request):
909911
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
910912
return hook.pytest_fixture_setup(fixturedef=self, request=request)
911913

912-
def _dependee_fixture_argnames(self, request):
913-
"""A list of argnames for fixtures that this fixture depends on.
914-
915-
Given a request, this looks at the currently known list of fixture argnames, and
916-
attempts to determine what slice of the list contains fixtures that it can know
917-
should execute before it. This information is necessary so that this fixture can
918-
know what fixtures to register its finalizer with to make sure that if they
919-
would be torn down, they would tear down this fixture before themselves. It's
920-
crucial for fixtures to be torn down in the inverse order that they were set up
921-
in so that they don't try to clean up something that another fixture is still
922-
depending on.
923-
924-
When autouse fixtures are involved, it can be tricky to figure out when fixtures
925-
should be torn down. To solve this, this method leverages the ``fixturenames``
926-
list provided by the ``request`` object, as this list is at least somewhat
927-
sorted (in terms of the order fixtures are set up in) by the time this method is
928-
reached. It's sorted enough that the starting point of fixtures that depend on
929-
this one can be found using the ``self._parent_request`` stack.
930-
931-
If a request in the ``self._parent_request`` stack has a ``:class:FixtureDef``
932-
associated with it, then that fixture is dependent on this one, so any fixture
933-
names that appear in the list of fixture argnames that come after it can also be
934-
ruled out. The argnames of all fixtures associated with a request in the
935-
``self._parent_request`` stack are found, and the lowest index argname is
936-
considered the earliest point in the list of fixture argnames where everything
937-
from that point onward can be considered to execute after this fixture.
938-
Everything before this point can be considered fixtures that this fixture
939-
depends on, and so this fixture should register its finalizer with all of them
940-
to ensure that if any of them are to be torn down, they will tear this fixture
941-
down first.
942-
943-
This is the first part of the list of fixture argnames that is returned. The last
944-
part of the list is everything in ``self.argnames`` as those are explicit
945-
dependees of this fixture, so this fixture should definitely register its
946-
finalizer with them.
947-
"""
948-
all_fix_names = request.fixturenames
949-
try:
950-
current_fix_index = all_fix_names.index(self.argname)
951-
except ValueError:
952-
current_fix_index = len(request.fixturenames)
953-
parent_fixture_indexes = set()
954-
955-
parent_request = request._parent_request
956-
while hasattr(parent_request, "_parent_request"):
957-
if hasattr(parent_request, "_fixturedef"):
958-
parent_fix_name = parent_request._fixturedef.argname
959-
if parent_fix_name in all_fix_names:
960-
parent_fixture_indexes.add(all_fix_names.index(parent_fix_name))
961-
parent_request = parent_request._parent_request
962-
963-
stack_slice_index = min([current_fix_index, *parent_fixture_indexes])
964-
active_fixture_argnames = all_fix_names[:stack_slice_index]
965-
return {*active_fixture_argnames, *self.argnames}
966-
967914
def cache_key(self, request):
968915
return request.param_index if not hasattr(request, "param") else request.param
969916

testing/python/fixtures.py

-132
Original file line numberDiff line numberDiff line change
@@ -1716,138 +1716,6 @@ def test_world(self):
17161716
reprec.assertoutcome(passed=3)
17171717

17181718

1719-
class TestMultiLevelAutouseAndParameterization:
1720-
def test_setup_and_teardown_order(self, testdir):
1721-
"""Tests that parameterized fixtures effect subsequent fixtures. (#6436)
1722-
1723-
If a fixture uses a parameterized fixture, or, for any other reason, is executed
1724-
after the parameterized fixture in the fixture stack, then it should be affected
1725-
by the parameterization, and as a result, should be torn down before the
1726-
parameterized fixture, every time the parameterized fixture is torn down. This
1727-
should be the case even if autouse is involved and/or the linear order of
1728-
fixture execution isn't deterministic. In other words, before any fixture can be
1729-
torn down, every fixture that was executed after it must also be torn down.
1730-
"""
1731-
testdir.makepyfile(
1732-
test_auto="""
1733-
import pytest
1734-
def f(param):
1735-
return param
1736-
@pytest.fixture(scope="session", autouse=True)
1737-
def s_fix(request):
1738-
yield
1739-
@pytest.fixture(scope="package", params=["p1", "p2"], ids=f, autouse=True)
1740-
def p_fix(request):
1741-
yield
1742-
@pytest.fixture(scope="module", params=["m1", "m2"], ids=f, autouse=True)
1743-
def m_fix(request):
1744-
yield
1745-
@pytest.fixture(scope="class", autouse=True)
1746-
def another_c_fix(m_fix):
1747-
yield
1748-
@pytest.fixture(scope="class")
1749-
def c_fix():
1750-
yield
1751-
@pytest.fixture(scope="function", params=["f1", "f2"], ids=f, autouse=True)
1752-
def f_fix(request):
1753-
yield
1754-
class TestFixtures:
1755-
def test_a(self, c_fix):
1756-
pass
1757-
def test_b(self, c_fix):
1758-
pass
1759-
"""
1760-
)
1761-
result = testdir.runpytest("--setup-plan")
1762-
test_fixtures_used = (
1763-
"(fixtures used: another_c_fix, c_fix, f_fix, m_fix, p_fix, request, s_fix)"
1764-
)
1765-
result.stdout.fnmatch_lines(
1766-
"""
1767-
SETUP S s_fix
1768-
SETUP P p_fix[p1]
1769-
SETUP M m_fix[m1]
1770-
SETUP C another_c_fix (fixtures used: m_fix)
1771-
SETUP C c_fix
1772-
SETUP F f_fix[f1]
1773-
test_auto.py::TestFixtures::test_a[p1-m1-f1] {0}
1774-
TEARDOWN F f_fix[f1]
1775-
SETUP F f_fix[f2]
1776-
test_auto.py::TestFixtures::test_a[p1-m1-f2] {0}
1777-
TEARDOWN F f_fix[f2]
1778-
SETUP F f_fix[f1]
1779-
test_auto.py::TestFixtures::test_b[p1-m1-f1] {0}
1780-
TEARDOWN F f_fix[f1]
1781-
SETUP F f_fix[f2]
1782-
test_auto.py::TestFixtures::test_b[p1-m1-f2] {0}
1783-
TEARDOWN F f_fix[f2]
1784-
TEARDOWN C c_fix
1785-
TEARDOWN C another_c_fix
1786-
TEARDOWN M m_fix[m1]
1787-
SETUP M m_fix[m2]
1788-
SETUP C another_c_fix (fixtures used: m_fix)
1789-
SETUP C c_fix
1790-
SETUP F f_fix[f1]
1791-
test_auto.py::TestFixtures::test_a[p1-m2-f1] {0}
1792-
TEARDOWN F f_fix[f1]
1793-
SETUP F f_fix[f2]
1794-
test_auto.py::TestFixtures::test_a[p1-m2-f2] {0}
1795-
TEARDOWN F f_fix[f2]
1796-
SETUP F f_fix[f1]
1797-
test_auto.py::TestFixtures::test_b[p1-m2-f1] {0}
1798-
TEARDOWN F f_fix[f1]
1799-
SETUP F f_fix[f2]
1800-
test_auto.py::TestFixtures::test_b[p1-m2-f2] {0}
1801-
TEARDOWN F f_fix[f2]
1802-
TEARDOWN C c_fix
1803-
TEARDOWN C another_c_fix
1804-
TEARDOWN M m_fix[m2]
1805-
TEARDOWN P p_fix[p1]
1806-
SETUP P p_fix[p2]
1807-
SETUP M m_fix[m1]
1808-
SETUP C another_c_fix (fixtures used: m_fix)
1809-
SETUP C c_fix
1810-
SETUP F f_fix[f1]
1811-
test_auto.py::TestFixtures::test_a[p2-m1-f1] {0}
1812-
TEARDOWN F f_fix[f1]
1813-
SETUP F f_fix[f2]
1814-
test_auto.py::TestFixtures::test_a[p2-m1-f2] {0}
1815-
TEARDOWN F f_fix[f2]
1816-
SETUP F f_fix[f1]
1817-
test_auto.py::TestFixtures::test_b[p2-m1-f1] {0}
1818-
TEARDOWN F f_fix[f1]
1819-
SETUP F f_fix[f2]
1820-
test_auto.py::TestFixtures::test_b[p2-m1-f2] {0}
1821-
TEARDOWN F f_fix[f2]
1822-
TEARDOWN C c_fix
1823-
TEARDOWN C another_c_fix
1824-
TEARDOWN M m_fix[m1]
1825-
SETUP M m_fix[m2]
1826-
SETUP C another_c_fix (fixtures used: m_fix)
1827-
SETUP C c_fix
1828-
SETUP F f_fix[f1]
1829-
test_auto.py::TestFixtures::test_a[p2-m2-f1] {0}
1830-
TEARDOWN F f_fix[f1]
1831-
SETUP F f_fix[f2]
1832-
test_auto.py::TestFixtures::test_a[p2-m2-f2] {0}
1833-
TEARDOWN F f_fix[f2]
1834-
SETUP F f_fix[f1]
1835-
test_auto.py::TestFixtures::test_b[p2-m2-f1] {0}
1836-
TEARDOWN F f_fix[f1]
1837-
SETUP F f_fix[f2]
1838-
test_auto.py::TestFixtures::test_b[p2-m2-f2] {0}
1839-
TEARDOWN F f_fix[f2]
1840-
TEARDOWN C c_fix
1841-
TEARDOWN C another_c_fix
1842-
TEARDOWN M m_fix[m2]
1843-
TEARDOWN P p_fix[p2]
1844-
TEARDOWN S s_fix
1845-
""".format(
1846-
test_fixtures_used
1847-
)
1848-
)
1849-
1850-
18511719
class TestAutouseManagement:
18521720
def test_autouse_conftest_mid_directory(self, testdir):
18531721
pkgdir = testdir.mkpydir("xyz123")

0 commit comments

Comments
 (0)