Skip to content

Commit 3f92109

Browse files
authored
Merge branch 'master' into issue/3139
2 parents de33f88 + 7d73d74 commit 3f92109

File tree

21 files changed

+1061
-150
lines changed

21 files changed

+1061
-150
lines changed

.github/workflows/integration.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
max-parallel: 15
6464
fail-fast: false
6565
matrix:
66-
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8', 'pypy-3.9']
66+
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10']
6767
test-type: ['standalone', 'cluster']
6868
connection-type: ['hiredis', 'plain']
6969
env:
@@ -184,7 +184,7 @@ jobs:
184184
strategy:
185185
fail-fast: false
186186
matrix:
187-
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8', 'pypy-3.9']
187+
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10']
188188
steps:
189189
- uses: actions/checkout@v4
190190
- uses: actions/setup-python@v5

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
* Prevent async ClusterPipeline instances from becoming "false-y" in case of empty command stack (#3061)
6868
* Close Unix sockets if the connection attempt fails. This prevents `ResourceWarning`s. (#3314)
6969
* Close SSL sockets if the connection attempt fails, or if validations fail. (#3317)
70+
* Eliminate mutable default arguments in the `redis.commands.core.Script` class. (#3332)
7071

7172
* 4.1.3 (Feb 8, 2022)
7273
* Fix flushdb and flushall (#1926)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Looking for a high-level library to handle object mapping? See [redis-om-python]
5454

5555
## Supported Redis Versions
5656

57-
The most recent version of this library supports redis version [5.0](https://github.com/redis/redis/blob/5.0/00-RELEASENOTES), [6.0](https://github.com/redis/redis/blob/6.0/00-RELEASENOTES), [6.2](https://github.com/redis/redis/blob/6.2/00-RELEASENOTES), [7.0](https://github.com/redis/redis/blob/7.0/00-RELEASENOTES) and [7.2](https://github.com/redis/redis/blob/7.2/00-RELEASENOTES).
57+
The most recent version of this library supports redis version [5.0](https://github.com/redis/redis/blob/5.0/00-RELEASENOTES), [6.0](https://github.com/redis/redis/blob/6.0/00-RELEASENOTES), [6.2](https://github.com/redis/redis/blob/6.2/00-RELEASENOTES), [7.0](https://github.com/redis/redis/blob/7.0/00-RELEASENOTES), [7.2](https://github.com/redis/redis/blob/7.2/00-RELEASENOTES) and [7.4](https://github.com/redis/redis/blob/7.4/00-RELEASENOTES).
5858

5959
The table below highlights version compatibility of the most-recent library versions and redis versions.
6060

dev_requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ invoke==2.2.0
88
mock
99
packaging>=20.4
1010
pytest
11-
pytest-asyncio
11+
pytest-asyncio>=0.23.0,<0.24.0
1212
pytest-cov
1313
pytest-profiling
1414
pytest-timeout

doctests/cmds_generic.py

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# EXAMPLE: cmds_generic
2+
# HIDE_START
3+
import redis
4+
5+
r = redis.Redis(decode_responses=True)
6+
# HIDE_END
7+
8+
# STEP_START del
9+
res = r.set("key1", "Hello")
10+
print(res)
11+
# >>> True
12+
13+
res = r.set("key2", "World")
14+
print(res)
15+
# >>> True
16+
17+
res = r.delete("key1", "key2", "key3")
18+
print(res)
19+
# >>> 2
20+
# REMOVE_START
21+
assert res == 2
22+
# REMOVE_END
23+
# STEP_END
24+
25+
# STEP_START expire
26+
res = r.set("mykey", "Hello")
27+
print(res)
28+
# >>> True
29+
30+
res = r.expire("mykey", 10)
31+
print(res)
32+
# >>> True
33+
34+
res = r.ttl("mykey")
35+
print(res)
36+
# >>> 10
37+
# REMOVE_START
38+
assert res == 10
39+
# REMOVE_END
40+
41+
res = r.set("mykey", "Hello World")
42+
print(res)
43+
# >>> True
44+
45+
res = r.ttl("mykey")
46+
print(res)
47+
# >>> -1
48+
# REMOVE_START
49+
assert res == -1
50+
# REMOVE_END
51+
52+
res = r.expire("mykey", 10, xx=True)
53+
print(res)
54+
# >>> False
55+
# REMOVE_START
56+
assert res == False
57+
# REMOVE_END
58+
59+
res = r.ttl("mykey")
60+
print(res)
61+
# >>> -1
62+
# REMOVE_START
63+
assert res == -1
64+
# REMOVE_END
65+
66+
res = r.expire("mykey", 10, nx=True)
67+
print(res)
68+
# >>> True
69+
# REMOVE_START
70+
assert res == True
71+
# REMOVE_END
72+
73+
res = r.ttl("mykey")
74+
print(res)
75+
# >>> 10
76+
# REMOVE_START
77+
assert res == 10
78+
r.delete("mykey")
79+
# REMOVE_END
80+
# STEP_END
81+
82+
# STEP_START ttl
83+
res = r.set("mykey", "Hello")
84+
print(res)
85+
# >>> True
86+
87+
res = r.expire("mykey", 10)
88+
print(res)
89+
# >>> True
90+
91+
res = r.ttl("mykey")
92+
print(res)
93+
# >>> 10
94+
# REMOVE_START
95+
assert res == 10
96+
r.delete("mykey")
97+
# REMOVE_END
98+
# STEP_END
99+
100+
# STEP_START scan1
101+
res = r.sadd("myset", *set([1, 2, 3, "foo", "foobar", "feelsgood"]))
102+
print(res)
103+
# >>> 6
104+
105+
res = list(r.sscan_iter("myset", match="f*"))
106+
print(res)
107+
# >>> ['foobar', 'foo', 'feelsgood']
108+
# REMOVE_START
109+
assert sorted(res) == sorted(["foo", "foobar", "feelsgood"])
110+
r.delete("myset")
111+
# REMOVE_END
112+
# STEP_END
113+
114+
# STEP_START scan2
115+
# REMOVE_START
116+
for i in range(1, 1001):
117+
r.set(f"key:{i}", i)
118+
# REMOVE_END
119+
120+
cursor, key = r.scan(cursor=0, match='*11*')
121+
print(cursor, key)
122+
123+
cursor, key = r.scan(cursor, match='*11*')
124+
print(cursor, key)
125+
126+
cursor, key = r.scan(cursor, match='*11*')
127+
print(cursor, key)
128+
129+
cursor, key = r.scan(cursor, match='*11*')
130+
print(cursor, key)
131+
132+
cursor, keys = r.scan(cursor, match='*11*', count=1000)
133+
print(cursor, keys)
134+
135+
# REMOVE_START
136+
assert len(keys) == 18
137+
cursor = '0'
138+
prefix = "key:*"
139+
while cursor != 0:
140+
cursor, keys = r.scan(cursor=cursor, match=prefix, count=1000)
141+
if keys:
142+
r.delete(*keys)
143+
# REMOVE_END
144+
# STEP_END
145+
146+
# STEP_START scan3
147+
res = r.geoadd("geokey", (0, 0, "value"))
148+
print(res)
149+
# >>> 1
150+
151+
res = r.zadd("zkey", {"value": 1000})
152+
print(res)
153+
# >>> 1
154+
155+
res = r.type("geokey")
156+
print(res)
157+
# >>> zset
158+
# REMOVE_START
159+
assert res == "zset"
160+
# REMOVE_END
161+
162+
res = r.type("zkey")
163+
print(res)
164+
# >>> zset
165+
# REMOVE_START
166+
assert res == "zset"
167+
# REMOVE_END
168+
169+
cursor, keys = r.scan(cursor=0, _type="zset")
170+
print(keys)
171+
# >>> ['zkey', 'geokey']
172+
# REMOVE_START
173+
assert sorted(keys) == sorted(["zkey", "geokey"])
174+
r.delete("geokey", "zkey")
175+
# REMOVE_END
176+
# STEP_END
177+
178+
# STEP_START scan4
179+
res = r.hset("myhash", mapping={"a": 1, "b": 2})
180+
print(res)
181+
# >>> 2
182+
183+
cursor, keys = r.hscan("myhash", 0)
184+
print(keys)
185+
# >>> {'a': '1', 'b': '2'}
186+
# REMOVE_START
187+
assert keys == {'a': '1', 'b': '2'}
188+
# REMOVE_END
189+
190+
cursor, keys = r.hscan("myhash", 0, no_values=True)
191+
print(keys)
192+
# >>> ['a', 'b']
193+
# REMOVE_START
194+
assert keys == ['a', 'b']
195+
# REMOVE_END
196+
197+
# REMOVE_START
198+
r.delete("myhash")
199+
# REMOVE_END
200+
# STEP_END

doctests/cmds_hash.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# EXAMPLE: cmds_hash
2+
# HIDE_START
3+
import redis
4+
5+
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
6+
# HIDE_END
7+
8+
# STEP_START hset
9+
res1 = r.hset("myhash", "field1", "Hello")
10+
print(res1)
11+
# >>> 1
12+
13+
res2 = r.hget("myhash", "field1")
14+
print(res2)
15+
# >>> Hello
16+
17+
res3 = r.hset("myhash", mapping={"field2": "Hi", "field3": "World"})
18+
print(res3)
19+
# >>> 2
20+
21+
res4 = r.hget("myhash", "field2")
22+
print(res4)
23+
# >>> Hi
24+
25+
res5 = r.hget("myhash", "field3")
26+
print(res5)
27+
# >>> World
28+
29+
res6 = r.hgetall("myhash")
30+
print(res6)
31+
# >>> { "field1": "Hello", "field2": "Hi", "field3": "World" }
32+
33+
# REMOVE_START
34+
assert res1 == 1
35+
assert res2 == "Hello"
36+
assert res3 == 2
37+
assert res4 == "Hi"
38+
assert res5 == "World"
39+
assert res6 == { "field1": "Hello", "field2": "Hi", "field3": "World" }
40+
r.delete("myhash")
41+
# REMOVE_END
42+
# STEP_END
43+
44+
# STEP_START hget
45+
res7 = r.hset("myhash", "field1", "foo")
46+
print(res7)
47+
# >>> 1
48+
49+
res8 = r.hget("myhash", "field1")
50+
print(res8)
51+
# >>> foo
52+
53+
res9 = r.hget("myhash", "field2")
54+
print(res9)
55+
# >>> None
56+
57+
# REMOVE_START
58+
assert res7 == 1
59+
assert res8 == "foo"
60+
assert res9 == None
61+
r.delete("myhash")
62+
# REMOVE_END
63+
# STEP_END

doctests/cmds_sorted_set.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# EXAMPLE: cmds_sorted_set
2+
# HIDE_START
3+
import redis
4+
5+
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
6+
# HIDE_END
7+
8+
# STEP_START zadd
9+
res = r.zadd("myzset", {"one": 1})
10+
print(res)
11+
# >>> 1
12+
# REMOVE_START
13+
assert res == 1
14+
# REMOVE_END
15+
16+
res = r.zadd("myzset", {"uno": 1})
17+
print(res)
18+
# >>> 1
19+
# REMOVE_START
20+
assert res == 1
21+
# REMOVE_END
22+
23+
res = r.zadd("myzset", {"two": 2, "three": 3})
24+
print(res)
25+
# >>> 2
26+
# REMOVE_START
27+
assert res == 2
28+
# REMOVE_END
29+
30+
res = r.zrange("myzset", 0, -1, withscores=True)
31+
# >>> [('one', 1.0), ('uno', 1.0), ('two', 2.0), ('three', 3.0)]
32+
# REMOVE_START
33+
assert res == [('one', 1.0), ('uno', 1.0), ('two', 2.0), ('three', 3.0)]
34+
# REMOVE_END
35+
36+
# REMOVE_START
37+
r.delete("myzset")
38+
# REMOVE_END
39+
# STEP_END
40+
41+
# STEP_START zrange1
42+
res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
43+
print(res)
44+
# >>> 3
45+
46+
res = r.zrange("myzset", 0, -1)
47+
print(res)
48+
# >>> ['one', 'two', 'three']
49+
# REMOVE_START
50+
assert res == ['one', 'two', 'three']
51+
# REMOVE_END
52+
53+
res = r.zrange("myzset", 2, 3)
54+
print(res)
55+
# >>> ['three']
56+
# REMOVE_START
57+
assert res == ['three']
58+
# REMOVE_END
59+
60+
res = r.zrange("myzset", -2, -1)
61+
print(res)
62+
# >>> ['two', 'three']
63+
# REMOVE_START
64+
assert res == ['two', 'three']
65+
r.delete("myzset")
66+
# REMOVE_END
67+
# STEP_END
68+
69+
# STEP_START zrange2
70+
res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
71+
res = r.zrange("myzset", 0, 1, withscores=True)
72+
print(res)
73+
# >>> [('one', 1.0), ('two', 2.0)]
74+
# REMOVE_START
75+
assert res == [('one', 1.0), ('two', 2.0)]
76+
r.delete("myzset")
77+
# REMOVE_END
78+
# STEP_END
79+
80+
# STEP_START zrange3
81+
res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
82+
res = r.zrange("myzset", 2, 3, byscore=True, offset=1, num=1)
83+
print(res)
84+
# >>> ['three']
85+
# REMOVE_START
86+
assert res == ['three']
87+
r.delete("myzset")
88+
# REMOVE_END
89+
# STEP_END

0 commit comments

Comments
 (0)