20
20
21
21
import pytest
22
22
from _pytest .fixtures import FixtureDef , FixtureManager , FixtureRequest , call_fixture_func
23
- from _pytest .nodes import iterparentnodeids
24
23
from typing_extensions import ParamSpec
25
24
26
25
from . import exceptions
43
42
ALPHA_REGEX = re .compile (r"^\d+_*" )
44
43
45
44
46
- def find_fixturedefs_for_step (step : Step , fixturemanager : FixtureManager , nodeid : str ) -> Iterable [FixtureDef [Any ]]:
45
+ def find_fixturedefs_for_step (step : Step , fixturemanager : FixtureManager , node ) -> Iterable [FixtureDef [Any ]]:
47
46
"""Find the fixture defs that can parse a step."""
48
47
# happens to be that _arg2fixturedefs is changed during the iteration so we use a copy
49
48
fixture_def_by_name = list (fixturemanager ._arg2fixturedefs .items ())
@@ -60,14 +59,65 @@ def find_fixturedefs_for_step(step: Step, fixturemanager: FixtureManager, nodeid
60
59
if not match :
61
60
continue
62
61
63
- if fixturedef not in (fixturemanager .getfixturedefs (fixturename , nodeid ) or []):
62
+ if hasattr (pytest , "version_tuple" ) and pytest .version_tuple >= (8 , 1 ):
63
+ fixturedefs = fixturemanager .getfixturedefs (fixturename , node )
64
+ else :
65
+ fixturedefs = fixturemanager .getfixturedefs (fixturename , node .nodeid )
66
+ if fixturedef not in (fixturedefs or []):
64
67
continue
65
68
66
69
yield fixturedef
67
70
68
71
72
+ # Function copied from pytest 8.0 (removed in later versions).
73
+ def iterparentnodeids (nodeid : str ) -> Iterator [str ]:
74
+ """Return the parent node IDs of a given node ID, inclusive.
75
+
76
+ For the node ID
77
+
78
+ "testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source"
79
+
80
+ the result would be
81
+
82
+ ""
83
+ "testing"
84
+ "testing/code"
85
+ "testing/code/test_excinfo.py"
86
+ "testing/code/test_excinfo.py::TestFormattedExcinfo"
87
+ "testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source"
88
+
89
+ Note that / components are only considered until the first ::.
90
+ """
91
+ SEP = "/"
92
+ pos = 0
93
+ first_colons : Optional [int ] = nodeid .find ("::" )
94
+ if first_colons == - 1 :
95
+ first_colons = None
96
+ # The root Session node - always present.
97
+ yield ""
98
+ # Eagerly consume SEP parts until first colons.
99
+ while True :
100
+ at = nodeid .find (SEP , pos , first_colons )
101
+ if at == - 1 :
102
+ break
103
+ if at > 0 :
104
+ yield nodeid [:at ]
105
+ pos = at + len (SEP )
106
+ # Eagerly consume :: parts.
107
+ while True :
108
+ at = nodeid .find ("::" , pos )
109
+ if at == - 1 :
110
+ break
111
+ if at > 0 :
112
+ yield nodeid [:at ]
113
+ pos = at + len ("::" )
114
+ # The node ID itself.
115
+ if nodeid :
116
+ yield nodeid
117
+
118
+
69
119
@contextlib .contextmanager
70
- def inject_fixturedefs_for_step (step : Step , fixturemanager : FixtureManager , nodeid : str ) -> Iterator [None ]:
120
+ def inject_fixturedefs_for_step (step : Step , fixturemanager : FixtureManager , node ) -> Iterator [None ]:
71
121
"""Inject fixture definitions that can parse a step.
72
122
73
123
We fist iterate over all the fixturedefs that can parse the step.
@@ -78,7 +128,7 @@ def inject_fixturedefs_for_step(step: Step, fixturemanager: FixtureManager, node
78
128
"""
79
129
bdd_name = get_step_fixture_name (step = step )
80
130
81
- fixturedefs = list (find_fixturedefs_for_step (step = step , fixturemanager = fixturemanager , nodeid = nodeid ))
131
+ fixturedefs = list (find_fixturedefs_for_step (step = step , fixturemanager = fixturemanager , node = node ))
82
132
83
133
# Sort the fixture definitions by their "path", so that the `bdd_name` fixture will
84
134
# respect the fixture scope
@@ -114,7 +164,7 @@ def get_step_function(request, step: Step) -> StepFunctionContext | None:
114
164
__tracebackhide__ = True
115
165
bdd_name = get_step_fixture_name (step = step )
116
166
117
- with inject_fixturedefs_for_step (step = step , fixturemanager = request ._fixturemanager , nodeid = request .node . nodeid ):
167
+ with inject_fixturedefs_for_step (step = step , fixturemanager = request ._fixturemanager , node = request .node ):
118
168
try :
119
169
return cast (StepFunctionContext , request .getfixturevalue (bdd_name ))
120
170
except pytest .FixtureLookupError :
0 commit comments