From 78c8d4bc8596af1143801076faa922f2f21c1bba Mon Sep 17 00:00:00 2001 From: Mehdi ABAAKOUK Date: Mon, 6 Feb 2023 11:29:32 +0100 Subject: [PATCH] fix: remove __iter__ from AsyncRetring (#387) This method doesn't make sense for AsyncRetrying. And it's even more vicious as: ``` for attempts in AsyncRetrying(): with attempts: await do_for_a_while() ``` will work, but sleep(XXX) coroutine will never be awaited and the call is retried instantly. This change removes the __iter__ method from AsyncRetrying. Co-authored-by: Julien Danjou --- releasenotes/notes/no-async-iter-6132a42e52348a75.yaml | 7 +++++++ tenacity/_asyncio.py | 3 +++ tests/test_asyncio.py | 10 ++++++++++ 3 files changed, 20 insertions(+) create mode 100644 releasenotes/notes/no-async-iter-6132a42e52348a75.yaml diff --git a/releasenotes/notes/no-async-iter-6132a42e52348a75.yaml b/releasenotes/notes/no-async-iter-6132a42e52348a75.yaml new file mode 100644 index 00000000..7a92c1b5 --- /dev/null +++ b/releasenotes/notes/no-async-iter-6132a42e52348a75.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + `AsyncRetrying` was erroneously implementing `__iter__()`, making tenacity + retrying mechanism working but in a synchronous fashion and not waiting as + expected. This interface has been removed, `__aiter__()` should be used + instead. diff --git a/tenacity/_asyncio.py b/tenacity/_asyncio.py index 0b0f8765..ab88d26b 100644 --- a/tenacity/_asyncio.py +++ b/tenacity/_asyncio.py @@ -62,6 +62,9 @@ async def __call__( # type: ignore[override] else: return do # type: ignore[no-any-return] + def __iter__(self) -> typing.Generator[AttemptManager, None, None]: + raise TypeError("AsyncRetrying object is not iterable") + def __aiter__(self) -> "AsyncRetrying": self.begin() self._retry_state = RetryCallState(self, fn=None, args=(), kwargs={}) diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index f6e9b0d8..66096beb 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -18,6 +18,8 @@ import unittest from functools import wraps +import pytest + from tenacity import AsyncRetrying, RetryError from tenacity import _asyncio as tasyncio from tenacity import retry, retry_if_result, stop_after_attempt @@ -169,6 +171,14 @@ async def test(): self.assertEqual(3, result) + @asynctest + async def test_async_retying_iterator(self): + thing = NoIOErrorAfterCount(5) + with pytest.raises(TypeError): + for attempts in AsyncRetrying(): + with attempts: + await _async_function(thing) + if __name__ == "__main__": unittest.main()