Skip to content

Commit 7c3abf1

Browse files
authored
Merge branch 'master' into cluster-shards
2 parents ad780fa + e1988c6 commit 7c3abf1

30 files changed

+7255
-106
lines changed

.github/workflows/integration.yaml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
steps:
2323
- uses: actions/checkout@v2
2424
- name: install python
25-
uses: actions/setup-python@v2
25+
uses: actions/setup-python@v3
2626
with:
2727
python-version: 3.9
2828
- name: run code linters
@@ -32,20 +32,27 @@ jobs:
3232
3333
run-tests:
3434
runs-on: ubuntu-latest
35+
continue-on-error: ${{ matrix.experimental }}
3536
timeout-minutes: 30
3637
strategy:
3738
max-parallel: 15
3839
matrix:
3940
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', 'pypy-3.7']
4041
test-type: ['standalone', 'cluster']
4142
connection-type: ['hiredis', 'plain']
43+
experimental: [false]
44+
include:
45+
- python-version: 3.11.0-alpha.6
46+
experimental: true
47+
test-type: standalone
48+
connection-type: plain
4249
env:
4350
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
4451
name: Python ${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}} tests
4552
steps:
4653
- uses: actions/checkout@v2
4754
- name: install python
48-
uses: actions/setup-python@v2
55+
uses: actions/setup-python@v3
4956
with:
5057
python-version: ${{ matrix.python-version }}
5158
- name: run tests
@@ -68,23 +75,28 @@ jobs:
6875
steps:
6976
- uses: actions/checkout@v2
7077
- name: install python
71-
uses: actions/setup-python@v2
78+
uses: actions/setup-python@v3
7279
with:
7380
python-version: 3.9
7481
- name: Run installed unit tests
7582
run: |
7683
bash .github/workflows/install_and_test.sh ${{ matrix.extension }}
7784
7885
install_package_from_commit:
86+
continue-on-error: ${{ matrix.experimental }}
7987
name: Install package from commit hash
8088
runs-on: ubuntu-latest
8189
strategy:
8290
matrix:
8391
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', 'pypy-3.7']
92+
experimental: [false]
93+
include:
94+
- python-version: 3.11.0-alpha.5
95+
- experimental: true
8496
steps:
8597
- uses: actions/checkout@v2
8698
- name: install python ${{ matrix.python-version }}
87-
uses: actions/setup-python@v2
99+
uses: actions/setup-python@v3
88100
with:
89101
python-version: ${{ matrix.python-version }}
90102
- name: install from pip

.github/workflows/pypi-publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
steps:
1212
- uses: actions/checkout@v2
1313
- name: install python
14-
uses: actions/setup-python@v2
14+
uses: actions/setup-python@v3
1515
with:
1616
python-version: 3.9
1717
- name: Install dev tools

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
* Allow negative `retries` for `Retry` class to retry forever
23
* Add `items` parameter to `hset` signature
34
* Create codeql-analysis.yml (#1988). Thanks @chayim
45
* Add limited support for Lua scripting with RedisCluster
@@ -7,6 +8,7 @@
78
* Fix scan_iter for RedisCluster
89
* Remove verbose logging when initializing ClusterPubSub, ClusterPipeline or RedisCluster
910
* Fix broken connection writer lock-up for asyncio (#2065)
11+
* Fix auth bug when provided with no username (#2086)
1012

1113
* 4.1.3 (Feb 8, 2022)
1214
* Fix flushdb and flushall (#1926)

docker/redis7/master/redis.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
port 6379
2+
save ""
3+
enable-debug-command yes
4+
enable-module-command yes

redis/asyncio/client.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
)
4242
from redis.commands import (
4343
AsyncCoreCommands,
44+
AsyncRedisModuleCommands,
4445
AsyncSentinelCommands,
45-
RedisModuleCommands,
4646
list_or_args,
4747
)
4848
from redis.compat import Protocol, TypedDict
@@ -81,7 +81,7 @@ async def __call__(self, response: Any, **kwargs):
8181

8282

8383
class Redis(
84-
AbstractRedis, RedisModuleCommands, AsyncCoreCommands, AsyncSentinelCommands
84+
AbstractRedis, AsyncRedisModuleCommands, AsyncCoreCommands, AsyncSentinelCommands
8585
):
8686
"""
8787
Implementation of the Redis protocol.
@@ -693,16 +693,24 @@ async def execute_command(self, *args: EncodableT):
693693
# legitimate message off the stack if the connection is already
694694
# subscribed to one or more channels
695695

696+
await self.connect()
697+
connection = self.connection
698+
kwargs = {"check_health": not self.subscribed}
699+
await self._execute(connection, connection.send_command, *args, **kwargs)
700+
701+
async def connect(self):
702+
"""
703+
Ensure that the PubSub is connected
704+
"""
696705
if self.connection is None:
697706
self.connection = await self.connection_pool.get_connection(
698707
"pubsub", self.shard_hint
699708
)
700709
# register a callback that re-subscribes to any channels we
701710
# were listening to when we were disconnected
702711
self.connection.register_connect_callback(self.on_connect)
703-
connection = self.connection
704-
kwargs = {"check_health": not self.subscribed}
705-
await self._execute(connection, connection.send_command, *args, **kwargs)
712+
else:
713+
await self.connection.connect()
706714

707715
async def _disconnect_raise_connect(self, conn, error):
708716
"""
@@ -962,6 +970,7 @@ async def run(
962970
if handler is None:
963971
raise PubSubError(f"Pattern: '{pattern}' has no handler registered")
964972

973+
await self.connect()
965974
while True:
966975
try:
967976
await self.get_message(

redis/asyncio/lock.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import threading
44
import uuid
55
from types import SimpleNamespace
6-
from typing import TYPE_CHECKING, Awaitable, NoReturn, Optional, Union
6+
from typing import TYPE_CHECKING, Awaitable, Optional, Union
77

88
from redis.exceptions import LockError, LockNotOwnedError
99

@@ -243,15 +243,15 @@ async def owned(self) -> bool:
243243
stored_token = encoder.encode(stored_token)
244244
return self.local.token is not None and stored_token == self.local.token
245245

246-
def release(self) -> Awaitable[NoReturn]:
246+
def release(self) -> Awaitable[None]:
247247
"""Releases the already acquired lock"""
248248
expected_token = self.local.token
249249
if expected_token is None:
250250
raise LockError("Cannot release an unlocked lock")
251251
self.local.token = None
252252
return self.do_release(expected_token)
253253

254-
async def do_release(self, expected_token: bytes):
254+
async def do_release(self, expected_token: bytes) -> None:
255255
if not bool(
256256
await self.lua_release(
257257
keys=[self.name], args=[expected_token], client=self.redis

redis/asyncio/retry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(
2727
"""
2828
Initialize a `Retry` object with a `Backoff` object
2929
that retries a maximum of `retries` times.
30+
`retries` can be negative to retry forever.
3031
You can specify the types of supported errors which trigger
3132
a retry with the `supported_errors` parameter.
3233
"""
@@ -51,7 +52,7 @@ async def call_with_retry(
5152
except self._supported_errors as error:
5253
failures += 1
5354
await fail(error)
54-
if failures > self._retries:
55+
if self._retries >= 0 and failures > self._retries:
5556
raise error
5657
backoff = self._backoff.compute(failures)
5758
if backoff > 0:

redis/client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,6 @@ class AbstractRedis:
760760
"DEBUG OBJECT": parse_debug_object,
761761
"FUNCTION DELETE": bool_ok,
762762
"FUNCTION FLUSH": bool_ok,
763-
"FUNCTION LOAD": bool_ok,
764763
"FUNCTION RESTORE": bool_ok,
765764
"GEOHASH": lambda r: list(map(str_if_bytes, r)),
766765
"GEOPOS": lambda r: list(

redis/cluster.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,10 @@ def set_response_callback(self, command, callback):
886886
self.cluster_response_callbacks[command] = callback
887887

888888
def _determine_nodes(self, *args, **kwargs):
889-
command = args[0]
889+
command = args[0].upper()
890+
if len(args) >= 2 and f"{args[0]} {args[1]}".upper() in self.command_flags:
891+
command = f"{args[0]} {args[1]}".upper()
892+
890893
nodes_flag = kwargs.pop("nodes_flag", None)
891894
if nodes_flag is not None:
892895
# nodes flag passed by the user

redis/commands/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from .core import AsyncCoreCommands, CoreCommands
33
from .helpers import list_or_args
44
from .parser import CommandsParser
5-
from .redismodules import RedisModuleCommands
5+
from .redismodules import AsyncRedisModuleCommands, RedisModuleCommands
66
from .sentinel import AsyncSentinelCommands, SentinelCommands
77

88
__all__ = [
@@ -11,6 +11,7 @@
1111
"AsyncCoreCommands",
1212
"CoreCommands",
1313
"list_or_args",
14+
"AsyncRedisModuleCommands",
1415
"RedisModuleCommands",
1516
"AsyncSentinelCommands",
1617
"SentinelCommands",

redis/commands/cluster.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,15 @@ def replicaof(self, *args, **kwargs):
189189
190190
For more information see https://redis.io/commands/replicaof
191191
"""
192-
raise RedisClusterException("REPLICAOF is not supported in cluster" " mode")
192+
raise RedisClusterException("REPLICAOF is not supported in cluster mode")
193193

194194
def swapdb(self, *args, **kwargs):
195195
"""
196196
Swaps two Redis databases.
197197
198198
For more information see https://redis.io/commands/swapdb
199199
"""
200-
raise RedisClusterException("SWAPDB is not supported in cluster" " mode")
200+
raise RedisClusterException("SWAPDB is not supported in cluster mode")
201201

202202

203203
class ClusterDataAccessCommands(DataAccessCommands):
@@ -310,7 +310,6 @@ class RedisClusterCommands(
310310
target specific nodes. By default, if target_nodes is not specified, the
311311
command will be executed on the default cluster node.
312312
313-
314313
:param :target_nodes: type can be one of the followings:
315314
- nodes flag: ALL_NODES, PRIMARIES, REPLICAS, RANDOM
316315
- 'ClusterNode'
@@ -323,7 +322,7 @@ class RedisClusterCommands(
323322

324323
def cluster_myid(self, target_node):
325324
"""
326-
Returns the nodes id.
325+
Returns the node's id.
327326
328327
:target_node: 'ClusterNode'
329328
The node to execute the command on

0 commit comments

Comments
 (0)