@@ -354,16 +354,27 @@ def get_direct_param_fixture_func(request: "FixtureRequest") -> Any:
354
354
355
355
@dataclasses .dataclass (frozen = True )
356
356
class 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
+
357
369
__slots__ = ("argnames" , "initialnames" , "names_closure" , "name2fixturedefs" )
358
370
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.
361
372
argnames : Tuple [str , ...]
362
- # Fixture names that the function immediately requires. These include
373
+ # Fixture names that the item immediately requires. These include
363
374
# argnames + fixture names specified via usefixtures and via autouse=True in
364
375
# fixture definitions.
365
376
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.
367
378
# Note: can't include dynamic dependencies (`request.getfixturevalue` calls).
368
379
names_closure : List [str ]
369
380
# A map from a fixture name in the transitive closure to the FixtureDefs
@@ -547,8 +558,7 @@ def path(self) -> Path:
547
558
"""Path where the test function was collected."""
548
559
if self .scope not in ("function" , "class" , "module" , "package" ):
549
560
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
552
562
553
563
@property
554
564
def keywords (self ) -> MutableMapping [str , Any ]:
@@ -620,20 +630,17 @@ def getfixturevalue(self, argname: str) -> Any:
620
630
def _get_active_fixturedef (
621
631
self , argname : str
622
632
) -> 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 :
626
635
try :
627
636
fixturedef = self ._getnextfixturedef (argname )
628
637
except FixtureLookupError :
629
638
if argname == "request" :
630
639
cached_result = (self , [0 ], None )
631
640
return PseudoFixtureDef (cached_result , Scope .Function )
632
641
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
637
644
return fixturedef
638
645
639
646
def _get_fixturestack (self ) -> List ["FixtureDef[Any]" ]:
@@ -1467,8 +1474,26 @@ def _get_direct_parametrize_args(self, node: nodes.Node) -> List[str]:
1467
1474
return parametrize_argnames
1468
1475
1469
1476
def getfixtureinfo (
1470
- self , node : nodes .Node , func , cls , funcargs : bool = True
1477
+ self ,
1478
+ node : nodes .Item ,
1479
+ func : Callable [..., object ],
1480
+ cls : Optional [type ],
1481
+ funcargs : bool = True ,
1471
1482
) -> FuncFixtureInfo :
1483
+ """Calculate the :class:`FuncFixtureInfo` for an item.
1484
+
1485
+ If ``funcargs`` is false, or if the item sets an attribute
1486
+ ``nofuncargs = True``, then ``func`` is not examined at all.
1487
+
1488
+ :param node:
1489
+ The item requesting the fixtures.
1490
+ :param func:
1491
+ The item's function.
1492
+ :param cls:
1493
+ If the function is a method, the method's class.
1494
+ :param funcargs:
1495
+ Whether to look into func's parameters as fixture requests.
1496
+ """
1472
1497
if funcargs and not getattr (node , "nofuncargs" , False ):
1473
1498
argnames = getfuncargnames (func , name = node .name , cls = cls )
1474
1499
else :
@@ -1478,8 +1503,7 @@ def getfixtureinfo(
1478
1503
arg for mark in node .iter_markers (name = "usefixtures" ) for arg in mark .args
1479
1504
)
1480
1505
initialnames = usefixtures + argnames
1481
- fm = node .session ._fixturemanager
1482
- initialnames , names_closure , arg2fixturedefs = fm .getfixtureclosure (
1506
+ initialnames , names_closure , arg2fixturedefs = self .getfixtureclosure (
1483
1507
initialnames , node , ignore_args = self ._get_direct_parametrize_args (node )
1484
1508
)
1485
1509
return FuncFixtureInfo (argnames , initialnames , names_closure , arg2fixturedefs )
0 commit comments