Skip to content

Commit ad1f6ea

Browse files
authored
Merge branch 'master' into fixing_mypy_errors
2 parents 62db7bf + b1e5b01 commit ad1f6ea

File tree

15 files changed

+302
-92
lines changed

15 files changed

+302
-92
lines changed

.github/actions/run-tests/action.yml

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ runs:
4646
CLIENT_LIBS_TEST_IMAGE_TAG: ${{ inputs.redis-version }}
4747
run: |
4848
set -e
49-
49+
5050
echo "::group::Installing dependencies"
5151
pip install -r dev_requirements.txt
5252
pip uninstall -y redis # uninstall Redis package installed via redis-entraid
@@ -57,80 +57,79 @@ runs:
5757
pip install -e ./hiredis-py
5858
else
5959
pip install "hiredis${{inputs.hiredis-version}}"
60-
fi
60+
fi
6161
echo "PARSER_BACKEND=$(echo "${{inputs.parser-backend}}_${{inputs.hiredis-version}}" | sed 's/[^a-zA-Z0-9]/_/g')" >> $GITHUB_ENV
6262
else
6363
echo "PARSER_BACKEND=${{inputs.parser-backend}}" >> $GITHUB_ENV
6464
fi
6565
echo "::endgroup::"
66-
66+
6767
echo "::group::Starting Redis servers"
6868
redis_major_version=$(echo "$REDIS_VERSION" | grep -oP '^\d+')
6969
echo "REDIS_MAJOR_VERSION=${redis_major_version}" >> $GITHUB_ENV
70-
70+
7171
if (( redis_major_version < 8 )); then
7272
echo "Using redis-stack for module tests"
73-
74-
# Mapping of redis version to stack version
73+
74+
# Mapping of redis version to stack version
7575
declare -A redis_stack_version_mapping=(
7676
["7.4.2"]="rs-7.4.0-v2"
7777
["7.2.7"]="rs-7.2.0-v14"
78-
["6.2.17"]="rs-6.2.6-v18"
7978
)
80-
79+
8180
if [[ -v redis_stack_version_mapping[$REDIS_VERSION] ]]; then
8281
export CLIENT_LIBS_TEST_STACK_IMAGE_TAG=${redis_stack_version_mapping[$REDIS_VERSION]}
8382
echo "REDIS_MOD_URL=redis://127.0.0.1:6479/0" >> $GITHUB_ENV
8483
else
8584
echo "Version not found in the mapping."
8685
exit 1
8786
fi
88-
87+
8988
if (( redis_major_version < 7 )); then
9089
export REDIS_STACK_EXTRA_ARGS="--tls-auth-clients optional --save ''"
91-
export REDIS_EXTRA_ARGS="--tls-auth-clients optional --save ''"
90+
export REDIS_EXTRA_ARGS="--tls-auth-clients optional --save ''"
9291
fi
93-
92+
9493
invoke devenv --endpoints=all-stack
9594
else
9695
echo "Using redis CE for module tests"
9796
echo "REDIS_MOD_URL=redis://127.0.0.1:6379" >> $GITHUB_ENV
9897
invoke devenv --endpoints all
99-
fi
100-
98+
fi
99+
101100
sleep 10 # time to settle
102101
echo "::endgroup::"
103102
shell: bash
104103

105104
- name: Run tests
106105
run: |
107106
set -e
108-
107+
109108
run_tests() {
110109
local protocol=$1
111110
local eventloop=""
112-
111+
113112
if [ "${{inputs.event-loop}}" == "uvloop" ]; then
114113
eventloop="--uvloop"
115114
fi
116-
115+
117116
echo "::group::RESP${protocol} standalone tests"
118117
echo "REDIS_MOD_URL=${REDIS_MOD_URL}"
119-
118+
120119
if (( $REDIS_MAJOR_VERSION < 7 )) && [ "$protocol" == "3" ]; then
121120
echo "Skipping module tests: Modules doesn't support RESP3 for Redis versions < 7"
122121
invoke standalone-tests --redis-mod-url=${REDIS_MOD_URL} $eventloop --protocol="${protocol}" --extra-markers="not redismod and not cp_integration"
123-
else
122+
else
124123
invoke standalone-tests --redis-mod-url=${REDIS_MOD_URL} $eventloop --protocol="${protocol}"
125124
fi
126-
125+
127126
echo "::endgroup::"
128-
127+
129128
echo "::group::RESP${protocol} cluster tests"
130129
invoke cluster-tests $eventloop --protocol=${protocol}
131-
echo "::endgroup::"
130+
echo "::endgroup::"
132131
}
133-
132+
134133
run_tests 2 "${{inputs.event-loop}}"
135134
run_tests 3 "${{inputs.event-loop}}"
136135
shell: bash

.github/workflows/integration.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ jobs:
7474
max-parallel: 15
7575
fail-fast: false
7676
matrix:
77-
redis-version: ['8.0.1-pre', '${{ needs.redis_version.outputs.CURRENT }}', '7.2.7', '6.2.17']
77+
redis-version: ['8.0.1-pre', '${{ needs.redis_version.outputs.CURRENT }}', '7.2.7']
7878
python-version: ['3.9', '3.13']
7979
parser-backend: ['plain']
8080
event-loop: ['asyncio']

.github/workflows/spellcheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
- name: Checkout
99
uses: actions/checkout@v4
1010
- name: Check Spelling
11-
uses: rojopolis/spellcheck-github-actions@0.48.0
11+
uses: rojopolis/spellcheck-github-actions@0.49.0
1212
with:
1313
config_path: .github/spellcheck-settings.yml
1414
task_name: Markdown

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
The Python interface to the Redis key-value store.
44

55
[![CI](https://github.com/redis/redis-py/workflows/CI/badge.svg?branch=master)](https://github.com/redis/redis-py/actions?query=workflow%3ACI+branch%3Amaster)
6-
[![docs](https://readthedocs.org/projects/redis/badge/?version=stable&style=flat)](https://redis-py.readthedocs.io/en/stable/)
6+
[![docs](https://readthedocs.org/projects/redis/badge/?version=stable&style=flat)](https://redis.readthedocs.io/en/stable/)
77
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
88
[![pypi](https://badge.fury.io/py/redis.svg)](https://pypi.org/project/redis/)
99
[![pre-release](https://img.shields.io/github/v/release/redis/redis-py?include_prereleases&label=latest-prerelease)](https://github.com/redis/redis-py/releases)

docs/examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Examples
22

3-
Examples of redis-py usage go here. They're being linked to the [generated documentation](https://redis-py.readthedocs.org).
3+
Examples of redis-py usage go here. They're being linked to the [generated documentation](https://redis.readthedocs.org).

docs/examples/opentelemetry/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This example demonstrates how to monitor Redis using [OpenTelemetry](https://ope
44
[Uptrace](https://github.com/uptrace/uptrace). It requires Docker to start Redis Server and Uptrace.
55

66
See
7-
[Monitoring redis-py performance with OpenTelemetry](https://redis-py.readthedocs.io/en/latest/opentelemetry.html)
7+
[Monitoring redis-py performance with OpenTelemetry](https://redis.readthedocs.io/en/latest/opentelemetry.html)
88
for details.
99

1010
**Step 1**. Download the example using Git:

redis/asyncio/cluster.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,10 +2350,11 @@ async def reset(self):
23502350
# watching something
23512351
if self._transaction_connection:
23522352
try:
2353-
# call this manually since our unwatch or
2354-
# immediate_execute_command methods can call reset()
2355-
await self._transaction_connection.send_command("UNWATCH")
2356-
await self._transaction_connection.read_response()
2353+
if self._watching:
2354+
# call this manually since our unwatch or
2355+
# immediate_execute_command methods can call reset()
2356+
await self._transaction_connection.send_command("UNWATCH")
2357+
await self._transaction_connection.read_response()
23572358
# we can safely return the connection to the pool here since we're
23582359
# sure we're no longer WATCHing anything
23592360
self._transaction_node.release(self._transaction_connection)

redis/asyncio/sentinel.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,19 +223,31 @@ async def execute_command(self, *args, **kwargs):
223223
once - If set to True, then execute the resulting command on a single
224224
node at random, rather than across the entire sentinel cluster.
225225
"""
226-
once = bool(kwargs.get("once", False))
227-
if "once" in kwargs.keys():
228-
kwargs.pop("once")
226+
once = bool(kwargs.pop("once", False))
227+
228+
# Check if command is supposed to return the original
229+
# responses instead of boolean value.
230+
return_responses = bool(kwargs.pop("return_responses", False))
229231

230232
if once:
231-
await random.choice(self.sentinels).execute_command(*args, **kwargs)
232-
else:
233-
tasks = [
234-
asyncio.Task(sentinel.execute_command(*args, **kwargs))
235-
for sentinel in self.sentinels
236-
]
237-
await asyncio.gather(*tasks)
238-
return True
233+
response = await random.choice(self.sentinels).execute_command(
234+
*args, **kwargs
235+
)
236+
if return_responses:
237+
return [response]
238+
else:
239+
return True if response else False
240+
241+
tasks = [
242+
asyncio.Task(sentinel.execute_command(*args, **kwargs))
243+
for sentinel in self.sentinels
244+
]
245+
responses = await asyncio.gather(*tasks)
246+
247+
if return_responses:
248+
return responses
249+
250+
return all(responses)
239251

240252
def __repr__(self):
241253
sentinel_addresses = []

redis/cluster.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,6 @@ def pipeline(self, transaction=None, shard_hint=None):
856856
startup_nodes=self.nodes_manager.startup_nodes,
857857
result_callbacks=self.result_callbacks,
858858
cluster_response_callbacks=self.cluster_response_callbacks,
859-
cluster_error_retry_attempts=self.retry.get_retries(),
860859
read_from_replicas=self.read_from_replicas,
861860
load_balancing_strategy=self.load_balancing_strategy,
862861
reinitialize_steps=self.reinitialize_steps,
@@ -3290,10 +3289,11 @@ def reset(self):
32903289
# watching something
32913290
if self._transaction_connection:
32923291
try:
3293-
# call this manually since our unwatch or
3294-
# immediate_execute_command methods can call reset()
3295-
self._transaction_connection.send_command("UNWATCH")
3296-
self._transaction_connection.read_response()
3292+
if self._watching:
3293+
# call this manually since our unwatch or
3294+
# immediate_execute_command methods can call reset()
3295+
self._transaction_connection.send_command("UNWATCH")
3296+
self._transaction_connection.read_response()
32973297
# we can safely return the connection to the pool here since we're
32983298
# sure we're no longer WATCHing anything
32993299
node = self._nodes_manager.find_connection_owner(

redis/commands/core.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,15 +3290,15 @@ class SetCommands(CommandsProtocol):
32903290
see: https://redis.io/topics/data-types#sets
32913291
"""
32923292

3293-
def sadd(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]:
3293+
def sadd(self, name: KeyT, *values: FieldT) -> Union[Awaitable[int], int]:
32943294
"""
32953295
Add ``value(s)`` to set ``name``
32963296
32973297
For more information see https://redis.io/commands/sadd
32983298
"""
32993299
return self.execute_command("SADD", name, *values)
33003300

3301-
def scard(self, name: str) -> Union[Awaitable[int], int]:
3301+
def scard(self, name: KeyT) -> Union[Awaitable[int], int]:
33023302
"""
33033303
Return the number of elements in set ``name``
33043304
@@ -3337,7 +3337,7 @@ def sinter(self, keys: List, *args: List) -> Union[Awaitable[list], list]:
33373337
return self.execute_command("SINTER", *args, keys=args)
33383338

33393339
def sintercard(
3340-
self, numkeys: int, keys: List[str], limit: int = 0
3340+
self, numkeys: int, keys: List[KeyT], limit: int = 0
33413341
) -> Union[Awaitable[int], int]:
33423342
"""
33433343
Return the cardinality of the intersect of multiple sets specified by ``keys``.
@@ -3352,7 +3352,7 @@ def sintercard(
33523352
return self.execute_command("SINTERCARD", *args, keys=keys)
33533353

33543354
def sinterstore(
3355-
self, dest: str, keys: List, *args: List
3355+
self, dest: KeyT, keys: List, *args: List
33563356
) -> Union[Awaitable[int], int]:
33573357
"""
33583358
Store the intersection of sets specified by ``keys`` into a new
@@ -3364,7 +3364,7 @@ def sinterstore(
33643364
return self.execute_command("SINTERSTORE", dest, *args)
33653365

33663366
def sismember(
3367-
self, name: str, value: str
3367+
self, name: KeyT, value: str
33683368
) -> Union[Awaitable[Union[Literal[0], Literal[1]]], Union[Literal[0], Literal[1]]]:
33693369
"""
33703370
Return whether ``value`` is a member of set ``name``:
@@ -3375,7 +3375,7 @@ def sismember(
33753375
"""
33763376
return self.execute_command("SISMEMBER", name, value, keys=[name])
33773377

3378-
def smembers(self, name: str) -> Union[Awaitable[Set], Set]:
3378+
def smembers(self, name: KeyT) -> Union[Awaitable[Set], Set]:
33793379
"""
33803380
Return all members of the set ``name``
33813381
@@ -3384,7 +3384,7 @@ def smembers(self, name: str) -> Union[Awaitable[Set], Set]:
33843384
return self.execute_command("SMEMBERS", name, keys=[name])
33853385

33863386
def smismember(
3387-
self, name: str, values: List, *args: List
3387+
self, name: KeyT, values: List, *args: List
33883388
) -> Union[
33893389
Awaitable[List[Union[Literal[0], Literal[1]]]],
33903390
List[Union[Literal[0], Literal[1]]],
@@ -3400,15 +3400,15 @@ def smismember(
34003400
args = list_or_args(values, args)
34013401
return self.execute_command("SMISMEMBER", name, *args, keys=[name])
34023402

3403-
def smove(self, src: str, dst: str, value: str) -> Union[Awaitable[bool], bool]:
3403+
def smove(self, src: KeyT, dst: KeyT, value: str) -> Union[Awaitable[bool], bool]:
34043404
"""
34053405
Move ``value`` from set ``src`` to set ``dst`` atomically
34063406
34073407
For more information see https://redis.io/commands/smove
34083408
"""
34093409
return self.execute_command("SMOVE", src, dst, value)
34103410

3411-
def spop(self, name: str, count: Optional[int] = None) -> Union[str, List, None]:
3411+
def spop(self, name: KeyT, count: Optional[int] = None) -> Union[str, List, None]:
34123412
"""
34133413
Remove and return a random member of set ``name``
34143414
@@ -3418,7 +3418,7 @@ def spop(self, name: str, count: Optional[int] = None) -> Union[str, List, None]
34183418
return self.execute_command("SPOP", name, *args)
34193419

34203420
def srandmember(
3421-
self, name: str, number: Optional[int] = None
3421+
self, name: KeyT, number: Optional[int] = None
34223422
) -> Union[str, List, None]:
34233423
"""
34243424
If ``number`` is None, returns a random member of set ``name``.
@@ -3432,7 +3432,7 @@ def srandmember(
34323432
args = (number is not None) and [number] or []
34333433
return self.execute_command("SRANDMEMBER", name, *args)
34343434

3435-
def srem(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]:
3435+
def srem(self, name: KeyT, *values: FieldT) -> Union[Awaitable[int], int]:
34363436
"""
34373437
Remove ``values`` from set ``name``
34383438
@@ -3450,7 +3450,7 @@ def sunion(self, keys: List, *args: List) -> Union[Awaitable[List], List]:
34503450
return self.execute_command("SUNION", *args, keys=args)
34513451

34523452
def sunionstore(
3453-
self, dest: str, keys: List, *args: List
3453+
self, dest: KeyT, keys: List, *args: List
34543454
) -> Union[Awaitable[int], int]:
34553455
"""
34563456
Store the union of sets specified by ``keys`` into a new

redis/commands/json/_util.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
from typing import Any, Dict, List, Union
1+
from typing import List, Mapping, Union
22

3-
JsonType = Union[str, int, float, bool, None, Dict[str, Any], List[Any]]
3+
JsonType = Union[
4+
str, int, float, bool, None, Mapping[str, "JsonType"], List["JsonType"]
5+
]

0 commit comments

Comments
 (0)