Skip to content

Commit d839686

Browse files
committed
Don't delete FixtureDef.cached_result, set it to None instead
Previously `cached_result` was either set or deleted. Type annotations cannot handle this, so use `None` for the non-set state instead.
1 parent 56a5dbe commit d839686

File tree

4 files changed

+18
-11
lines changed

4 files changed

+18
-11
lines changed

changelog/6737.breaking.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
The ``cached_result`` attribute of ``FixtureDef`` is now set to ``None`` when
2+
the result is unavailable, instead of being deleted.
3+
4+
If your plugin perform checks like ``hasattr(fixturedef, 'cached_result')``,
5+
for example in a ``pytest_fixture_post_finalizer`` hook implementation, replace
6+
it with ``fixturedef.cached_result is not None``. If you ``del`` the attribute,
7+
set it to ``None`` instead.

src/_pytest/fixtures.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ def __init__(
855855
self.argnames = getfuncargnames(func, name=argname, is_method=unittest)
856856
self.unittest = unittest
857857
self.ids = ids
858+
self.cached_result = None
858859
self._finalizers = []
859860

860861
def addfinalizer(self, finalizer):
@@ -881,8 +882,7 @@ def finish(self, request):
881882
# the cached fixture value and remove
882883
# all finalizers because they may be bound methods which will
883884
# keep instances alive
884-
if hasattr(self, "cached_result"):
885-
del self.cached_result
885+
self.cached_result = None
886886
self._finalizers = []
887887

888888
def execute(self, request):
@@ -894,9 +894,8 @@ def execute(self, request):
894894
fixturedef.addfinalizer(functools.partial(self.finish, request=request))
895895

896896
my_cache_key = self.cache_key(request)
897-
cached_result = getattr(self, "cached_result", None)
898-
if cached_result is not None:
899-
result, cache_key, err = cached_result
897+
if self.cached_result is not None:
898+
result, cache_key, err = self.cached_result
900899
# note: comparison with `==` can fail (or be expensive) for e.g.
901900
# numpy arrays (#6497)
902901
if my_cache_key is cache_key:
@@ -908,7 +907,7 @@ def execute(self, request):
908907
# we have a previous but differently parametrized fixture instance
909908
# so we need to tear it down before creating a new one
910909
self.finish(request)
911-
assert not hasattr(self, "cached_result")
910+
assert self.cached_result is None
912911

913912
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
914913
return hook.pytest_fixture_setup(fixturedef=self, request=request)
@@ -953,6 +952,7 @@ def pytest_fixture_setup(fixturedef, request):
953952
kwargs = {}
954953
for argname in fixturedef.argnames:
955954
fixdef = request._get_active_fixturedef(argname)
955+
assert fixdef.cached_result is not None
956956
result, arg_cache_key, exc = fixdef.cached_result
957957
request._check_scope(argname, request.scope, fixdef.scope)
958958
kwargs[argname] = result

src/_pytest/hookspec.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,9 @@ def pytest_fixture_setup(fixturedef, request):
423423

424424

425425
def pytest_fixture_post_finalizer(fixturedef, request):
426-
""" called after fixture teardown, but before the cache is cleared so
427-
the fixture result cache ``fixturedef.cached_result`` can
428-
still be accessed."""
426+
"""Called after fixture teardown, but before the cache is cleared, so
427+
the fixture result ``fixturedef.cached_result`` is still available (not
428+
``None``)."""
429429

430430

431431
# -------------------------------------------------------------------------

src/_pytest/setuponly.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def pytest_fixture_setup(fixturedef, request):
3434
_show_fixture_action(fixturedef, "SETUP")
3535

3636

37-
def pytest_fixture_post_finalizer(fixturedef):
38-
if hasattr(fixturedef, "cached_result"):
37+
def pytest_fixture_post_finalizer(fixturedef) -> None:
38+
if fixturedef.cached_result is not None:
3939
config = fixturedef._fixturemanager.config
4040
if config.option.setupshow:
4141
_show_fixture_action(fixturedef, "TEARDOWN")

0 commit comments

Comments
 (0)