Skip to content

Commit 8c7757b

Browse files
committed
Merge branch 'multi-exec-on-cluster' of github.com:robertosantamaria-scopely/redis-py into multi-exec-on-cluster
2 parents a3de190 + 096ac29 commit 8c7757b

File tree

8 files changed

+120
-24
lines changed

8 files changed

+120
-24
lines changed

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

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ inputs:
1414
description: 'hiredis version to test against'
1515
required: false
1616
default: '>3.0.0'
17+
hiredis-branch:
18+
description: 'hiredis branch to test against'
19+
required: false
20+
default: 'master'
1721
event-loop:
1822
description: 'Event loop to use'
1923
required: false
@@ -28,6 +32,14 @@ runs:
2832
python-version: ${{ inputs.python-version }}
2933
cache: 'pip'
3034

35+
- uses: actions/checkout@v4
36+
if: ${{ inputs.parser-backend == 'hiredis' && inputs.hiredis-version == 'unstable' }}
37+
with:
38+
repository: redis/hiredis-py
39+
submodules: true
40+
path: hiredis-py
41+
ref: ${{ inputs.hiredis-branch }}
42+
3143
- name: Setup Test environment
3244
env:
3345
REDIS_VERSION: ${{ inputs.redis-version }}
@@ -40,15 +52,21 @@ runs:
4052
pip uninstall -y redis # uninstall Redis package installed via redis-entraid
4153
pip install -e .[jwt] # install the working copy
4254
if [ "${{inputs.parser-backend}}" == "hiredis" ]; then
43-
pip install "hiredis${{inputs.hiredis-version}}"
44-
echo "PARSER_BACKEND=$(echo "${{inputs.parser-backend}}_${{inputs.hiredis-version}}" | sed 's/[^a-zA-Z0-9]/_/g')" >> $GITHUB_ENV
55+
if [[ "${{inputs.hiredis-version}}" == "unstable" ]]; then
56+
echo "Installing unstable version of hiredis from local directory"
57+
pip install -e ./hiredis-py
58+
else
59+
pip install "hiredis${{inputs.hiredis-version}}"
60+
fi
61+
echo "PARSER_BACKEND=$(echo "${{inputs.parser-backend}}_${{inputs.hiredis-version}}" | sed 's/[^a-zA-Z0-9]/_/g')" >> $GITHUB_ENV
4562
else
4663
echo "PARSER_BACKEND=${{inputs.parser-backend}}" >> $GITHUB_ENV
4764
fi
4865
echo "::endgroup::"
4966
5067
echo "::group::Starting Redis servers"
5168
redis_major_version=$(echo "$REDIS_VERSION" | grep -oP '^\d+')
69+
echo "REDIS_MAJOR_VERSION=${redis_major_version}" >> $GITHUB_ENV
5270
5371
if (( redis_major_version < 8 )); then
5472
echo "Using redis-stack for module tests"
@@ -70,8 +88,7 @@ runs:
7088
7189
if (( redis_major_version < 7 )); then
7290
export REDIS_STACK_EXTRA_ARGS="--tls-auth-clients optional --save ''"
73-
export REDIS_EXTRA_ARGS="--tls-auth-clients optional --save ''"
74-
echo "REDIS_MAJOR_VERSION=${redis_major_version}" >> $GITHUB_ENV
91+
export REDIS_EXTRA_ARGS="--tls-auth-clients optional --save ''"
7592
fi
7693
7794
invoke devenv --endpoints=all-stack
@@ -108,12 +125,10 @@ runs:
108125
fi
109126

110127
echo "::endgroup::"
111-
112-
if [ "$protocol" == "2" ] || [ "${{inputs.parser-backend}}" != 'hiredis' ]; then
113-
echo "::group::RESP${protocol} cluster tests"
114-
invoke cluster-tests $eventloop --protocol=${protocol}
115-
echo "::endgroup::"
116-
fi
128+
129+
echo "::group::RESP${protocol} cluster tests"
130+
invoke cluster-tests $eventloop --protocol=${protocol}
131+
echo "::endgroup::"
117132
}
118133

119134
run_tests 2 "${{inputs.event-loop}}"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Hiredis-py integration tests
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
redis-py-branch:
7+
description: 'redis-py branch to run tests on'
8+
required: true
9+
default: 'master'
10+
hiredis-branch:
11+
description: 'hiredis-py branch to run tests on'
12+
required: true
13+
default: 'master'
14+
15+
concurrency:
16+
group: ${{ github.event.pull_request.number || github.ref }}-hiredis-integration
17+
cancel-in-progress: true
18+
19+
permissions:
20+
contents: read # to fetch code (actions/checkout)
21+
22+
env:
23+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
24+
# this speeds up coverage with Python 3.12: https://github.com/nedbat/coveragepy/issues/1665
25+
COVERAGE_CORE: sysmon
26+
CURRENT_CLIENT_LIBS_TEST_STACK_IMAGE_TAG: 'rs-7.4.0-v2'
27+
CURRENT_REDIS_VERSION: '7.4.2'
28+
29+
jobs:
30+
redis_version:
31+
runs-on: ubuntu-latest
32+
outputs:
33+
CURRENT: ${{ env.CURRENT_REDIS_VERSION }}
34+
steps:
35+
- name: Compute outputs
36+
run: |
37+
echo "CURRENT=${{ env.CURRENT_REDIS_VERSION }}" >> $GITHUB_OUTPUT
38+
39+
hiredis-tests:
40+
runs-on: ubuntu-latest
41+
needs: [redis_version]
42+
timeout-minutes: 60
43+
strategy:
44+
max-parallel: 15
45+
fail-fast: false
46+
matrix:
47+
redis-version: [ '${{ needs.redis_version.outputs.CURRENT }}' ]
48+
python-version: [ '3.8', '3.13']
49+
parser-backend: [ 'hiredis' ]
50+
hiredis-version: [ 'unstable' ]
51+
event-loop: [ 'asyncio' ]
52+
env:
53+
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
54+
name: Redis ${{ matrix.redis-version }}; Python ${{ matrix.python-version }}; RESP Parser:${{matrix.parser-backend}} (${{ matrix.hiredis-version }}); EL:${{matrix.event-loop}}
55+
steps:
56+
- uses: actions/checkout@v4
57+
with:
58+
ref: ${{ inputs.redis-py-branch }}
59+
- name: Run tests
60+
uses: ./.github/actions/run-tests
61+
with:
62+
python-version: ${{ matrix.python-version }}
63+
parser-backend: ${{ matrix.parser-backend }}
64+
redis-version: ${{ matrix.redis-version }}
65+
hiredis-version: ${{ matrix.hiredis-version }}
66+
hiredis-branch: ${{ inputs.hiredis-branch }}

.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-RC2-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', '6.2.17']
7878
python-version: ['3.8', '3.13']
7979
parser-backend: ['plain']
8080
event-loop: ['asyncio']

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
* Close Unix sockets if the connection attempt fails. This prevents `ResourceWarning`s. (#3314)
7272
* Close SSL sockets if the connection attempt fails, or if validations fail. (#3317)
7373
* Eliminate mutable default arguments in the `redis.commands.core.Script` class. (#3332)
74+
* Allow newer versions of PyJWT as dependency. (#3630)
7475

7576
* 4.1.3 (Feb 8, 2022)
7677
* Fix flushdb and flushall (#1926)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ ocsp = [
4141
"requests>=2.31.0",
4242
]
4343
jwt = [
44-
"PyJWT~=2.9.0",
44+
"PyJWT>=2.9.0",
4545
]
4646

4747
[project.urls]

redis/asyncio/cluster.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,9 @@ async def initialize(self) -> None:
13131313
startup_nodes_reachable = False
13141314
fully_covered = False
13151315
exception = None
1316-
for startup_node in self.startup_nodes.values():
1316+
# Convert to tuple to prevent RuntimeError if self.startup_nodes
1317+
# is modified during iteration
1318+
for startup_node in tuple(self.startup_nodes.values()):
13171319
try:
13181320
# Make sure cluster mode is enabled on this node
13191321
try:

redis/cluster.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1703,7 +1703,9 @@ def initialize(self):
17031703
fully_covered = False
17041704
kwargs = self.connection_kwargs
17051705
exception = None
1706-
for startup_node in self.startup_nodes.values():
1706+
# Convert to tuple to prevent RuntimeError if self.startup_nodes
1707+
# is modified during iteration
1708+
for startup_node in tuple(self.startup_nodes.values()):
17071709
try:
17081710
if startup_node.redis_connection:
17091711
r = startup_node.redis_connection

redis/commands/redismodules.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
1+
from __future__ import annotations
2+
13
from json import JSONDecoder, JSONEncoder
4+
from typing import TYPE_CHECKING
5+
6+
if TYPE_CHECKING:
7+
from .bf import BFBloom, CFBloom, CMSBloom, TDigestBloom, TOPKBloom
8+
from .json import JSON
9+
from .search import AsyncSearch, Search
10+
from .timeseries import TimeSeries
11+
from .vectorset import VectorSet
212

313

414
class RedisModuleCommands:
515
"""This class contains the wrapper functions to bring supported redis
616
modules into the command namespace.
717
"""
818

9-
def json(self, encoder=JSONEncoder(), decoder=JSONDecoder()):
19+
def json(self, encoder=JSONEncoder(), decoder=JSONDecoder()) -> JSON:
1020
"""Access the json namespace, providing support for redis json."""
1121

1222
from .json import JSON
1323

1424
jj = JSON(client=self, encoder=encoder, decoder=decoder)
1525
return jj
1626

17-
def ft(self, index_name="idx"):
27+
def ft(self, index_name="idx") -> Search:
1828
"""Access the search namespace, providing support for redis search."""
1929

2030
from .search import Search
2131

2232
s = Search(client=self, index_name=index_name)
2333
return s
2434

25-
def ts(self):
35+
def ts(self) -> TimeSeries:
2636
"""Access the timeseries namespace, providing support for
2737
redis timeseries data.
2838
"""
@@ -32,47 +42,47 @@ def ts(self):
3242
s = TimeSeries(client=self)
3343
return s
3444

35-
def bf(self):
45+
def bf(self) -> BFBloom:
3646
"""Access the bloom namespace."""
3747

3848
from .bf import BFBloom
3949

4050
bf = BFBloom(client=self)
4151
return bf
4252

43-
def cf(self):
53+
def cf(self) -> CFBloom:
4454
"""Access the bloom namespace."""
4555

4656
from .bf import CFBloom
4757

4858
cf = CFBloom(client=self)
4959
return cf
5060

51-
def cms(self):
61+
def cms(self) -> CMSBloom:
5262
"""Access the bloom namespace."""
5363

5464
from .bf import CMSBloom
5565

5666
cms = CMSBloom(client=self)
5767
return cms
5868

59-
def topk(self):
69+
def topk(self) -> TOPKBloom:
6070
"""Access the bloom namespace."""
6171

6272
from .bf import TOPKBloom
6373

6474
topk = TOPKBloom(client=self)
6575
return topk
6676

67-
def tdigest(self):
77+
def tdigest(self) -> TDigestBloom:
6878
"""Access the bloom namespace."""
6979

7080
from .bf import TDigestBloom
7181

7282
tdigest = TDigestBloom(client=self)
7383
return tdigest
7484

75-
def vset(self):
85+
def vset(self) -> VectorSet:
7686
"""Access the VectorSet commands namespace."""
7787

7888
from .vectorset import VectorSet
@@ -82,7 +92,7 @@ def vset(self):
8292

8393

8494
class AsyncRedisModuleCommands(RedisModuleCommands):
85-
def ft(self, index_name="idx"):
95+
def ft(self, index_name="idx") -> AsyncSearch:
8696
"""Access the search namespace, providing support for redis search."""
8797

8898
from .search import AsyncSearch

0 commit comments

Comments
 (0)