diff --git a/releasenotes/notes/fix-wait-chain-keyword-state-7c2f5b9e04a1d836.yaml b/releasenotes/notes/fix-wait-chain-keyword-state-7c2f5b9e04a1d836.yaml new file mode 100644 index 00000000..c00e491c --- /dev/null +++ b/releasenotes/notes/fix-wait-chain-keyword-state-7c2f5b9e04a1d836.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + ``wait_chain`` now passes the retry state positionally, matching how + ``wait_combine`` and ``BaseRetrying`` invoke ``wait``. It previously + passed it as the keyword ``retry_state=``, which crashed on any callable + whose parameter had a different name. diff --git a/tenacity/wait.py b/tenacity/wait.py index 6607e4fd..3cdfbde7 100644 --- a/tenacity/wait.py +++ b/tenacity/wait.py @@ -123,7 +123,7 @@ def wait_chained(): "thereafter.") """ - def __init__(self, *strategies: wait_base) -> None: + def __init__(self, *strategies: "WaitBaseT") -> None: if not strategies: raise ValueError("wait_chain() requires at least one strategy") self.strategies = strategies @@ -132,7 +132,9 @@ def __init__(self, *strategies: wait_base) -> None: def __call__(self, retry_state: "RetryCallState") -> float: wait_func_no = min(max(retry_state.attempt_number, 1), len(self.strategies)) wait_func = self.strategies[wait_func_no - 1] - return wait_func(retry_state=retry_state) + # Positional, like `wait_combine`: a `WaitBaseT` callable is only + # guaranteed to take the state positionally. + return wait_func(retry_state) class wait_exception(wait_base): diff --git a/tests/test_tenacity.py b/tests/test_tenacity.py index 95ab8117..8b927e5e 100644 --- a/tests/test_tenacity.py +++ b/tests/test_tenacity.py @@ -612,6 +612,12 @@ def test_wait_chain_requires_at_least_one_strategy(self) -> None: with self.assertRaises(ValueError): Retrying(wait=tenacity.wait_chain()) + def test_wait_chain_passes_state_positionally(self) -> None: + # A WaitBaseT callable only promises to take the state positionally; + # its parameter name is its own business. + chained = tenacity.wait_chain(lambda rs: 2.0) + self.assertEqual(chained(make_retry_state(1, 5)), 2.0) + def test_wait_random_exponential(self) -> None: fn = tenacity.wait_random_exponential(0.5, 60.0)