Skip to content

Commit f8a9ce0

Browse files
committed
Injecting fixtures is much easier in pytest 8.1!
Move logic for older pythons in the `compat.py` module.
1 parent 0bf17f1 commit f8a9ce0

File tree

3 files changed

+57
-52
lines changed

3 files changed

+57
-52
lines changed

src/pytest_bdd/compat.py

+55-8
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,75 @@
22

33
from collections.abc import Sequence
44
from importlib.metadata import version
5+
from typing import Any
56

6-
from _pytest.fixtures import FixtureDef as _FixtureDef
7-
from _pytest.fixtures import FixtureManager
7+
from _pytest.fixtures import FixtureDef, FixtureManager, FixtureRequest
88
from _pytest.nodes import Node
99
from packaging.version import parse as parse_version
1010

1111
pytest_version = parse_version(version("pytest"))
1212

13-
__all__ = ["getfixturedefs", "FixtureDef"]
13+
__all__ = ["getfixturedefs", "inject_fixture"]
1414

1515
if pytest_version.release >= (8, 1):
1616

17-
def getfixturedefs(fixturemanager: FixtureManager, fixturename: str, node: Node) -> Sequence[_FixtureDef] | None:
17+
def getfixturedefs(fixturemanager: FixtureManager, fixturename: str, node: Node) -> Sequence[FixtureDef] | None:
1818
return fixturemanager.getfixturedefs(fixturename, node)
1919

20-
def FixtureDef(fixturemanager, **kwargs):
21-
kwargs.setdefault("config", fixturemanager.config)
22-
return _FixtureDef(**kwargs)
20+
def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
21+
"""Inject fixture into pytest fixture request.
22+
23+
:param request: pytest fixture request
24+
:param arg: argument name
25+
:param value: argument value
26+
"""
27+
28+
request._fixturemanager._register_fixture(
29+
name=arg,
30+
func=lambda: value,
31+
nodeid=request.node.nodeid,
32+
)
2333

2434
else:
2535

2636
def getfixturedefs(fixturemanager: FixtureManager, fixturename: str, node: Node) -> Sequence[FixtureDef] | None:
2737
return fixturemanager.getfixturedefs(fixturename, node.nodeid)
2838

29-
FixtureDef = _FixtureDef
39+
def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
40+
"""Inject fixture into pytest fixture request.
41+
42+
:param request: pytest fixture request
43+
:param arg: argument name
44+
:param value: argument value
45+
"""
46+
fd = FixtureDef(
47+
fixturemanager=request._fixturemanager,
48+
baseid=None,
49+
argname=arg,
50+
func=lambda: value,
51+
scope="function",
52+
params=None,
53+
)
54+
fd.cached_result = (value, 0, None)
55+
56+
old_fd = request._fixture_defs.get(arg)
57+
add_fixturename = arg not in request.fixturenames
58+
59+
def fin() -> None:
60+
request._fixturemanager._arg2fixturedefs[arg].remove(fd)
61+
62+
if old_fd is not None:
63+
request._fixture_defs[arg] = old_fd
64+
65+
if add_fixturename:
66+
request._pyfuncitem._fixtureinfo.names_closure.remove(arg)
67+
68+
request.addfinalizer(fin)
69+
70+
# inject fixture definition
71+
request._fixturemanager._arg2fixturedefs.setdefault(arg, []).append(fd)
72+
73+
# inject fixture value in request cache
74+
request._fixture_defs[arg] = fd
75+
if add_fixturename:
76+
request._pyfuncitem._fixtureinfo.names_closure.append(arg)

src/pytest_bdd/scenario.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
from typing_extensions import ParamSpec
2424

2525
from . import exceptions
26-
from .compat import getfixturedefs
26+
from .compat import getfixturedefs, inject_fixture
2727
from .feature import get_feature, get_features
28-
from .steps import StepFunctionContext, get_step_fixture_name, inject_fixture
28+
from .steps import StepFunctionContext, get_step_fixture_name
2929
from .utils import CONFIG_STACK, get_args, get_caller_module_locals, get_caller_module_path
3030

3131
if TYPE_CHECKING:

src/pytest_bdd/steps.py

-42
Original file line numberDiff line numberDiff line change
@@ -201,45 +201,3 @@ def find_unique_name(name: str, seen: Iterable[str]) -> str:
201201
new_name = f"{name}_{i}"
202202
if new_name not in seen:
203203
return new_name
204-
205-
206-
def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
207-
"""Inject fixture into pytest fixture request.
208-
209-
:param request: pytest fixture request
210-
:param arg: argument name
211-
:param value: argument value
212-
"""
213-
214-
fd = compat.FixtureDef(
215-
fixturemanager=request._fixturemanager,
216-
baseid=None,
217-
argname=arg,
218-
func=lambda: value,
219-
scope="function",
220-
params=None,
221-
)
222-
fd.cached_result = (value, 0, None)
223-
224-
old_fd = request._fixture_defs.get(arg)
225-
add_fixturename = arg not in request.fixturenames
226-
227-
def fin() -> None:
228-
# TODO: Still required?
229-
request._fixturemanager._arg2fixturedefs[arg].remove(fd)
230-
231-
if old_fd is not None:
232-
request._fixture_defs[arg] = old_fd
233-
234-
if add_fixturename:
235-
request._pyfuncitem._fixtureinfo.names_closure.remove(arg)
236-
237-
request.addfinalizer(fin)
238-
239-
# inject fixture definition
240-
request._fixturemanager._arg2fixturedefs.setdefault(arg, []).append(fd)
241-
242-
# inject fixture value in request cache
243-
request._fixture_defs[arg] = fd
244-
if add_fixturename:
245-
request._pyfuncitem._fixtureinfo.names_closure.append(arg)

0 commit comments

Comments
 (0)