fixtures: some code comments and minor improvements
This commit is contained in:
parent
a3fbf24389
commit
0e0ed2af95
|
@ -102,7 +102,7 @@ def num_mock_patch_args(function) -> int:
|
||||||
|
|
||||||
|
|
||||||
def getfuncargnames(
|
def getfuncargnames(
|
||||||
function: Callable[..., Any],
|
function: Callable[..., object],
|
||||||
*,
|
*,
|
||||||
name: str = "",
|
name: str = "",
|
||||||
is_method: bool = False,
|
is_method: bool = False,
|
||||||
|
|
|
@ -354,16 +354,27 @@ def get_direct_param_fixture_func(request: "FixtureRequest") -> Any:
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class FuncFixtureInfo:
|
class FuncFixtureInfo:
|
||||||
|
"""Fixture-related information for a fixture-requesting item (e.g. test
|
||||||
|
function).
|
||||||
|
|
||||||
|
This is used to examine the fixtures which an item requests statically
|
||||||
|
(known during collection). This includes autouse fixtures, fixtures
|
||||||
|
requested by the `usefixtures` marker, fixtures requested in the function
|
||||||
|
parameters, and the transitive closure of these.
|
||||||
|
|
||||||
|
An item may also request fixtures dynamically (using `request.getfixturevalue`);
|
||||||
|
these are not reflected here.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs")
|
__slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs")
|
||||||
|
|
||||||
# Original function argument names, i.e. fixture names that the function
|
# Fixture names that the item requests directly by function parameters.
|
||||||
# requests directly.
|
|
||||||
argnames: Tuple[str, ...]
|
argnames: Tuple[str, ...]
|
||||||
# Fixture names that the function immediately requires. These include
|
# Fixture names that the item immediately requires. These include
|
||||||
# argnames + fixture names specified via usefixtures and via autouse=True in
|
# argnames + fixture names specified via usefixtures and via autouse=True in
|
||||||
# fixture definitions.
|
# fixture definitions.
|
||||||
initialnames: Tuple[str, ...]
|
initialnames: Tuple[str, ...]
|
||||||
# The transitive closure of the fixture names that the function requires.
|
# The transitive closure of the fixture names that the item requires.
|
||||||
# Note: can't include dynamic dependencies (`request.getfixturevalue` calls).
|
# Note: can't include dynamic dependencies (`request.getfixturevalue` calls).
|
||||||
names_closure: List[str]
|
names_closure: List[str]
|
||||||
# A map from a fixture name in the transitive closure to the FixtureDefs
|
# A map from a fixture name in the transitive closure to the FixtureDefs
|
||||||
|
@ -547,8 +558,7 @@ class FixtureRequest:
|
||||||
"""Path where the test function was collected."""
|
"""Path where the test function was collected."""
|
||||||
if self.scope not in ("function", "class", "module", "package"):
|
if self.scope not in ("function", "class", "module", "package"):
|
||||||
raise AttributeError(f"path not available in {self.scope}-scoped context")
|
raise AttributeError(f"path not available in {self.scope}-scoped context")
|
||||||
# TODO: Remove ignore once _pyfuncitem is properly typed.
|
return self._pyfuncitem.path
|
||||||
return self._pyfuncitem.path # type: ignore
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def keywords(self) -> MutableMapping[str, Any]:
|
def keywords(self) -> MutableMapping[str, Any]:
|
||||||
|
@ -620,9 +630,8 @@ class FixtureRequest:
|
||||||
def _get_active_fixturedef(
|
def _get_active_fixturedef(
|
||||||
self, argname: str
|
self, argname: str
|
||||||
) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]:
|
) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]:
|
||||||
try:
|
fixturedef = self._fixture_defs.get(argname)
|
||||||
return self._fixture_defs[argname]
|
if fixturedef is None:
|
||||||
except KeyError:
|
|
||||||
try:
|
try:
|
||||||
fixturedef = self._getnextfixturedef(argname)
|
fixturedef = self._getnextfixturedef(argname)
|
||||||
except FixtureLookupError:
|
except FixtureLookupError:
|
||||||
|
@ -630,8 +639,6 @@ class FixtureRequest:
|
||||||
cached_result = (self, [0], None)
|
cached_result = (self, [0], None)
|
||||||
return PseudoFixtureDef(cached_result, Scope.Function)
|
return PseudoFixtureDef(cached_result, Scope.Function)
|
||||||
raise
|
raise
|
||||||
# Remove indent to prevent the python3 exception
|
|
||||||
# from leaking into the call.
|
|
||||||
self._compute_fixture_value(fixturedef)
|
self._compute_fixture_value(fixturedef)
|
||||||
self._fixture_defs[argname] = fixturedef
|
self._fixture_defs[argname] = fixturedef
|
||||||
return fixturedef
|
return fixturedef
|
||||||
|
@ -1467,8 +1474,26 @@ class FixtureManager:
|
||||||
return parametrize_argnames
|
return parametrize_argnames
|
||||||
|
|
||||||
def getfixtureinfo(
|
def getfixtureinfo(
|
||||||
self, node: nodes.Node, func, cls, funcargs: bool = True
|
self,
|
||||||
|
node: nodes.Item,
|
||||||
|
func: Callable[..., object],
|
||||||
|
cls: Optional[type],
|
||||||
|
funcargs: bool = True,
|
||||||
) -> FuncFixtureInfo:
|
) -> FuncFixtureInfo:
|
||||||
|
"""Calculate the :class:`FuncFixtureInfo` for an item.
|
||||||
|
|
||||||
|
If ``funcargs`` is false, or if the item sets an attribute
|
||||||
|
``nofuncargs = True``, then ``func`` is not examined at all.
|
||||||
|
|
||||||
|
:param node:
|
||||||
|
The item requesting the fixtures.
|
||||||
|
:param func:
|
||||||
|
The item's function.
|
||||||
|
:param cls:
|
||||||
|
If the function is a method, the method's class.
|
||||||
|
:param funcargs:
|
||||||
|
Whether to look into func's parameters as fixture requests.
|
||||||
|
"""
|
||||||
if funcargs and not getattr(node, "nofuncargs", False):
|
if funcargs and not getattr(node, "nofuncargs", False):
|
||||||
argnames = getfuncargnames(func, name=node.name, cls=cls)
|
argnames = getfuncargnames(func, name=node.name, cls=cls)
|
||||||
else:
|
else:
|
||||||
|
@ -1478,8 +1503,7 @@ class FixtureManager:
|
||||||
arg for mark in node.iter_markers(name="usefixtures") for arg in mark.args
|
arg for mark in node.iter_markers(name="usefixtures") for arg in mark.args
|
||||||
)
|
)
|
||||||
initialnames = usefixtures + argnames
|
initialnames = usefixtures + argnames
|
||||||
fm = node.session._fixturemanager
|
initialnames, names_closure, arg2fixturedefs = self.getfixtureclosure(
|
||||||
initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure(
|
|
||||||
initialnames, node, ignore_args=self._get_direct_parametrize_args(node)
|
initialnames, node, ignore_args=self._get_direct_parametrize_args(node)
|
||||||
)
|
)
|
||||||
return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs)
|
return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs)
|
||||||
|
|
Loading…
Reference in New Issue