Skip to content

Commit

Permalink
fix: remove __iter__ from AsyncRetring (#387)
Browse files Browse the repository at this point in the history
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 <julien@danjou.info>
  • Loading branch information
sileht and jd authored Feb 6, 2023
1 parent b93e4dc commit 78c8d4b
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 0 deletions.
7 changes: 7 additions & 0 deletions releasenotes/notes/no-async-iter-6132a42e52348a75.yaml
Original file line number Diff line number Diff line change
@@ -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.
3 changes: 3 additions & 0 deletions tenacity/_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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={})
Expand Down
10 changes: 10 additions & 0 deletions tests/test_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

0 comments on commit 78c8d4b

Please sign in to comment.