Skip to content

Commit 8427c7b

Browse files
authored
Deprecating unused arguments in connection pools's get_connection functions (#3517)
1 parent 799716c commit 8427c7b

19 files changed

+196
-113
lines changed

redis/asyncio/client.py

+6-10
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ async def initialize(self: _RedisT) -> _RedisT:
375375
if self.single_connection_client:
376376
async with self._single_conn_lock:
377377
if self.connection is None:
378-
self.connection = await self.connection_pool.get_connection("_")
378+
self.connection = await self.connection_pool.get_connection()
379379

380380
self._event_dispatcher.dispatch(
381381
AfterSingleConnectionInstantiationEvent(
@@ -638,7 +638,7 @@ async def execute_command(self, *args, **options):
638638
await self.initialize()
639639
pool = self.connection_pool
640640
command_name = args[0]
641-
conn = self.connection or await pool.get_connection(command_name, **options)
641+
conn = self.connection or await pool.get_connection()
642642

643643
if self.single_connection_client:
644644
await self._single_conn_lock.acquire()
@@ -712,7 +712,7 @@ def __init__(self, connection_pool: ConnectionPool):
712712

713713
async def connect(self):
714714
if self.connection is None:
715-
self.connection = await self.connection_pool.get_connection("MONITOR")
715+
self.connection = await self.connection_pool.get_connection()
716716

717717
async def __aenter__(self):
718718
await self.connect()
@@ -900,9 +900,7 @@ async def connect(self):
900900
Ensure that the PubSub is connected
901901
"""
902902
if self.connection is None:
903-
self.connection = await self.connection_pool.get_connection(
904-
"pubsub", self.shard_hint
905-
)
903+
self.connection = await self.connection_pool.get_connection()
906904
# register a callback that re-subscribes to any channels we
907905
# were listening to when we were disconnected
908906
self.connection.register_connect_callback(self.on_connect)
@@ -1370,9 +1368,7 @@ async def immediate_execute_command(self, *args, **options):
13701368
conn = self.connection
13711369
# if this is the first call, we need a connection
13721370
if not conn:
1373-
conn = await self.connection_pool.get_connection(
1374-
command_name, self.shard_hint
1375-
)
1371+
conn = await self.connection_pool.get_connection()
13761372
self.connection = conn
13771373

13781374
return await conn.retry.call_with_retry(
@@ -1568,7 +1564,7 @@ async def execute(self, raise_on_error: bool = True) -> List[Any]:
15681564

15691565
conn = self.connection
15701566
if not conn:
1571-
conn = await self.connection_pool.get_connection("MULTI", self.shard_hint)
1567+
conn = await self.connection_pool.get_connection()
15721568
# assign to self.connection so reset() releases the connection
15731569
# back to the pool after we're done
15741570
self.connection = conn

redis/asyncio/connection.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
from ..auth.token import TokenInterface
3131
from ..event import AsyncAfterConnectionReleasedEvent, EventDispatcher
32-
from ..utils import format_error_message
32+
from ..utils import deprecated_args, format_error_message
3333

3434
# the functionality is available in 3.11.x but has a major issue before
3535
# 3.11.3. See https://github.com/redis/redis-py/issues/2633
@@ -1087,7 +1087,12 @@ def can_get_connection(self) -> bool:
10871087
or len(self._in_use_connections) < self.max_connections
10881088
)
10891089

1090-
async def get_connection(self, command_name, *keys, **options):
1090+
@deprecated_args(
1091+
args_to_warn=["*"],
1092+
reason="Use get_connection() without args instead",
1093+
version="5.0.3",
1094+
)
1095+
async def get_connection(self, command_name=None, *keys, **options):
10911096
async with self._lock:
10921097
"""Get a connected connection from the pool"""
10931098
connection = self.get_available_connection()
@@ -1255,7 +1260,12 @@ def __init__(
12551260
self._condition = asyncio.Condition()
12561261
self.timeout = timeout
12571262

1258-
async def get_connection(self, command_name, *keys, **options):
1263+
@deprecated_args(
1264+
args_to_warn=["*"],
1265+
reason="Use get_connection() without args instead",
1266+
version="5.0.3",
1267+
)
1268+
async def get_connection(self, command_name=None, *keys, **options):
12591269
"""Gets a connection from the pool, blocking until one is available"""
12601270
try:
12611271
async with self._condition:

redis/client.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ def __init__(
366366
self.connection = None
367367
self._single_connection_client = single_connection_client
368368
if self._single_connection_client:
369-
self.connection = self.connection_pool.get_connection("_")
369+
self.connection = self.connection_pool.get_connection()
370370
self._event_dispatcher.dispatch(
371371
AfterSingleConnectionInstantiationEvent(
372372
self.connection, ClientType.SYNC, self.single_connection_lock
@@ -608,7 +608,7 @@ def _execute_command(self, *args, **options):
608608
"""Execute a command and return a parsed response"""
609609
pool = self.connection_pool
610610
command_name = args[0]
611-
conn = self.connection or pool.get_connection(command_name, **options)
611+
conn = self.connection or pool.get_connection()
612612

613613
if self._single_connection_client:
614614
self.single_connection_lock.acquire()
@@ -667,7 +667,7 @@ class Monitor:
667667

668668
def __init__(self, connection_pool):
669669
self.connection_pool = connection_pool
670-
self.connection = self.connection_pool.get_connection("MONITOR")
670+
self.connection = self.connection_pool.get_connection()
671671

672672
def __enter__(self):
673673
self.connection.send_command("MONITOR")
@@ -840,9 +840,7 @@ def execute_command(self, *args):
840840
# subscribed to one or more channels
841841

842842
if self.connection is None:
843-
self.connection = self.connection_pool.get_connection(
844-
"pubsub", self.shard_hint
845-
)
843+
self.connection = self.connection_pool.get_connection()
846844
# register a callback that re-subscribes to any channels we
847845
# were listening to when we were disconnected
848846
self.connection.register_connect_callback(self.on_connect)
@@ -1397,7 +1395,7 @@ def immediate_execute_command(self, *args, **options):
13971395
conn = self.connection
13981396
# if this is the first call, we need a connection
13991397
if not conn:
1400-
conn = self.connection_pool.get_connection(command_name, self.shard_hint)
1398+
conn = self.connection_pool.get_connection()
14011399
self.connection = conn
14021400

14031401
return conn.retry.call_with_retry(
@@ -1583,7 +1581,7 @@ def execute(self, raise_on_error: bool = True) -> List[Any]:
15831581

15841582
conn = self.connection
15851583
if not conn:
1586-
conn = self.connection_pool.get_connection("MULTI", self.shard_hint)
1584+
conn = self.connection_pool.get_connection()
15871585
# assign to self.connection so reset() releases the connection
15881586
# back to the pool after we're done
15891587
self.connection = conn

redis/cluster.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from redis.retry import Retry
4141
from redis.utils import (
4242
HIREDIS_AVAILABLE,
43+
deprecated_args,
4344
dict_merge,
4445
list_keys_to_dict,
4546
merge_result,
@@ -52,10 +53,13 @@ def get_node_name(host: str, port: Union[str, int]) -> str:
5253
return f"{host}:{port}"
5354

5455

56+
@deprecated_args(
57+
allowed_args=["redis_node"],
58+
reason="Use get_connection(redis_node) instead",
59+
version="5.0.3",
60+
)
5561
def get_connection(redis_node, *args, **options):
56-
return redis_node.connection or redis_node.connection_pool.get_connection(
57-
args[0], **options
58-
)
62+
return redis_node.connection or redis_node.connection_pool.get_connection()
5963

6064

6165
def parse_scan_result(command, res, **options):
@@ -1151,7 +1155,7 @@ def _execute_command(self, target_node, *args, **kwargs):
11511155
moved = False
11521156

11531157
redis_node = self.get_redis_connection(target_node)
1154-
connection = get_connection(redis_node, *args, **kwargs)
1158+
connection = get_connection(redis_node)
11551159
if asking:
11561160
connection.send_command("ASKING")
11571161
redis_node.parse_response(connection, "ASKING", **kwargs)
@@ -1822,9 +1826,7 @@ def execute_command(self, *args):
18221826
self.node = node
18231827
redis_connection = self.cluster.get_redis_connection(node)
18241828
self.connection_pool = redis_connection.connection_pool
1825-
self.connection = self.connection_pool.get_connection(
1826-
"pubsub", self.shard_hint
1827-
)
1829+
self.connection = self.connection_pool.get_connection()
18281830
# register a callback that re-subscribes to any channels we
18291831
# were listening to when we were disconnected
18301832
self.connection.register_connect_callback(self.on_connect)
@@ -2184,7 +2186,7 @@ def _send_cluster_commands(
21842186
if node_name not in nodes:
21852187
redis_node = self.get_redis_connection(node)
21862188
try:
2187-
connection = get_connection(redis_node, c.args)
2189+
connection = get_connection(redis_node)
21882190
except (ConnectionError, TimeoutError):
21892191
for n in nodes.values():
21902192
n.connection_pool.release(n.connection)

redis/connection.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
HIREDIS_AVAILABLE,
4343
SSL_AVAILABLE,
4444
compare_versions,
45+
deprecated_args,
4546
ensure_string,
4647
format_error_message,
4748
get_lib_version,
@@ -1461,8 +1462,14 @@ def _checkpid(self) -> None:
14611462
finally:
14621463
self._fork_lock.release()
14631464

1464-
def get_connection(self, command_name: str, *keys, **options) -> "Connection":
1465+
@deprecated_args(
1466+
args_to_warn=["*"],
1467+
reason="Use get_connection() without args instead",
1468+
version="5.0.3",
1469+
)
1470+
def get_connection(self, command_name=None, *keys, **options) -> "Connection":
14651471
"Get a connection from the pool"
1472+
14661473
self._checkpid()
14671474
with self._lock:
14681475
try:
@@ -1683,7 +1690,12 @@ def make_connection(self):
16831690
self._connections.append(connection)
16841691
return connection
16851692

1686-
def get_connection(self, command_name, *keys, **options):
1693+
@deprecated_args(
1694+
args_to_warn=["*"],
1695+
reason="Use get_connection() without args instead",
1696+
version="5.0.3",
1697+
)
1698+
def get_connection(self, command_name=None, *keys, **options):
16871699
"""
16881700
Get a connection, blocking for ``self.timeout`` until a connection
16891701
is available from the pool.

redis/utils.py

+65
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,71 @@ def wrapper(*args, **kwargs):
122122
return decorator
123123

124124

125+
def warn_deprecated_arg_usage(
126+
arg_name: Union[list, str],
127+
function_name: str,
128+
reason: str = "",
129+
version: str = "",
130+
stacklevel: int = 2,
131+
):
132+
import warnings
133+
134+
msg = (
135+
f"Call to '{function_name}' function with deprecated"
136+
f" usage of input argument/s '{arg_name}'."
137+
)
138+
if reason:
139+
msg += f" ({reason})"
140+
if version:
141+
msg += f" -- Deprecated since version {version}."
142+
warnings.warn(msg, category=DeprecationWarning, stacklevel=stacklevel)
143+
144+
145+
def deprecated_args(
146+
args_to_warn: list = ["*"],
147+
allowed_args: list = [],
148+
reason: str = "",
149+
version: str = "",
150+
):
151+
"""
152+
Decorator to mark specified args of a function as deprecated.
153+
If '*' is in args_to_warn, all arguments will be marked as deprecated.
154+
"""
155+
156+
def decorator(func):
157+
@wraps(func)
158+
def wrapper(*args, **kwargs):
159+
# Get function argument names
160+
arg_names = func.__code__.co_varnames[: func.__code__.co_argcount]
161+
162+
provided_args = dict(zip(arg_names, args))
163+
provided_args.update(kwargs)
164+
165+
provided_args.pop("self", None)
166+
for allowed_arg in allowed_args:
167+
provided_args.pop(allowed_arg, None)
168+
169+
for arg in args_to_warn:
170+
if arg == "*" and len(provided_args) > 0:
171+
warn_deprecated_arg_usage(
172+
list(provided_args.keys()),
173+
func.__name__,
174+
reason,
175+
version,
176+
stacklevel=3,
177+
)
178+
elif arg in provided_args:
179+
warn_deprecated_arg_usage(
180+
arg, func.__name__, reason, version, stacklevel=3
181+
)
182+
183+
return func(*args, **kwargs)
184+
185+
return wrapper
186+
187+
return decorator
188+
189+
125190
def _set_info_logger():
126191
"""
127192
Set up a logger that log info logs to stdout.

tests/test_asyncio/test_connection.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ async def call_with_retry(self, _, __):
7878
mock_conn = mock.AsyncMock(spec=Connection)
7979
mock_conn.retry = Retry_()
8080

81-
async def get_conn(_):
81+
async def get_conn():
8282
# Validate only one client is created in single-client mode when
8383
# concurrent requests are made
8484
nonlocal init_call_count

0 commit comments

Comments
 (0)