Skip to content

Commit

Permalink
Merge pull request #11393 from pytest-dev/fixtures-tweaks
Browse files Browse the repository at this point in the history
Fixtures tweaks
  • Loading branch information
bluetech committed Sep 6, 2023
2 parents 194a782 + bc71561 commit faa8f2e
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 15 deletions.
4 changes: 3 additions & 1 deletion src/_pytest/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,9 +579,11 @@ def func() -> None:

doctest_item.funcargs = {} # type: ignore[attr-defined]
fm = doctest_item.session._fixturemanager
doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined]
fixtureinfo = fm.getfixtureinfo(
node=doctest_item, func=func, cls=None, funcargs=False
)
doctest_item._fixtureinfo = fixtureinfo # type: ignore[attr-defined]
doctest_item.fixturenames = fixtureinfo.names_closure # type: ignore[attr-defined]
fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type]
fixture_request._fillfixtures()
return fixture_request
Expand Down
20 changes: 10 additions & 10 deletions src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,14 @@ def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]:
argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]] = {}
items_by_argkey: Dict[Scope, Dict[FixtureArgKey, Deque[nodes.Item]]] = {}
for scope in HIGH_SCOPES:
d: Dict[nodes.Item, Dict[FixtureArgKey, None]] = {}
argkeys_cache[scope] = d
item_d: Dict[FixtureArgKey, Deque[nodes.Item]] = defaultdict(deque)
items_by_argkey[scope] = item_d
scoped_argkeys_cache = argkeys_cache[scope] = {}
scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(deque)
for item in items:
keys = dict.fromkeys(get_parametrized_fixture_keys(item, scope), None)
if keys:
d[item] = keys
scoped_argkeys_cache[item] = keys
for key in keys:
item_d[key].append(item)
scoped_items_by_argkey[key].append(item)
items_dict = dict.fromkeys(items, None)
return list(
reorder_items_atscope(items_dict, argkeys_cache, items_by_argkey, Scope.Session)
Expand Down Expand Up @@ -407,7 +405,7 @@ def scope(self) -> _ScopeName:
@property
def fixturenames(self) -> List[str]:
"""Names of all active fixtures in this request."""
result = list(self._pyfuncitem._fixtureinfo.names_closure)
result = list(self._pyfuncitem.fixturenames)
result.extend(set(self._fixture_defs).difference(result))
return result

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

def _fillfixtures(self) -> None:
item = self._pyfuncitem
fixturenames = getattr(item, "fixturenames", self.fixturenames)
for argname in fixturenames:
for argname in item.fixturenames:
if argname not in item.funcargs:
item.funcargs[argname] = self.getfixturevalue(argname)

Expand Down Expand Up @@ -794,7 +791,10 @@ def _schedule_finalizers(
# If the executing fixturedef was not explicitly requested in the argument list (via
# getfixturevalue inside the fixture call) then ensure this fixture def will be finished
# first.
if fixturedef.argname not in self.fixturenames:
if (
fixturedef.argname not in self._fixture_defs
and fixturedef.argname not in self._pyfuncitem.fixturenames
):
fixturedef.addfinalizer(
functools.partial(self._fixturedef.finish, request=self)
)
Expand Down
10 changes: 6 additions & 4 deletions src/_pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,9 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]:
clscol = self.getparent(Class)
cls = clscol and clscol.obj or None

definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj)
definition: FunctionDefinition = FunctionDefinition.from_parent(
self, name=name, callobj=funcobj
)
fixtureinfo = definition._fixtureinfo

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

Expand All @@ -1141,7 +1143,7 @@ def setmulti(
) -> "CallSpec2":
params = self.params.copy()
indices = self.indices.copy()
arg2scope = self._arg2scope.copy()
arg2scope = dict(self._arg2scope)
for arg, val in zip(argnames, valset):
if arg in params:
raise ValueError(f"duplicate parametrization of {arg!r}")
Expand Down

0 comments on commit faa8f2e

Please sign in to comment.