fixtures: avoid FixtureDef <-> FixtureManager reference cycle

There is no need to store the FixtureManager on each FixtureDef.
This commit is contained in:
Ran Benita 2024-01-09 23:01:50 +02:00
parent 97dfc3429e
commit 372c17e228
3 changed files with 13 additions and 11 deletions

View File

@ -970,7 +970,7 @@ class FixtureDef(Generic[FixtureValue]):
def __init__( def __init__(
self, self,
fixturemanager: "FixtureManager", config: Config,
baseid: Optional[str], baseid: Optional[str],
argname: str, argname: str,
func: "_FixtureFunc[FixtureValue]", func: "_FixtureFunc[FixtureValue]",
@ -984,7 +984,6 @@ class FixtureDef(Generic[FixtureValue]):
_ispytest: bool = False, _ispytest: bool = False,
) -> None: ) -> None:
check_ispytest(_ispytest) check_ispytest(_ispytest)
self._fixturemanager = fixturemanager
# The "base" node ID for the fixture. # The "base" node ID for the fixture.
# #
# This is a node ID prefix. A fixture is only available to a node (e.g. # This is a node ID prefix. A fixture is only available to a node (e.g.
@ -1010,7 +1009,7 @@ class FixtureDef(Generic[FixtureValue]):
if scope is None: if scope is None:
scope = Scope.Function scope = Scope.Function
elif callable(scope): elif callable(scope):
scope = _eval_scope_callable(scope, argname, fixturemanager.config) scope = _eval_scope_callable(scope, argname, config)
if isinstance(scope, str): if isinstance(scope, str):
scope = Scope.from_user( scope = Scope.from_user(
scope, descr=f"Fixture '{func.__name__}'", where=baseid scope, descr=f"Fixture '{func.__name__}'", where=baseid
@ -1657,7 +1656,7 @@ class FixtureManager:
Set this if this is a unittest fixture. Set this if this is a unittest fixture.
""" """
fixture_def = FixtureDef( fixture_def = FixtureDef(
fixturemanager=self, config=self.config,
baseid=nodeid, baseid=nodeid,
argname=name, argname=name,
func=func, func=func,

View File

@ -1323,7 +1323,7 @@ class Metafunc:
fixturedef = name2pseudofixturedef[argname] fixturedef = name2pseudofixturedef[argname]
else: else:
fixturedef = FixtureDef( fixturedef = FixtureDef(
fixturemanager=self.definition.session._fixturemanager, config=self.config,
baseid="", baseid="",
argname=argname, argname=argname,
func=get_direct_param_fixture_func, func=get_direct_param_fixture_func,

View File

@ -47,20 +47,23 @@ def pytest_fixture_setup(
else: else:
param = request.param param = request.param
fixturedef.cached_param = param # type: ignore[attr-defined] fixturedef.cached_param = param # type: ignore[attr-defined]
_show_fixture_action(fixturedef, "SETUP") _show_fixture_action(fixturedef, request.config, "SETUP")
def pytest_fixture_post_finalizer(fixturedef: FixtureDef[object]) -> None: def pytest_fixture_post_finalizer(
fixturedef: FixtureDef[object], request: SubRequest
) -> None:
if fixturedef.cached_result is not None: if fixturedef.cached_result is not None:
config = fixturedef._fixturemanager.config config = request.config
if config.option.setupshow: if config.option.setupshow:
_show_fixture_action(fixturedef, "TEARDOWN") _show_fixture_action(fixturedef, request.config, "TEARDOWN")
if hasattr(fixturedef, "cached_param"): if hasattr(fixturedef, "cached_param"):
del fixturedef.cached_param # type: ignore[attr-defined] del fixturedef.cached_param # type: ignore[attr-defined]
def _show_fixture_action(fixturedef: FixtureDef[object], msg: str) -> None: def _show_fixture_action(
config = fixturedef._fixturemanager.config fixturedef: FixtureDef[object], config: Config, msg: str
) -> None:
capman = config.pluginmanager.getplugin("capturemanager") capman = config.pluginmanager.getplugin("capturemanager")
if capman: if capman:
capman.suspend_global_capture() capman.suspend_global_capture()