Skip to content

Commit 1c71bf9

Browse files
authored
Merge pull request #680 from pytest-dev/ab/fix-pytest-8.1
Fix compatibility issues with pytest 8.1
2 parents 669492d + ee05bc6 commit 1c71bf9

File tree

7 files changed

+279
-259
lines changed

7 files changed

+279
-259
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343

4444
- name: Install poetry
4545
run: |
46-
python -m pip install poetry==1.6.1
46+
python -m pip install poetry==1.8.2
4747
4848
- name: Configure poetry
4949
run: |

CHANGES.rst

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Changelog
33

44
Unreleased
55
----------
6+
- Address another compatibility issue with pytest 8.1 (fixture registration). `#680 <https://github.com/pytest-dev/pytest-bdd/pull/680>`_
67

78
7.1.1
89
----------

poetry.lock

+213-211
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/pytest_bdd/compat.py

+56-1
Original file line numberDiff line numberDiff line change
@@ -2,20 +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, FixtureManager
7+
from _pytest.fixtures import FixtureDef, FixtureManager, FixtureRequest
78
from _pytest.nodes import Node
89
from packaging.version import parse as parse_version
910

1011
pytest_version = parse_version(version("pytest"))
1112

13+
__all__ = ["getfixturedefs", "inject_fixture"]
1214

1315
if pytest_version.release >= (8, 1):
1416

1517
def getfixturedefs(fixturemanager: FixtureManager, fixturename: str, node: Node) -> Sequence[FixtureDef] | None:
1618
return fixturemanager.getfixturedefs(fixturename, node)
1719

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+
)
33+
1834
else:
1935

2036
def getfixturedefs(fixturemanager: FixtureManager, fixturename: str, node: Node) -> Sequence[FixtureDef] | None:
2137
return fixturemanager.getfixturedefs(fixturename, node.nodeid)
38+
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

+2-42
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ def _(article):
4242
from typing import Any, Callable, Iterable, Literal, TypeVar
4343

4444
import pytest
45-
from _pytest.fixtures import FixtureDef, FixtureRequest
45+
from _pytest.fixtures import FixtureRequest
4646
from typing_extensions import ParamSpec
4747

48+
from . import compat
4849
from .parser import Step
4950
from .parsers import StepParser, get_parser
5051
from .types import GIVEN, THEN, WHEN
@@ -200,44 +201,3 @@ def find_unique_name(name: str, seen: Iterable[str]) -> str:
200201
new_name = f"{name}_{i}"
201202
if new_name not in seen:
202203
return new_name
203-
204-
205-
def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
206-
"""Inject fixture into pytest fixture request.
207-
208-
:param request: pytest fixture request
209-
:param arg: argument name
210-
:param value: argument value
211-
"""
212-
213-
fd = FixtureDef(
214-
fixturemanager=request._fixturemanager,
215-
baseid=None,
216-
argname=arg,
217-
func=lambda: value,
218-
scope="function",
219-
params=None,
220-
)
221-
fd.cached_result = (value, 0, None)
222-
223-
old_fd = request._fixture_defs.get(arg)
224-
add_fixturename = arg not in request.fixturenames
225-
226-
def fin() -> None:
227-
request._fixturemanager._arg2fixturedefs[arg].remove(fd)
228-
229-
if old_fd is not None:
230-
request._fixture_defs[arg] = old_fd
231-
232-
if add_fixturename:
233-
request._pyfuncitem._fixtureinfo.names_closure.remove(arg)
234-
235-
request.addfinalizer(fin)
236-
237-
# inject fixture definition
238-
request._fixturemanager._arg2fixturedefs.setdefault(arg, []).append(fd)
239-
240-
# inject fixture value in request cache
241-
request._fixture_defs[arg] = fd
242-
if add_fixturename:
243-
request._pyfuncitem._fixtureinfo.names_closure.append(arg)

tox.ini

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tox]
22
distshare = {homedir}/.tox/distshare
3-
envlist = py{3.8,3.9,3.10,3.11}-pytest{6.2,7.0,7.1,7.2,7.3,7.4,latest}-coverage
4-
py{3.12,3.13}-pytest{7.3,7.4,latest}-coverage
3+
envlist = py{3.8,3.9,3.10,3.11}-pytest{6.2,7.0,7.1,7.2,7.3,7.4,8.0,8.1,latest}-coverage
4+
py{3.12,3.13}-pytest{7.3,7.4,8.0,8.1,latest}-coverage
55
py3.12-pytestlatest-xdist-coverage
66
mypy
77

@@ -12,6 +12,8 @@ setenv =
1212
xdist: _PYTEST_MORE_ARGS=-n3 -rfsxX
1313
deps =
1414
pytestlatest: pytest
15+
pytest8.1: pytest~=8.1.0
16+
pytest8.0: pytest~=8.0.0
1517
pytest7.4: pytest~=7.4.0
1618
pytest7.3: pytest~=7.3.0
1719
pytest7.2: pytest~=7.2.0

0 commit comments

Comments
 (0)