diff --git a/CHANGELOG.md b/CHANGELOG.md index a2cc998..9fa7a4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Changed - Python 3.9+ is required [#152](https://github.com/python-backoff/backoff/pull/152) +- Simplify `expo`, `decay` and `fibo` wait generators [#183](https://github.com/python-backoff/backoff/pull/183) ### Fixed diff --git a/backoff/_wait_gen.py b/backoff/_wait_gen.py index 48e555d..1231c5e 100644 --- a/backoff/_wait_gen.py +++ b/backoff/_wait_gen.py @@ -24,14 +24,13 @@ def expo( """ # Advance past initial .send() call yield 0 - base_n: float = 1 + + a = factor + while max_value is None or a < max_value: + yield a + a *= base while True: - a = factor * base_n - if max_value is None or a < max_value: - yield a - base_n *= base - else: - yield max_value + yield max_value def decay( @@ -52,14 +51,13 @@ def decay( """ # Advance past initial .send() call yield 0 - t = 0 + a = initial_value + min_value = min_value or 0.0 + while a > min_value: + yield a + a *= math.exp(-decay_factor) while True: - a = initial_value * math.e ** (-t * decay_factor) - if min_value is None or a > min_value: - yield a - t += 1 - else: - yield min_value + yield min_value def fibo(max_value: int | None = None) -> Generator[int, Any, None]: @@ -75,17 +73,14 @@ def fibo(max_value: int | None = None) -> Generator[int, Any, None]: a = 1 b = 1 + while max_value is None or a < max_value: + yield a + a, b = b, a + b while True: - if max_value is None or a < max_value: - yield a - a, b = b, a + b - else: - yield max_value + yield max_value -def constant( - interval: float | Iterable[float] = 1, -) -> Generator[int | float, Any, None]: +def constant(interval: float | Iterable[float] = 1) -> Generator[float, Any, None]: """Generator for constant intervals. Args: @@ -104,10 +99,7 @@ def constant( yield val -def runtime( - *, - value: Callable[[Any], float], -) -> Generator[float, Any, None]: +def runtime(*, value: Callable[[Any], float]) -> Generator[float, Any, None]: """Generator that is based on parsing the return value or thrown exception of the decorated method diff --git a/tests/test_wait_gen.py b/tests/test_wait_gen.py index d2fc238..67cc2ba 100644 --- a/tests/test_wait_gen.py +++ b/tests/test_wait_gen.py @@ -1,7 +1,7 @@ -# ruff: file-ignore[float-equality-comparison] - import math +import pytest + import backoff @@ -9,28 +9,28 @@ def test_decay() -> None: gen = backoff.decay() gen.send(None) for i in range(10): - assert math.e**-i == next(gen) + assert math.e**-i == pytest.approx(next(gen)) def test_decay_init100() -> None: gen = backoff.decay(initial_value=100) gen.send(None) for i in range(10): - assert 100 * math.e**-i == next(gen) + assert 100 * math.e**-i == pytest.approx(next(gen)) def test_decay_init100_decay3() -> None: gen = backoff.decay(initial_value=100, decay_factor=3) gen.send(None) for i in range(10): - assert 100 * math.e ** (-i * 3) == next(gen) + assert 100 * math.e ** (-i * 3) == pytest.approx(next(gen)) def test_decay_init100_decay3_min5() -> None: gen = backoff.decay(initial_value=100, decay_factor=3, min_value=5) gen.send(None) for i in range(10): - assert max(100 * math.e ** (-i * 3), 5) == next(gen) + assert max(100 * math.e ** (-i * 3), 5) == pytest.approx(next(gen)) def test_expo() -> None: @@ -102,8 +102,8 @@ def test_constant() -> None: gen = backoff.constant(interval=[1, 2.0, 3.25]) gen.send(None) assert next(gen) == 1 - assert next(gen) == 2.0 - assert next(gen) == 3.25 + assert next(gen) == pytest.approx(2.0) + assert next(gen) == pytest.approx(3.25) assert next(gen, None) is None