summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMehdi ABAAKOUK <sileht@sileht.net>2023-03-16 12:51:19 +0100
committerGitHub <noreply@github.com>2023-03-16 13:51:19 +0200
commit25e85e51e57b7aae9eb8fc77cfb0a45a07a501a7 (patch)
tree9b781b1b730dcd14bdfb10f0ba8a96c2866256f7
parent91ab12a0f1bdf0e433131e1a51578e9fa2f89718 (diff)
downloadredis-py-25e85e51e57b7aae9eb8fc77cfb0a45a07a501a7.tar.gz
fix: replace async_timeout by asyncio.timeout (#2602)
async_timeout does not support python 3.11 https://github.com/aio-libs/async-timeout/pull/295 And have two years old annoying bugs: https://github.com/aio-libs/async-timeout/issues/229 https://github.com/redis/redis-py/issues/2551 Since asyncio.timeout has been shipped in python 3.11, we should start using it. Partially fixes 2551
-rw-r--r--CHANGES1
-rw-r--r--redis/asyncio/connection.py21
-rw-r--r--setup.py2
-rw-r--r--tests/test_asyncio/test_pubsub.py22
4 files changed, 28 insertions, 18 deletions
diff --git a/CHANGES b/CHANGES
index e83660d..3e4eba4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
+ * Use asyncio.timeout() instead of async_timeout.timeout() for python >= 3.11 (#2602)
* Add test and fix async HiredisParser when reading during a disconnect() (#2349)
* Use hiredis-py pack_command if available.
* Support `.unlink()` in ClusterPipeline
diff --git a/redis/asyncio/connection.py b/redis/asyncio/connection.py
index 056998e..93db37e 100644
--- a/redis/asyncio/connection.py
+++ b/redis/asyncio/connection.py
@@ -5,6 +5,7 @@ import inspect
import os
import socket
import ssl
+import sys
import threading
import weakref
from itertools import chain
@@ -24,7 +25,11 @@ from typing import (
)
from urllib.parse import ParseResult, parse_qs, unquote, urlparse
-import async_timeout
+if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
+ from asyncio import timeout as async_timeout
+else:
+ from async_timeout import timeout as async_timeout
+
from redis.asyncio.retry import Retry
from redis.backoff import NoBackoff
@@ -242,7 +247,7 @@ class PythonParser(BaseParser):
if self._stream is None:
raise RedisError("Buffer is closed.")
try:
- async with async_timeout.timeout(0):
+ async with async_timeout(0):
return await self._stream.read(1)
except asyncio.TimeoutError:
return False
@@ -380,7 +385,7 @@ class HiredisParser(BaseParser):
if self._reader.gets():
return True
try:
- async with async_timeout.timeout(0):
+ async with async_timeout(0):
return await self.read_from_socket()
except asyncio.TimeoutError:
return False
@@ -635,7 +640,7 @@ class Connection:
async def _connect(self):
"""Create a TCP socket connection"""
- async with async_timeout.timeout(self.socket_connect_timeout):
+ async with async_timeout(self.socket_connect_timeout):
reader, writer = await asyncio.open_connection(
host=self.host,
port=self.port,
@@ -722,7 +727,7 @@ class Connection:
async def disconnect(self, nowait: bool = False) -> None:
"""Disconnects from the Redis server"""
try:
- async with async_timeout.timeout(self.socket_connect_timeout):
+ async with async_timeout(self.socket_connect_timeout):
self._parser.on_disconnect()
if not self.is_connected:
return
@@ -827,7 +832,7 @@ class Connection:
read_timeout = timeout if timeout is not None else self.socket_timeout
try:
if read_timeout is not None:
- async with async_timeout.timeout(read_timeout):
+ async with async_timeout(read_timeout):
response = await self._parser.read_response(
disable_decoding=disable_decoding
)
@@ -1118,7 +1123,7 @@ class UnixDomainSocketConnection(Connection): # lgtm [py/missing-call-to-init]
return pieces
async def _connect(self):
- async with async_timeout.timeout(self.socket_connect_timeout):
+ async with async_timeout(self.socket_connect_timeout):
reader, writer = await asyncio.open_unix_connection(path=self.path)
self._reader = reader
self._writer = writer
@@ -1589,7 +1594,7 @@ class BlockingConnectionPool(ConnectionPool):
# self.timeout then raise a ``ConnectionError``.
connection = None
try:
- async with async_timeout.timeout(self.timeout):
+ async with async_timeout(self.timeout):
connection = await self.pool.get()
except (asyncio.QueueEmpty, asyncio.TimeoutError):
# Note that this is not caught by the redis client and will be
diff --git a/setup.py b/setup.py
index 060e9da..ceeeb81 100644
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,7 @@ setup(
install_requires=[
'importlib-metadata >= 1.0; python_version < "3.8"',
'typing-extensions; python_version<"3.8"',
- "async-timeout>=4.0.2",
+ 'async-timeout>=4.0.2; python_version<"3.11"',
],
classifiers=[
"Development Status :: 5 - Production/Stable",
diff --git a/tests/test_asyncio/test_pubsub.py b/tests/test_asyncio/test_pubsub.py
index c2a9130..0df7847 100644
--- a/tests/test_asyncio/test_pubsub.py
+++ b/tests/test_asyncio/test_pubsub.py
@@ -5,7 +5,11 @@ import sys
from typing import Optional
from unittest.mock import patch
-import async_timeout
+if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
+ from asyncio import timeout as async_timeout
+else:
+ from async_timeout import timeout as async_timeout
+
import pytest
import pytest_asyncio
@@ -21,7 +25,7 @@ def with_timeout(t):
def wrapper(corofunc):
@functools.wraps(corofunc)
async def run(*args, **kwargs):
- async with async_timeout.timeout(t):
+ async with async_timeout(t):
return await corofunc(*args, **kwargs)
return run
@@ -648,7 +652,7 @@ class TestPubSubReconnect:
async def loop():
# must make sure the task exits
- async with async_timeout.timeout(2):
+ async with async_timeout(2):
nonlocal interrupt
await pubsub.subscribe("foo")
while True:
@@ -677,7 +681,7 @@ class TestPubSubReconnect:
task = asyncio.get_running_loop().create_task(loop())
# get the initial connect message
- async with async_timeout.timeout(1):
+ async with async_timeout(1):
message = await messages.get()
assert message == {
"channel": b"foo",
@@ -776,7 +780,7 @@ class TestPubSubRun:
if n == 1:
break
await asyncio.sleep(0.1)
- async with async_timeout.timeout(0.1):
+ async with async_timeout(0.1):
message = await messages.get()
task.cancel()
# we expect a cancelled error, not the Runtime error
@@ -839,7 +843,7 @@ class TestPubSubAutoReconnect:
Test that a socket error will cause reconnect
"""
try:
- async with async_timeout.timeout(self.timeout):
+ async with async_timeout(self.timeout):
await self.mysetup(r, method)
# now, disconnect the connection, and wait for it to be re-established
async with self.cond:
@@ -868,7 +872,7 @@ class TestPubSubAutoReconnect:
Test that a manual disconnect() will cause reconnect
"""
try:
- async with async_timeout.timeout(self.timeout):
+ async with async_timeout(self.timeout):
await self.mysetup(r, method)
# now, disconnect the connection, and wait for it to be re-established
async with self.cond:
@@ -923,7 +927,7 @@ class TestPubSubAutoReconnect:
async def loop_step_listen(self):
# get a single message via listen()
try:
- async with async_timeout.timeout(0.1):
+ async with async_timeout(0.1):
async for message in self.pubsub.listen():
await self.messages.put(message)
return True
@@ -947,7 +951,7 @@ class TestBaseException:
assert pubsub.connection.is_connected
async def get_msg_or_timeout(timeout=0.1):
- async with async_timeout.timeout(timeout):
+ async with async_timeout(timeout):
# blocking method to return messages
while True:
response = await pubsub.parse_response(block=True)