Skip to content

Commit

Permalink
Drop dependency on the abandoned python-lazy-fixture
Browse files Browse the repository at this point in the history
  • Loading branch information
jkbrzt committed Mar 4, 2024
1 parent 8ac44b5 commit 3524ccf
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 4 deletions.
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
tests_require = [
'pytest',
'pytest-httpbin>=0.0.6',
'pytest-lazy-fixture>=0.0.6',
'responses',
'pytest-mock',
'werkzeug<2.1.0'
Expand Down
8 changes: 5 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@
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,
httpie_plugins,
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)
Expand Down
99 changes: 99 additions & 0 deletions tests/fixtures/pytest_lazy_fixture.py
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 3524ccf

Please sign in to comment.