Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
44 changes: 18 additions & 26 deletions backoff/_wait_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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]:
Expand All @@ -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:
Expand All @@ -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

Expand Down
16 changes: 8 additions & 8 deletions tests/test_wait_gen.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
# ruff: file-ignore[float-equality-comparison]

import math

import pytest

import backoff


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:
Expand Down Expand Up @@ -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


Expand Down