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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

- Apply the Ruff `FA` rules [#104](https://github.com/python-backoff/backoff/pull/104) (from [@edgarrmondragon](https://github.com/edgarrmondragon))

- Check types with [`ty`](https://docs.astral.sh/ty/) and update some type annotations [#179](https://github.com/python-backoff/backoff/pull/179)

## [v2.3.1] - 2025-12-18

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion backoff/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def _config_handlers(
assert log_level is not None, "Log level is not specified"
# bind the specified logger to the default log handler
log_handler = functools.partial(
default_handler,
default_handler, # ty:ignore[invalid-argument-type]
logger=logger,
log_level=log_level,
)
Expand Down
4 changes: 2 additions & 2 deletions backoff/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ class Details(_Details, total=False):
_MaybeCallable = Union[T, Callable[[], T]]
_MaybeLogger = Union[str, logging.Logger, logging.LoggerAdapter, None]
_MaybeSequence = Union[T, Sequence[T]]
_Predicate = Callable[[T], bool]
_WaitGenerator = Callable[..., Generator[float, None, None]]
_Predicate = Union[Callable[[T], bool], Callable[[T], Coroutine[T, None, bool]]]
_WaitGenerator = Callable[..., Generator[Union[float, None], None, None]]
14 changes: 7 additions & 7 deletions backoff/_wait_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def expo(
base: float = 2,
factor: float = 1,
max_value: float | None = None,
) -> Generator[float, Any, None]:
) -> Generator[float | None, Any, None]:
"""Generator for exponential decay.

Args:
Expand All @@ -38,7 +38,7 @@ def decay(
initial_value: float = 1,
decay_factor: float = 1,
min_value: float | None = None,
) -> Generator[float, Any, None]:
) -> Generator[float | None, Any, None]:
"""Generator for exponential decay[1]:

Args:
Expand All @@ -62,7 +62,7 @@ def decay(
yield min_value


def fibo(max_value: int | None = None) -> Generator[int, None, None]:
def fibo(max_value: int | None = None) -> Generator[int | None, None, None]:
"""Generator for fibonaccial decay.

Args:
Expand All @@ -85,7 +85,7 @@ def fibo(max_value: int | None = None) -> Generator[int, None, None]:

def constant(
interval: int | Iterable[float] = 1,
) -> Generator[float, None, None]:
) -> Generator[int | float | None, None, None]:
"""Generator for constant intervals.

Args:
Expand All @@ -97,16 +97,16 @@ def constant(
try:
itr = iter(interval) # type: ignore
except TypeError:
itr = itertools.repeat(interval) # type: ignore
itr = itertools.repeat(interval) # type: ignore[arg-type]

for val in itr:
yield val
yield val # ty:ignore[invalid-yield]


def runtime(
*,
value: Callable[[Any], float],
) -> Generator[float, None, None]:
) -> Generator[float | None, None, None]:
"""Generator that is based on parsing the return value or thrown
exception of the decorated method

Expand Down
10 changes: 10 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ test = [
typing = [
{ include-group = "test" },
"mypy>=0.942",
"ty>=0.0.59",
"types-requests>=2.27.20",
]

Expand Down Expand Up @@ -134,6 +135,15 @@ commands = [
"tests",
], extend = true },
],
[
"ty",
"check",
{ replace = "if", condition = "env.GITHUB_ACTIONS == 'true'", then = [ "--output-format=github" ], else = [], extend = true },
{ replace = "posargs", default = [
"backoff",
"tests",
], extend = true },
],
]

[tool.tox.env.docs]
Expand Down
15 changes: 8 additions & 7 deletions tests/test_backoff.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
import random
import re
import sys
import threading
Expand Down Expand Up @@ -531,7 +530,6 @@ def emptiness(*args, **kwargs):
# on_predicate should support 0-argument jitter function.
def test_on_exception_success_0_arg_jitter(monkeypatch):
monkeypatch.setattr("time.sleep", lambda x: None)
monkeypatch.setattr("random.random", lambda: 0)

backoffs, giveups, successes = [], [], []

Expand All @@ -541,7 +539,7 @@ def test_on_exception_success_0_arg_jitter(monkeypatch):
on_success=successes.append,
on_backoff=backoffs.append,
on_giveup=giveups.append,
jitter=random.random,
jitter=lambda: 0.0, # ty:ignore[invalid-argument-type]
interval=0,
)
@_save_target
Expand All @@ -550,7 +548,9 @@ def succeeder(*args, **kwargs):
if len(backoffs) < 2:
raise ValueError("catch me")

with pytest.deprecated_call():
with pytest.deprecated_call(
match="Nullary jitter function signature is deprecated",
):
succeeder(1, 2, 3, foo=1, bar=2)

# we try 3 times, backing off twice before succeeding
Expand Down Expand Up @@ -587,7 +587,6 @@ def succeeder(*args, **kwargs):
# on_predicate should support 0-argument jitter function.
def test_on_predicate_success_0_arg_jitter(monkeypatch):
monkeypatch.setattr("time.sleep", lambda x: None)
monkeypatch.setattr("random.random", lambda: 0)

backoffs, giveups, successes = [], [], []

Expand All @@ -596,15 +595,17 @@ def test_on_predicate_success_0_arg_jitter(monkeypatch):
on_success=successes.append,
on_backoff=backoffs.append,
on_giveup=giveups.append,
jitter=random.random,
jitter=lambda: 0.0, # ty:ignore[invalid-argument-type]
interval=0,
)
@_save_target
def success(*args, **kwargs):
# succeed after we've backed off twice
return len(backoffs) == 2

with pytest.deprecated_call():
with pytest.deprecated_call(
match="Nullary jitter function signature is deprecated",
):
success(1, 2, 3, foo=1, bar=2)

# we try 3 times, backing off twice before succeeding
Expand Down
17 changes: 9 additions & 8 deletions tests/test_backoff_async.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio # Python 3.5 code and syntax is allowed in this file
import random

import pytest

Expand Down Expand Up @@ -347,7 +346,7 @@ async def foo_bar_baz():
async def test_on_exception_giveup_coro(monkeypatch):
monkeypatch.setattr("asyncio.sleep", _await_none)

async def on_baz(e):
async def on_baz(e: Exception) -> bool:
return str(e) == "baz"

vals = ["baz", "bar", "foo"]
Expand Down Expand Up @@ -518,7 +517,6 @@ async def falsey():
@pytest.mark.asyncio
async def test_on_exception_success_0_arg_jitter(monkeypatch):
monkeypatch.setattr("asyncio.sleep", _await_none)
monkeypatch.setattr("random.random", lambda: 0)

log, log_success, log_backoff, log_giveup = _log_hdlrs()

Expand All @@ -528,7 +526,7 @@ async def test_on_exception_success_0_arg_jitter(monkeypatch):
on_success=log_success,
on_backoff=log_backoff,
on_giveup=log_giveup,
jitter=random.random,
jitter=lambda: 0.0, # ty:ignore[invalid-argument-type]
interval=0,
)
@_save_target
Expand All @@ -537,7 +535,9 @@ async def succeeder(*args, **kwargs):
if len(log["backoff"]) < 2:
raise ValueError("catch me")

with pytest.deprecated_call():
with pytest.deprecated_call(
match="Nullary jitter function signature is deprecated",
):
await succeeder(1, 2, 3, foo=1, bar=2)

# we try 3 times, backing off twice before succeeding
Expand Down Expand Up @@ -575,7 +575,6 @@ async def succeeder(*args, **kwargs):
@pytest.mark.asyncio
async def test_on_predicate_success_0_arg_jitter(monkeypatch):
monkeypatch.setattr("asyncio.sleep", _await_none)
monkeypatch.setattr("random.random", lambda: 0)

log, log_success, log_backoff, log_giveup = _log_hdlrs()

Expand All @@ -584,15 +583,17 @@ async def test_on_predicate_success_0_arg_jitter(monkeypatch):
on_success=log_success,
on_backoff=log_backoff,
on_giveup=log_giveup,
jitter=random.random,
jitter=lambda: 0.0, # ty:ignore[invalid-argument-type]
interval=0,
)
@_save_target
async def success(*args, **kwargs):
# succeed after we've backed off twice
return len(log["backoff"]) == 2

with pytest.deprecated_call():
with pytest.deprecated_call(
match="Nullary jitter function signature is deprecated",
):
await success(1, 2, 3, foo=1, bar=2)

# we try 3 times, backing off twice before succeeding
Expand Down
2 changes: 1 addition & 1 deletion tests/test_wait_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ def test_runtime():
gen = backoff.runtime(value=lambda x: x)
gen.send(None)
for i in range(20):
assert i == gen.send(i)
assert i == gen.send(i) # ty:ignore[invalid-argument-type]
Loading