Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6d17c85

Browse files
committed
fixtures: replace PseudoFixtureDef with RequestFixtureDef which is a real FixtureDef
Remove some special cases from the code, and make the types more regular.
1 parent 631dd86 commit 6d17c85

File tree

2 files changed

+30
-21
lines changed

2 files changed

+30
-21
lines changed

‎src/_pytest/fixtures.py‎

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,6 @@
106106
)
107107

108108

109-
@dataclasses.dataclass(frozen=True)
110-
class PseudoFixtureDef(Generic[FixtureValue]):
111-
cached_result: _FixtureCachedResult[FixtureValue]
112-
_scope: Scope
113-
114-
115109
def pytest_sessionstart(session: Session) -> None:
116110
session._fixturemanager = FixtureManager(session)
117111

@@ -420,7 +414,7 @@ def scope(self) -> _ScopeName:
420414
@abc.abstractmethod
421415
def _check_scope(
422416
self,
423-
requested_fixturedef: FixtureDef[object]|PseudoFixtureDef[object],
417+
requested_fixturedef: FixtureDef[object],
424418
requested_scope: Scope,
425419
) -> None:
426420
raise NotImplementedError()
@@ -559,12 +553,9 @@ def _iter_chain(self) -> Iterator[SubRequest]:
559553
yield current
560554
current = current._parent_request
561555

562-
def _get_active_fixturedef(
563-
self, argname: str
564-
) -> FixtureDef[object] | PseudoFixtureDef[object]:
556+
def _get_active_fixturedef(self, argname: str) -> FixtureDef[object]:
565557
if argname == "request":
566-
cached_result = (self, [0], None)
567-
return PseudoFixtureDef(cached_result, Scope.Function)
558+
return RequestFixtureDef(self)
568559

569560
# If we already finished computing a fixture by this name in this item,
570561
# return it.
@@ -696,7 +687,7 @@ def _scope(self) -> Scope:
696687

697688
def _check_scope(
698689
self,
699-
requested_fixturedef: FixtureDef[object]|PseudoFixtureDef[object],
690+
requested_fixturedef: FixtureDef[object],
700691
requested_scope: Scope,
701692
) -> None:
702693
# TopRequest always has function scope so always valid.
@@ -775,11 +766,9 @@ def node(self):
775766

776767
def _check_scope(
777768
self,
778-
requested_fixturedef: FixtureDef[object]|PseudoFixtureDef[object],
769+
requested_fixturedef: FixtureDef[object],
779770
requested_scope: Scope,
780771
) -> None:
781-
if isinstance(requested_fixturedef, PseudoFixtureDef):
782-
return
783772
if self._scope > requested_scope:
784773
# Try to report something helpful.
785774
argname = requested_fixturedef.argname
@@ -968,7 +957,6 @@ def _eval_scope_callable(
968957
return result
969958

970959

971-
@final
972960
class FixtureDef(Generic[FixtureValue]):
973961
"""A container for a fixture definition.
974962
@@ -1083,8 +1071,7 @@ def execute(self, request: SubRequest) -> FixtureValue:
10831071
# down first. This is generally handled by SetupState, but still currently
10841072
# needed when this fixture is not parametrized but depends on a parametrized
10851073
# fixture.
1086-
if not isinstance(fixturedef, PseudoFixtureDef):
1087-
requested_fixtures_that_should_finalize_us.append(fixturedef)
1074+
requested_fixtures_that_should_finalize_us.append(fixturedef)
10881075

10891076
# Check for (and return) cached value/exception.
10901077
if self.cached_result is not None:
@@ -1136,6 +1123,28 @@ def __repr__(self) -> str:
11361123
return f"<FixtureDef argname={self.argname!r} scope={self.scope!r} baseid={self.baseid!r}>"
11371124

11381125

1126+
class RequestFixtureDef(FixtureDef[FixtureRequest]):
1127+
"""A custom FixtureDef for the special "request" fixture.
1128+
1129+
A new one is generated on-demand whenever "request" is requested.
1130+
"""
1131+
1132+
def __init__(self, request: FixtureRequest) -> None:
1133+
super().__init__(
1134+
config=request.config,
1135+
baseid=None,
1136+
argname="request",
1137+
func=lambda: request,
1138+
scope=Scope.Function,
1139+
params=None,
1140+
_ispytest=True,
1141+
)
1142+
self.cached_result = (request, [0], None)
1143+
1144+
def addfinalizer(self, finalizer: Callable[[], object]) -> None:
1145+
pass
1146+
1147+
11391148
def resolve_fixture_function(
11401149
fixturedef: FixtureDef[FixtureValue], request: FixtureRequest
11411150
) -> _FixtureFunc[FixtureValue]:

‎testing/python/fixtures.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ def test_request_garbage(self, pytester: Pytester) -> None:
750750
"""
751751
import sys
752752
import pytest
753-
from _pytest.fixtures import PseudoFixtureDef
753+
from _pytest.fixtures import RequestFixtureDef
754754
import gc
755755
756756
@pytest.fixture(autouse=True)
@@ -763,7 +763,7 @@ def something(request):
763763
764764
try:
765765
gc.collect()
766-
leaked = [x for _ in gc.garbage if isinstance(_, PseudoFixtureDef)]
766+
leaked = [x for _ in gc.garbage if isinstance(_, RequestFixtureDef)]
767767
assert leaked == []
768768
finally:
769769
gc.set_debug(original)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /