Skip to content

Commit faa8f2e

Browse files
authored
Merge pull request #11393 from pytest-dev/fixtures-tweaks
Fixtures tweaks
2 parents 194a782 + bc71561 commit faa8f2e

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

src/_pytest/doctest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,11 @@ def func() -> None:
579579

580580
doctest_item.funcargs = {} # type: ignore[attr-defined]
581581
fm = doctest_item.session._fixturemanager
582-
doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined]
582+
fixtureinfo = fm.getfixtureinfo(
583583
node=doctest_item, func=func, cls=None, funcargs=False
584584
)
585+
doctest_item._fixtureinfo = fixtureinfo # type: ignore[attr-defined]
586+
doctest_item.fixturenames = fixtureinfo.names_closure # type: ignore[attr-defined]
585587
fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type]
586588
fixture_request._fillfixtures()
587589
return fixture_request

src/_pytest/fixtures.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,16 +210,14 @@ def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]:
210210
argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]] = {}
211211
items_by_argkey: Dict[Scope, Dict[FixtureArgKey, Deque[nodes.Item]]] = {}
212212
for scope in HIGH_SCOPES:
213-
d: Dict[nodes.Item, Dict[FixtureArgKey, None]] = {}
214-
argkeys_cache[scope] = d
215-
item_d: Dict[FixtureArgKey, Deque[nodes.Item]] = defaultdict(deque)
216-
items_by_argkey[scope] = item_d
213+
scoped_argkeys_cache = argkeys_cache[scope] = {}
214+
scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(deque)
217215
for item in items:
218216
keys = dict.fromkeys(get_parametrized_fixture_keys(item, scope), None)
219217
if keys:
220-
d[item] = keys
218+
scoped_argkeys_cache[item] = keys
221219
for key in keys:
222-
item_d[key].append(item)
220+
scoped_items_by_argkey[key].append(item)
223221
items_dict = dict.fromkeys(items, None)
224222
return list(
225223
reorder_items_atscope(items_dict, argkeys_cache, items_by_argkey, Scope.Session)
@@ -407,7 +405,7 @@ def scope(self) -> _ScopeName:
407405
@property
408406
def fixturenames(self) -> List[str]:
409407
"""Names of all active fixtures in this request."""
410-
result = list(self._pyfuncitem._fixtureinfo.names_closure)
408+
result = list(self._pyfuncitem.fixturenames)
411409
result.extend(set(self._fixture_defs).difference(result))
412410
return result
413411

@@ -687,8 +685,7 @@ def __repr__(self) -> str:
687685

688686
def _fillfixtures(self) -> None:
689687
item = self._pyfuncitem
690-
fixturenames = getattr(item, "fixturenames", self.fixturenames)
691-
for argname in fixturenames:
688+
for argname in item.fixturenames:
692689
if argname not in item.funcargs:
693690
item.funcargs[argname] = self.getfixturevalue(argname)
694691

@@ -794,7 +791,10 @@ def _schedule_finalizers(
794791
# If the executing fixturedef was not explicitly requested in the argument list (via
795792
# getfixturevalue inside the fixture call) then ensure this fixture def will be finished
796793
# first.
797-
if fixturedef.argname not in self.fixturenames:
794+
if (
795+
fixturedef.argname not in self._fixture_defs
796+
and fixturedef.argname not in self._pyfuncitem.fixturenames
797+
):
798798
fixturedef.addfinalizer(
799799
functools.partial(self._fixturedef.finish, request=self)
800800
)

src/_pytest/python.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,9 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]:
473473
clscol = self.getparent(Class)
474474
cls = clscol and clscol.obj or None
475475

476-
definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj)
476+
definition: FunctionDefinition = FunctionDefinition.from_parent(
477+
self, name=name, callobj=funcobj
478+
)
477479
fixtureinfo = definition._fixtureinfo
478480

479481
# pytest_generate_tests impls call metafunc.parametrize() which fills
@@ -1123,9 +1125,9 @@ class CallSpec2:
11231125
# arg name -> arg index.
11241126
indices: Dict[str, int] = dataclasses.field(default_factory=dict)
11251127
# Used for sorting parametrized resources.
1126-
_arg2scope: Dict[str, Scope] = dataclasses.field(default_factory=dict)
1128+
_arg2scope: Mapping[str, Scope] = dataclasses.field(default_factory=dict)
11271129
# Parts which will be added to the item's name in `[..]` separated by "-".
1128-
_idlist: List[str] = dataclasses.field(default_factory=list)
1130+
_idlist: Sequence[str] = dataclasses.field(default_factory=tuple)
11291131
# Marks which will be applied to the item.
11301132
marks: List[Mark] = dataclasses.field(default_factory=list)
11311133

@@ -1141,7 +1143,7 @@ def setmulti(
11411143
) -> "CallSpec2":
11421144
params = self.params.copy()
11431145
indices = self.indices.copy()
1144-
arg2scope = self._arg2scope.copy()
1146+
arg2scope = dict(self._arg2scope)
11451147
for arg, val in zip(argnames, valset):
11461148
if arg in params:
11471149
raise ValueError(f"duplicate parametrization of {arg!r}")

0 commit comments

Comments
 (0)