Skip to content

Commit

Permalink
Merge pull request #29 from Lyncs-API/develop
Browse files Browse the repository at this point in the history
Version 0.5.0
  • Loading branch information
sbacchio authored Mar 22, 2024
2 parents d9018b6 + 5a5db25 commit 4f1678f
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,4 @@ Functions tu use within `pytest`, to be impoted from `lyncs_utils.pytest`

- `DynParam(fnc)`: Dynamic params based on the test function
- `GetMark(map, def)`: Dynamic params based on the marks of the test function
- `lazy_fixture(str)`: Use a fixture as one of the values passed in @pytest.mark.parametrize
2 changes: 1 addition & 1 deletion lyncs_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"Collection of generic-purpose and stand-alone functions"

__version__ = "0.4.5"
__version__ = "0.5.0"

from .math import *
from .logical import *
Expand Down
1 change: 1 addition & 0 deletions lyncs_utils/extensions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Extensions of Python standard functions
"""

# pylint: disable=invalid-name

__all__ = [
Expand Down
105 changes: 104 additions & 1 deletion lyncs_utils/pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
Include this module only within pytest
"""

__all__ = ("DynParam", "GetMark")
__all__ = ("DynParam", "GetMark", "lazy_fixture")

from copy import copy
from dataclasses import dataclass
import typing
import pytest


Expand Down Expand Up @@ -81,3 +82,105 @@ def copy_callspec(callspec):
def is_dyn_param(val):
"Checks if is DynParam"
return isinstance(val, DynParam)


@dataclass
class LazyFixture:
"""Lazy fixture dataclass."""

name: str


def lazy_fixture(name: str) -> LazyFixture:
"""Mark a fixture as lazy.
Credit:
- https://github.com/TvoroG/pytest-lazy-fixture/issues/65#issuecomment-1914581161
"""
return LazyFixture(name)


def is_lazy_fixture(value: object) -> bool:
"""Check whether a value is a lazy fixture.
Credit:
- https://github.com/TvoroG/pytest-lazy-fixture/issues/65#issuecomment-1914581161
"""
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.
Credit:
- https://github.com/TvoroG/pytest-lazy-fixture/issues/65#issuecomment-1914581161
"""
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.
Credit:
- https://github.com/TvoroG/pytest-lazy-fixture/issues/65#issuecomment-1914581161
"""
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.
Credit:
- https://github.com/TvoroG/pytest-lazy-fixture/issues/65#issuecomment-1914581161
"""
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)
2 changes: 1 addition & 1 deletion test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def test_iscomplex():
def test_isclose():
assert isclose(1, 1.0001, abs_tol=0.0001)
assert not isclose(1, 1.0002, abs_tol=0.0001)
with warns(None):
with warns():
assert isclose(1, 1.01, warn_tol=0.1)
assert isclose(1j, 1.0001j, abs_tol=0.0001)
assert isclose(1j, 1.0001j, rel_tol=0.0001)
Expand Down
17 changes: 16 additions & 1 deletion test/test_pytest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from lyncs_utils.pytest import GetMark, DynParam
from lyncs_utils.pytest import GetMark, DynParam, lazy_fixture


@pytest.fixture(params=[GetMark({"mark1": [11], "mark2": [12]}, default="mark1")])
Expand Down Expand Up @@ -35,3 +35,18 @@ def test_mark2(param1, param2, name):
assert param1 == 12
assert param2 == 21
assert name == "test_mark2"


@pytest.fixture
def one():
return 1


@pytest.mark.parametrize(
"arg1,arg2",
[
("val1", lazy_fixture("one")),
],
)
def test_func(arg1, arg2):
assert arg2 == 1

0 comments on commit 4f1678f

Please sign in to comment.