diff options
author | Jakub Roztocil <jakub@roztocil.co> | 2024-03-04 16:27:52 +0100 |
---|---|---|
committer | Jakub Roztocil <jakub@roztocil.co> | 2024-03-04 16:28:03 +0100 |
commit | 3524ccf0baa9f2b3029368ab07ba5f64e62dcb1f (patch) | |
tree | 55809361933126d823d65b1ff791cad1eda13d32 | |
parent | 8ac44b57ce0d4e8b8da574eb4391262c9c55b4e6 (diff) |
Drop dependency on the abandoned python-lazy-fixture
-rw-r--r-- | setup.py | 1 | ||||
-rw-r--r-- | tests/conftest.py | 8 | ||||
-rw-r--r-- | tests/fixtures/pytest_lazy_fixture.py | 99 |
3 files changed, 104 insertions, 4 deletions
@@ -11,7 +11,6 @@ import httpie tests_require = [ 'pytest', 'pytest-httpbin>=0.0.6', - 'pytest-lazy-fixture>=0.0.6', 'responses', 'pytest-mock', 'werkzeug<2.1.0' diff --git a/tests/conftest.py b/tests/conftest.py index 7ca172a8..9430a32e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,14 +3,14 @@ import socket import pytest from pytest_httpbin import certs -from .utils import ( # noqa +from .utils import ( # noqa HTTPBIN_WITH_CHUNKED_SUPPORT_DOMAIN, HTTPBIN_WITH_CHUNKED_SUPPORT, REMOTE_HTTPBIN_DOMAIN, IS_PYOPENSSL, mock_env ) -from .utils.plugins_cli import ( # noqa +from .utils.plugins_cli import ( # noqa broken_plugin, dummy_plugin, dummy_plugins, @@ -18,7 +18,9 @@ from .utils.plugins_cli import ( # noqa httpie_plugins_success, interface, ) -from .utils.http_server import http_server, localhost_http_server # noqa +from .utils.http_server import http_server, localhost_http_server # noqa +# noinspection PyUnresolvedReferences +from .fixtures import pytest_lazy_fixture @pytest.fixture(scope='function', autouse=True) diff --git a/tests/fixtures/pytest_lazy_fixture.py b/tests/fixtures/pytest_lazy_fixture.py new file mode 100644 index 00000000..5b70d8ec --- /dev/null +++ b/tests/fixtures/pytest_lazy_fixture.py @@ -0,0 +1,99 @@ +""" +Replacement for the abandoned `pytest.lazy_fixture` <https://github.com/TvoroG/pytest-lazy-fixture> + +Based on <https://github.com/TvoroG/pytest-lazy-fixture/issues/65#issuecomment-1914581161> + +""" +import dataclasses +import typing + +import pytest + + +@dataclasses.dataclass +class LazyFixture: + """Lazy fixture dataclass.""" + + name: str + + +def lazy_fixture(name: str) -> LazyFixture: + """Mark a fixture as lazy.""" + return LazyFixture(name) + + +# NOTE: Mimic the original API +pytest.lazy_fixture = lazy_fixture + + +def is_lazy_fixture(value: object) -> bool: + """Check whether a value is a lazy fixture.""" + return isinstance(value, LazyFixture) + + +def pytest_make_parametrize_id( + config: pytest.Config, + val: object, + argname: str, +) -> str | None: + """Inject lazy fixture parametrized id. + + Reference: + - https://bit.ly/48Off6r + + Args: + config (pytest.Config): pytest configuration. + value (object): fixture value. + argname (str): automatic parameter name. + + Returns: + str: new parameter id. + """ + if is_lazy_fixture(val): + return typing.cast(LazyFixture, val).name + return None + + +@pytest.hookimpl(tryfirst=True) +def pytest_fixture_setup( + fixturedef: pytest.FixtureDef, + request: pytest.FixtureRequest, +) -> object | None: + """Lazy fixture setup hook. + + This hook will never take over a fixture setup but just simply will + try to resolve recursively any lazy fixture found in request.param. + + Reference: + - https://bit.ly/3SyvsXJ + + Args: + fixturedef (pytest.FixtureDef): fixture definition object. + request (pytest.FixtureRequest): fixture request object. + + Returns: + object | None: fixture value or None otherwise. + """ + if hasattr(request, "param") and request.param: + request.param = _resolve_lazy_fixture(request.param, request) + return None + + +def _resolve_lazy_fixture(__val: object, request: pytest.FixtureRequest) -> object: + """Lazy fixture resolver. + + Args: + __val (object): fixture value object. + request (pytest.FixtureRequest): pytest fixture request object. + + Returns: + object: resolved fixture value. + """ + if isinstance(__val, list | tuple): + return tuple(_resolve_lazy_fixture(v, request) for v in __val) + if isinstance(__val, typing.Mapping): + return {k: _resolve_lazy_fixture(v, request) for k, v in __val.items()} + if not is_lazy_fixture(__val): + return __val + lazy_obj = typing.cast(LazyFixture, __val) + return request.getfixturevalue(lazy_obj.name) |