@@ -354,16 +354,27 @@ def get_direct_param_fixture_func(request: "FixtureRequest") -> Any:
354354
355355@dataclasses .dataclass (frozen = True )
356356class FuncFixtureInfo :
357+ """Fixture-related information for a fixture-requesting item (e.g. test
358+ function).
359+
360+ This is used to examine the fixtures which an item requests statically
361+ (known during collection). This includes autouse fixtures, fixtures
362+ requested by the `usefixtures` marker, fixtures requested in the function
363+ parameters, and the transitive closure of these.
364+
365+ An item may also request fixtures dynamically (using `request.getfixturevalue`);
366+ these are not reflected here.
367+ """
368+
357369 __slots__ = ("argnames" , "initialnames" , "names_closure" , "name2fixturedefs" )
358370
359- # Original function argument names, i.e. fixture names that the function
360- # requests directly.
371+ # Fixture names that the item requests directly by function parameters.
361372 argnames : Tuple [str , ...]
362- # Fixture names that the function immediately requires. These include
373+ # Fixture names that the item immediately requires. These include
363374 # argnames + fixture names specified via usefixtures and via autouse=True in
364375 # fixture definitions.
365376 initialnames : Tuple [str , ...]
366- # The transitive closure of the fixture names that the function requires.
377+ # The transitive closure of the fixture names that the item requires.
367378 # Note: can't include dynamic dependencies (`request.getfixturevalue` calls).
368379 names_closure : List [str ]
369380 # A map from a fixture name in the transitive closure to the FixtureDefs
@@ -547,8 +558,7 @@ def path(self) -> Path:
547558 """Path where the test function was collected."""
548559 if self .scope not in ("function" , "class" , "module" , "package" ):
549560 raise AttributeError (f"path not available in { self .scope } -scoped context" )
550- # TODO: Remove ignore once _pyfuncitem is properly typed.
551- return self ._pyfuncitem .path # type: ignore
561+ return self ._pyfuncitem .path
552562
553563 @property
554564 def keywords (self ) -> MutableMapping [str , Any ]:
@@ -620,20 +630,17 @@ def getfixturevalue(self, argname: str) -> Any:
620630 def _get_active_fixturedef (
621631 self , argname : str
622632 ) -> Union ["FixtureDef[object]" , PseudoFixtureDef [object ]]:
623- try :
624- return self ._fixture_defs [argname ]
625- except KeyError :
633+ fixturedef = self ._fixture_defs .get (argname )
634+ if fixturedef is None :
626635 try :
627636 fixturedef = self ._getnextfixturedef (argname )
628637 except FixtureLookupError :
629638 if argname == "request" :
630639 cached_result = (self , [0 ], None )
631640 return PseudoFixtureDef (cached_result , Scope .Function )
632641 raise
633- # Remove indent to prevent the python3 exception
634- # from leaking into the call.
635- self ._compute_fixture_value (fixturedef )
636- self ._fixture_defs [argname ] = fixturedef
642+ self ._compute_fixture_value (fixturedef )
643+ self ._fixture_defs [argname ] = fixturedef
637644 return fixturedef
638645
639646 def _get_fixturestack (self ) -> List ["FixtureDef[Any]" ]:
@@ -1039,8 +1046,6 @@ def __init__(
10391046 # The names requested by the fixtures.
10401047 self .argnames : Final = getfuncargnames (func , name = argname , is_method = unittest )
10411048 # Whether the fixture was collected from a unittest TestCase class.
1042- # Note that it really only makes sense to define autouse fixtures in
1043- # unittest TestCases.
10441049 self .unittest : Final = unittest
10451050 # If the fixture was executed, the current value of the fixture.
10461051 # Can change if the fixture is executed with different parameters.
@@ -1468,8 +1473,26 @@ def _get_direct_parametrize_args(self, node: nodes.Node) -> List[str]:
14681473 return parametrize_argnames
14691474
14701475 def getfixtureinfo (
1471- self , node : nodes .Node , func , cls , funcargs : bool = True
1476+ self ,
1477+ node : nodes .Item ,
1478+ func : Callable [..., object ],
1479+ cls : Optional [type ],
1480+ funcargs : bool = True ,
14721481 ) -> FuncFixtureInfo :
1482+ """Calculate the :class:`FuncFixtureInfo` for an item.
1483+
1484+ If ``funcargs`` is false, or if the item sets an attribute
1485+ ``nofuncargs = True``, then ``func`` is not examined at all.
1486+
1487+ :param node:
1488+ The item requesting the fixtures.
1489+ :param func:
1490+ The item's function.
1491+ :param cls:
1492+ If the function is a method, the method's class.
1493+ :param funcargs:
1494+ Whether to look into func's parameters as fixture requests.
1495+ """
14731496 if funcargs and not getattr (node , "nofuncargs" , False ):
14741497 argnames = getfuncargnames (func , name = node .name , cls = cls )
14751498 else :
@@ -1479,8 +1502,7 @@ def getfixtureinfo(
14791502 arg for mark in node .iter_markers (name = "usefixtures" ) for arg in mark .args
14801503 )
14811504 initialnames = usefixtures + argnames
1482- fm = node .session ._fixturemanager
1483- initialnames , names_closure , arg2fixturedefs = fm .getfixtureclosure (
1505+ initialnames , names_closure , arg2fixturedefs = self .getfixtureclosure (
14841506 initialnames , node , ignore_args = self ._get_direct_parametrize_args (node )
14851507 )
14861508 return FuncFixtureInfo (argnames , initialnames , names_closure , arg2fixturedefs )
0 commit comments