Skip to content

Commit aa96647

Browse files
committed
fix: replace async_timeout by asyncio.timeout
async_timeout does not support python 3.11 aio-libs/async-timeout#295 And have two years old annoying bugs: aio-libs/async-timeout#229 redis#2551 Since asyncio.timeout has been shipped in python 3.11, we should start using it. Partially fixes 2551
1 parent 6c708c2 commit aa96647

File tree

4 files changed

+28
-18
lines changed

4 files changed

+28
-18
lines changed

Diff for: CHANGES

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
* Use asyncio.timeout() instead of async_timeout.timeout() for python >= 3.11 (#2602)
12
* Add test and fix async HiredisParser when reading during a disconnect() (#2349)
23
* Use hiredis-py pack_command if available.
34
* Support `.unlink()` in ClusterPipeline

Diff for: redis/asyncio/connection.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os
66
import socket
77
import ssl
8+
import sys
89
import threading
910
import weakref
1011
from itertools import chain
@@ -24,7 +25,11 @@
2425
)
2526
from urllib.parse import ParseResult, parse_qs, unquote, urlparse
2627

27-
import async_timeout
28+
if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
29+
from asyncio import timeout as async_timeout
30+
else:
31+
from async_timeout import timeout as async_timeout
32+
2833

2934
from redis.asyncio.retry import Retry
3035
from redis.backoff import NoBackoff
@@ -242,7 +247,7 @@ async def can_read_destructive(self) -> bool:
242247
if self._stream is None:
243248
raise RedisError("Buffer is closed.")
244249
try:
245-
async with async_timeout.timeout(0):
250+
async with async_timeout(0):
246251
return await self._stream.read(1)
247252
except asyncio.TimeoutError:
248253
return False
@@ -381,7 +386,7 @@ async def can_read_destructive(self):
381386
if self._reader.gets():
382387
return True
383388
try:
384-
async with async_timeout.timeout(0):
389+
async with async_timeout(0):
385390
return await self.read_from_socket()
386391
except asyncio.TimeoutError:
387392
return False
@@ -636,7 +641,7 @@ async def connect(self):
636641

637642
async def _connect(self):
638643
"""Create a TCP socket connection"""
639-
async with async_timeout.timeout(self.socket_connect_timeout):
644+
async with async_timeout(self.socket_connect_timeout):
640645
reader, writer = await asyncio.open_connection(
641646
host=self.host,
642647
port=self.port,
@@ -723,7 +728,7 @@ async def on_connect(self) -> None:
723728
async def disconnect(self, nowait: bool = False) -> None:
724729
"""Disconnects from the Redis server"""
725730
try:
726-
async with async_timeout.timeout(self.socket_connect_timeout):
731+
async with async_timeout(self.socket_connect_timeout):
727732
self._parser.on_disconnect()
728733
if not self.is_connected:
729734
return
@@ -828,7 +833,7 @@ async def read_response(
828833
read_timeout = timeout if timeout is not None else self.socket_timeout
829834
try:
830835
if read_timeout is not None:
831-
async with async_timeout.timeout(read_timeout):
836+
async with async_timeout(read_timeout):
832837
response = await self._parser.read_response(
833838
disable_decoding=disable_decoding
834839
)
@@ -1119,7 +1124,7 @@ def repr_pieces(self) -> Iterable[Tuple[str, Union[str, int]]]:
11191124
return pieces
11201125

11211126
async def _connect(self):
1122-
async with async_timeout.timeout(self.socket_connect_timeout):
1127+
async with async_timeout(self.socket_connect_timeout):
11231128
reader, writer = await asyncio.open_unix_connection(path=self.path)
11241129
self._reader = reader
11251130
self._writer = writer
@@ -1590,7 +1595,7 @@ async def get_connection(self, command_name, *keys, **options):
15901595
# self.timeout then raise a ``ConnectionError``.
15911596
connection = None
15921597
try:
1593-
async with async_timeout.timeout(self.timeout):
1598+
async with async_timeout(self.timeout):
15941599
connection = await self.pool.get()
15951600
except (asyncio.QueueEmpty, asyncio.TimeoutError):
15961601
# Note that this is not caught by the redis client and will be

Diff for: setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
install_requires=[
3535
'importlib-metadata >= 1.0; python_version < "3.8"',
3636
'typing-extensions; python_version<"3.8"',
37-
"async-timeout>=4.0.2",
37+
'async-timeout>=4.0.2; python_version<"3.11"',
3838
],
3939
classifiers=[
4040
"Development Status :: 5 - Production/Stable",

Diff for: tests/test_asyncio/test_pubsub.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
from typing import Optional
66
from unittest.mock import patch
77

8-
import async_timeout
8+
if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
9+
from asyncio import timeout as async_timeout
10+
else:
11+
from async_timeout import timeout as async_timeout
12+
913
import pytest
1014
import pytest_asyncio
1115

@@ -21,7 +25,7 @@ def with_timeout(t):
2125
def wrapper(corofunc):
2226
@functools.wraps(corofunc)
2327
async def run(*args, **kwargs):
24-
async with async_timeout.timeout(t):
28+
async with async_timeout(t):
2529
return await corofunc(*args, **kwargs)
2630

2731
return run
@@ -648,7 +652,7 @@ async def test_reconnect_listen(self, r: redis.Redis, pubsub):
648652

649653
async def loop():
650654
# must make sure the task exits
651-
async with async_timeout.timeout(2):
655+
async with async_timeout(2):
652656
nonlocal interrupt
653657
await pubsub.subscribe("foo")
654658
while True:
@@ -677,7 +681,7 @@ async def loop_step():
677681

678682
task = asyncio.get_running_loop().create_task(loop())
679683
# get the initial connect message
680-
async with async_timeout.timeout(1):
684+
async with async_timeout(1):
681685
message = await messages.get()
682686
assert message == {
683687
"channel": b"foo",
@@ -776,7 +780,7 @@ def callback(message):
776780
if n == 1:
777781
break
778782
await asyncio.sleep(0.1)
779-
async with async_timeout.timeout(0.1):
783+
async with async_timeout(0.1):
780784
message = await messages.get()
781785
task.cancel()
782786
# we expect a cancelled error, not the Runtime error
@@ -839,7 +843,7 @@ async def test_reconnect_socket_error(self, r: redis.Redis, method):
839843
Test that a socket error will cause reconnect
840844
"""
841845
try:
842-
async with async_timeout.timeout(self.timeout):
846+
async with async_timeout(self.timeout):
843847
await self.mysetup(r, method)
844848
# now, disconnect the connection, and wait for it to be re-established
845849
async with self.cond:
@@ -868,7 +872,7 @@ async def test_reconnect_disconnect(self, r: redis.Redis, method):
868872
Test that a manual disconnect() will cause reconnect
869873
"""
870874
try:
871-
async with async_timeout.timeout(self.timeout):
875+
async with async_timeout(self.timeout):
872876
await self.mysetup(r, method)
873877
# now, disconnect the connection, and wait for it to be re-established
874878
async with self.cond:
@@ -923,7 +927,7 @@ async def loop_step_get_message(self):
923927
async def loop_step_listen(self):
924928
# get a single message via listen()
925929
try:
926-
async with async_timeout.timeout(0.1):
930+
async with async_timeout(0.1):
927931
async for message in self.pubsub.listen():
928932
await self.messages.put(message)
929933
return True
@@ -947,7 +951,7 @@ async def test_outer_timeout(self, r: redis.Redis):
947951
assert pubsub.connection.is_connected
948952

949953
async def get_msg_or_timeout(timeout=0.1):
950-
async with async_timeout.timeout(timeout):
954+
async with async_timeout(timeout):
951955
# blocking method to return messages
952956
while True:
953957
response = await pubsub.parse_response(block=True)

0 commit comments

Comments
 (0)