Skip to content

Commit b1c98ef

Browse files
authored
Merge pull request #215 from andersea/master
Use PEP 492 async/await syntax
2 parents 49c67bd + d49d2dc commit b1c98ef

File tree

3 files changed

+44
-63
lines changed

3 files changed

+44
-63
lines changed

tenacity/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
# limitations under the License.
1919

2020
try:
21-
import asyncio
21+
from inspect import iscoroutinefunction
2222
except ImportError:
23-
asyncio = None
23+
iscoroutinefunction = None
2424

2525
try:
2626
import tornado
@@ -96,7 +96,7 @@ def retry(*dargs, **dkw):
9696
return retry()(dargs[0])
9797
else:
9898
def wrap(f):
99-
if asyncio and asyncio.iscoroutinefunction(f):
99+
if iscoroutinefunction is not None and iscoroutinefunction(f):
100100
r = AsyncRetrying(*dargs, **dkw)
101101
elif tornado and hasattr(tornado.gen, 'is_coroutine_function') \
102102
and tornado.gen.is_coroutine_function(f):
@@ -479,7 +479,7 @@ def set_exception(self, exc_info):
479479
self.outcome, self.outcome_timestamp = fut, ts
480480

481481

482-
if asyncio:
482+
if iscoroutinefunction:
483483
from tenacity._asyncio import AsyncRetrying
484484

485485
if tornado:

tenacity/_asyncio.py

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,39 @@
1616
# See the License for the specific language governing permissions and
1717
# limitations under the License.
1818

19-
try:
20-
import asyncio
21-
except ImportError:
22-
asyncio = None
23-
2419
import sys
20+
from asyncio import sleep
2521

2622
from tenacity import BaseRetrying
2723
from tenacity import DoAttempt
2824
from tenacity import DoSleep
2925
from tenacity import RetryCallState
3026

3127

32-
if asyncio:
33-
class AsyncRetrying(BaseRetrying):
34-
35-
def __init__(self,
36-
sleep=asyncio.sleep,
37-
**kwargs):
38-
super(AsyncRetrying, self).__init__(**kwargs)
39-
self.sleep = sleep
28+
class AsyncRetrying(BaseRetrying):
4029

41-
def wraps(self, fn):
42-
fn = super().wraps(fn)
43-
# Ensure wrapper is recognized as a coroutine function.
44-
fn._is_coroutine = asyncio.coroutines._is_coroutine
45-
return fn
30+
def __init__(self,
31+
sleep=sleep,
32+
**kwargs):
33+
super(AsyncRetrying, self).__init__(**kwargs)
34+
self.sleep = sleep
4635

47-
@asyncio.coroutine
48-
def call(self, fn, *args, **kwargs):
49-
self.begin(fn)
36+
async def call(self, fn, *args, **kwargs):
37+
self.begin(fn)
5038

51-
retry_state = RetryCallState(
52-
retry_object=self, fn=fn, args=args, kwargs=kwargs)
53-
while True:
54-
do = self.iter(retry_state=retry_state)
55-
if isinstance(do, DoAttempt):
56-
try:
57-
result = yield from fn(*args, **kwargs)
58-
except BaseException:
59-
retry_state.set_exception(sys.exc_info())
60-
else:
61-
retry_state.set_result(result)
62-
elif isinstance(do, DoSleep):
63-
retry_state.prepare_for_next_attempt()
64-
yield from self.sleep(do)
39+
retry_state = RetryCallState(
40+
retry_object=self, fn=fn, args=args, kwargs=kwargs)
41+
while True:
42+
do = self.iter(retry_state=retry_state)
43+
if isinstance(do, DoAttempt):
44+
try:
45+
result = await fn(*args, **kwargs)
46+
except BaseException:
47+
retry_state.set_exception(sys.exc_info())
6548
else:
66-
return do
49+
retry_state.set_result(result)
50+
elif isinstance(do, DoSleep):
51+
retry_state.prepare_for_next_attempt()
52+
await self.sleep(do)
53+
else:
54+
return do

tenacity/tests/test_asyncio.py

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525

2626

2727
def asynctest(callable_):
28-
callable_ = asyncio.coroutine(callable_)
29-
3028
@six.wraps(callable_)
3129
def wrapper(*a, **kw):
3230
loop = asyncio.get_event_loop()
@@ -42,35 +40,31 @@ async def _retryable_coroutine(thing):
4240

4341

4442
@retry(stop=stop_after_attempt(2))
45-
@asyncio.coroutine
46-
def _retryable_coroutine_with_2_attempts(thing):
47-
yield from asyncio.sleep(0.00001)
43+
async def _retryable_coroutine_with_2_attempts(thing):
44+
await asyncio.sleep(0.00001)
4845
thing.go()
4946

5047

5148
class TestAsync(unittest.TestCase):
5249
@asynctest
53-
def test_retry(self):
54-
assert asyncio.iscoroutinefunction(_retryable_coroutine)
50+
async def test_retry(self):
5551
thing = NoIOErrorAfterCount(5)
56-
yield from _retryable_coroutine(thing)
52+
await _retryable_coroutine(thing)
5753
assert thing.counter == thing.count
5854

5955
@asynctest
60-
def test_stop_after_attempt(self):
61-
assert asyncio.iscoroutinefunction(
62-
_retryable_coroutine_with_2_attempts)
56+
async def test_stop_after_attempt(self):
6357
thing = NoIOErrorAfterCount(2)
6458
try:
65-
yield from _retryable_coroutine_with_2_attempts(thing)
59+
await _retryable_coroutine_with_2_attempts(thing)
6660
except RetryError:
6761
assert thing.counter == 2
6862

6963
def test_repr(self):
7064
repr(tasyncio.AsyncRetrying())
7165

7266
@asynctest
73-
def test_attempt_number_is_correct_for_interleaved_coroutines(self):
67+
async def test_attempt_number_is_correct_for_interleaved_coroutines(self):
7468

7569
attempts = []
7670

@@ -79,22 +73,21 @@ def after(retry_state):
7973

8074
thing1 = NoIOErrorAfterCount(3)
8175
thing2 = NoIOErrorAfterCount(3)
82-
future1 = asyncio.ensure_future(
83-
_retryable_coroutine.retry_with(after=after)(thing1))
84-
future2 = asyncio.ensure_future(
76+
77+
await asyncio.gather(
78+
_retryable_coroutine.retry_with(after=after)(thing1),
8579
_retryable_coroutine.retry_with(after=after)(thing2))
86-
yield from asyncio.gather(future1, future2)
8780

8881
# There's no waiting on retry, only a wait in the coroutine, so the
8982
# executions should be interleaved.
90-
thing1_attempts = attempts[::2]
91-
things1, attempt_nos1 = zip(*thing1_attempts)
92-
assert all(thing is thing1 for thing in things1)
83+
even_thing_attempts = attempts[::2]
84+
things, attempt_nos1 = zip(*even_thing_attempts)
85+
assert len(set(things)) == 1
9386
assert list(attempt_nos1) == [1, 2, 3]
9487

95-
thing2_attempts = attempts[1::2]
96-
things2, attempt_nos2 = zip(*thing2_attempts)
97-
assert all(thing is thing2 for thing in things2)
88+
odd_thing_attempts = attempts[1::2]
89+
things, attempt_nos2 = zip(*odd_thing_attempts)
90+
assert len(set(things)) == 1
9891
assert list(attempt_nos2) == [1, 2, 3]
9992

10093

0 commit comments

Comments
 (0)