Skip to content

Commit 2c39081

Browse files
gerzsevladvildanov
authored andcommitted
Prepare for Redis 7.4 RC2 (#3303)
Adapt the code and some of the tests to match the changes done in the Redis 7.4 RC2 release.
1 parent 22fa2fc commit 2c39081

File tree

7 files changed

+52
-60
lines changed

7 files changed

+52
-60
lines changed

.github/workflows/integration.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ permissions:
2525

2626
env:
2727
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
28-
REDIS_IMAGE: redis/redis-stack-server:7.4.0-rc1
29-
REDIS_STACK_IMAGE: redis/redis-stack-server:7.4.0-rc1
28+
REDIS_IMAGE: redis:7.4-rc2
29+
REDIS_STACK_IMAGE: redis/redis-stack-server:7.4.0-rc2
3030

3131
jobs:
3232
dependency-audit:

redis/commands/core.py

+18-27
Original file line numberDiff line numberDiff line change
@@ -5126,9 +5126,8 @@ def hexpire(
51265126
lt: Set expiry only when the new expiry is less than the current one.
51275127
51285128
Returns:
5129-
If the key does not exist, returns an empty list. If the key exists, returns
5130-
a list which contains for each field in the request:
5131-
- `-2` if the field does not exist.
5129+
Returns a list which contains for each field in the request:
5130+
- `-2` if the field does not exist, or if the key does not exist.
51325131
- `0` if the specified NX | XX | GT | LT condition was not met.
51335132
- `1` if the expiration time was set or updated.
51345133
- `2` if the field was deleted because the specified expiration time is
@@ -5187,9 +5186,8 @@ def hpexpire(
51875186
lt: Set expiry only when the new expiry is less than the current one.
51885187
51895188
Returns:
5190-
If the key does not exist, returns an empty list. If the key exists, returns
5191-
a list which contains for each field in the request:
5192-
- `-2` if the field does not exist.
5189+
Returns a list which contains for each field in the request:
5190+
- `-2` if the field does not exist, or if the key does not exist.
51935191
- `0` if the specified NX | XX | GT | LT condition was not met.
51945192
- `1` if the expiration time was set or updated.
51955193
- `2` if the field was deleted because the specified expiration time is
@@ -5248,9 +5246,8 @@ def hexpireat(
52485246
lt: Set expiry only when the new expiry is less than the current one.
52495247
52505248
Returns:
5251-
If the key does not exist, returns an empty list. If the key exists, returns
5252-
a list which contains for each field in the request:
5253-
- `-2` if the field does not exist.
5249+
Returns a list which contains for each field in the request:
5250+
- `-2` if the field does not exist, or if the key does not exist.
52545251
- `0` if the specified NX | XX | GT | LT condition was not met.
52555252
- `1` if the expiration time was set or updated.
52565253
- `2` if the field was deleted because the specified expiration time is
@@ -5315,9 +5312,8 @@ def hpexpireat(
53155312
lt: Set expiry only when the new expiry is less than the current one.
53165313
53175314
Returns:
5318-
If the key does not exist, returns an empty list. If the key exists, returns
5319-
a list which contains for each field in the request:
5320-
- `-2` if the field does not exist.
5315+
Returns a list which contains for each field in the request:
5316+
- `-2` if the field does not exist, or if the key does not exist.
53215317
- `0` if the specified NX | XX | GT | LT condition was not met.
53225318
- `1` if the expiration time was set or updated.
53235319
- `2` if the field was deleted because the specified expiration time is
@@ -5362,9 +5358,8 @@ def hpersist(self, name: KeyT, *fields: str) -> ResponseT:
53625358
expiration time.
53635359
53645360
Returns:
5365-
If the key does not exist, returns an empty list. If the key exists, returns
5366-
a list which contains for each field in the request:
5367-
- `-2` if the field does not exist.
5361+
Returns a list which contains for each field in the request:
5362+
- `-2` if the field does not exist, or if the key does not exist.
53685363
- `-1` if the field exists but has no associated expiration time.
53695364
- `1` if the expiration time was successfully removed from the field.
53705365
"""
@@ -5382,9 +5377,8 @@ def hexpiretime(self, key: KeyT, *fields: str) -> ResponseT:
53825377
time.
53835378
53845379
Returns:
5385-
If the key does not exist, returns an empty list. If the key exists, returns
5386-
a list which contains for each field in the request:
5387-
- `-2` if the field does not exist.
5380+
Returns a list which contains for each field in the request:
5381+
- `-2` if the field does not exist, or if the key does not exist.
53885382
- `-1` if the field exists but has no associated expire time.
53895383
- A positive integer representing the expiration Unix timestamp in
53905384
seconds, if the field has an associated expiration time.
@@ -5405,9 +5399,8 @@ def hpexpiretime(self, key: KeyT, *fields: str) -> ResponseT:
54055399
time.
54065400
54075401
Returns:
5408-
If the key does not exist, returns an empty list. If the key exists, returns
5409-
a list which contains for each field in the request:
5410-
- `-2` if the field does not exist.
5402+
Returns a list which contains for each field in the request:
5403+
- `-2` if the field does not exist, or if the key does not exist.
54115404
- `-1` if the field exists but has no associated expire time.
54125405
- A positive integer representing the expiration Unix timestamp in
54135406
milliseconds, if the field has an associated expiration time.
@@ -5428,9 +5421,8 @@ def httl(self, key: KeyT, *fields: str) -> ResponseT:
54285421
fields: A list of fields within the hash for which to get the TTL.
54295422
54305423
Returns:
5431-
If the key does not exist, returns an empty list. If the key exists, returns
5432-
a list which contains for each field in the request:
5433-
- `-2` if the field does not exist.
5424+
Returns a list which contains for each field in the request:
5425+
- `-2` if the field does not exist, or if the key does not exist.
54345426
- `-1` if the field exists but has no associated expire time.
54355427
- A positive integer representing the TTL in seconds if the field has
54365428
an associated expiration time.
@@ -5451,9 +5443,8 @@ def hpttl(self, key: KeyT, *fields: str) -> ResponseT:
54515443
fields: A list of fields within the hash for which to get the TTL.
54525444
54535445
Returns:
5454-
If the key does not exist, returns an empty list. If the key exists, returns
5455-
a list which contains for each field in the request:
5456-
- `-2` if the field does not exist.
5446+
Returns a list which contains for each field in the request:
5447+
- `-2` if the field does not exist, or if the key does not exist.
54575448
- `-1` if the field exists but has no associated expire time.
54585449
- A positive integer representing the TTL in milliseconds if the field
54595450
has an associated expiration time.

tests/test_asyncio/test_hash.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ async def test_hexpire_conditions(r):
4545
@skip_if_server_version_lt("7.3.240")
4646
async def test_hexpire_nonexistent_key_or_field(r):
4747
await r.delete("test:hash")
48-
assert await r.hexpire("test:hash", 1, "field1") == []
48+
assert await r.hexpire("test:hash", 1, "field1") == [-2]
4949
await r.hset("test:hash", "field1", "value1")
5050
assert await r.hexpire("test:hash", 1, "nonexistent_field") == [-2]
5151

@@ -105,7 +105,7 @@ async def test_hpexpire_conditions(r):
105105
@skip_if_server_version_lt("7.3.240")
106106
async def test_hpexpire_nonexistent_key_or_field(r):
107107
await r.delete("test:hash")
108-
assert await r.hpexpire("test:hash", 500, "field1") == []
108+
assert await r.hpexpire("test:hash", 500, "field1") == [-2]
109109
await r.hset("test:hash", "field1", "value1")
110110
assert await r.hpexpire("test:hash", 500, "nonexistent_field") == [-2]
111111

@@ -163,7 +163,7 @@ async def test_hexpireat_conditions(r):
163163
async def test_hexpireat_nonexistent_key_or_field(r):
164164
await r.delete("test:hash")
165165
future_exp_time = int((datetime.now() + timedelta(seconds=1)).timestamp())
166-
assert await r.hexpireat("test:hash", future_exp_time, "field1") == []
166+
assert await r.hexpireat("test:hash", future_exp_time, "field1") == [-2]
167167
await r.hset("test:hash", "field1", "value1")
168168
assert await r.hexpireat("test:hash", future_exp_time, "nonexistent_field") == [-2]
169169

@@ -228,7 +228,7 @@ async def test_hpexpireat_nonexistent_key_or_field(r):
228228
future_exp_time = int(
229229
(datetime.now() + timedelta(milliseconds=500)).timestamp() * 1000
230230
)
231-
assert await r.hpexpireat("test:hash", future_exp_time, "field1") == []
231+
assert await r.hpexpireat("test:hash", future_exp_time, "field1") == [-2]
232232
await r.hset("test:hash", "field1", "value1")
233233
assert await r.hpexpireat("test:hash", future_exp_time, "nonexistent_field") == [-2]
234234

tests/test_asyncio/test_json.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ async def test_mset(decoded_r: redis.Redis):
131131
async def test_clear(decoded_r: redis.Redis):
132132
await decoded_r.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4])
133133
assert 1 == await decoded_r.json().clear("arr", Path.root_path())
134-
assert_resp_response(decoded_r, await decoded_r.json().get("arr"), [], [[[]]])
134+
assert_resp_response(decoded_r, await decoded_r.json().get("arr"), [], [])
135135

136136

137137
@pytest.mark.redismod

tests/test_hash.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def test_hexpire_conditions(r):
4646
@skip_if_server_version_lt("7.3.240")
4747
def test_hexpire_nonexistent_key_or_field(r):
4848
r.delete("test:hash")
49-
assert r.hexpire("test:hash", 1, "field1") == []
49+
assert r.hexpire("test:hash", 1, "field1") == [-2]
5050
r.hset("test:hash", "field1", "value1")
5151
assert r.hexpire("test:hash", 1, "nonexistent_field") == [-2]
5252

@@ -115,7 +115,7 @@ def test_hpexpire_conditions(r):
115115
@skip_if_server_version_lt("7.3.240")
116116
def test_hpexpire_nonexistent_key_or_field(r):
117117
r.delete("test:hash")
118-
assert r.hpexpire("test:hash", 500, "field1") == []
118+
assert r.hpexpire("test:hash", 500, "field1") == [-2]
119119
r.hset("test:hash", "field1", "value1")
120120
assert r.hpexpire("test:hash", 500, "nonexistent_field") == [-2]
121121

@@ -182,7 +182,7 @@ def test_hexpireat_conditions(r):
182182
def test_hexpireat_nonexistent_key_or_field(r):
183183
r.delete("test:hash")
184184
future_exp_time = int((datetime.now() + timedelta(seconds=1)).timestamp())
185-
assert r.hexpireat("test:hash", future_exp_time, "field1") == []
185+
assert r.hexpireat("test:hash", future_exp_time, "field1") == [-2]
186186
r.hset("test:hash", "field1", "value1")
187187
assert r.hexpireat("test:hash", future_exp_time, "nonexistent_field") == [-2]
188188

@@ -257,7 +257,7 @@ def test_hpexpireat_nonexistent_key_or_field(r):
257257
future_exp_time = int(
258258
(datetime.now() + timedelta(milliseconds=500)).timestamp() * 1000
259259
)
260-
assert r.hpexpireat("test:hash", future_exp_time, "field1") == []
260+
assert r.hpexpireat("test:hash", future_exp_time, "field1") == [-2]
261261
r.hset("test:hash", "field1", "value1")
262262
assert r.hpexpireat("test:hash", future_exp_time, "nonexistent_field") == [-2]
263263

@@ -298,7 +298,7 @@ def test_hpersist_multiple_fields(r):
298298
@skip_if_server_version_lt("7.3.240")
299299
def test_hpersist_nonexistent_key(r):
300300
r.delete("test:hash")
301-
assert r.hpersist("test:hash", "field1", "field2", "field3") == []
301+
assert r.hpersist("test:hash", "field1", "field2", "field3") == [-2, -2, -2]
302302

303303

304304
@skip_if_server_version_lt("7.3.240")
@@ -315,7 +315,7 @@ def test_hexpiretime_multiple_fields_mixed_conditions(r):
315315
@skip_if_server_version_lt("7.3.240")
316316
def test_hexpiretime_nonexistent_key(r):
317317
r.delete("test:hash")
318-
assert r.hexpiretime("test:hash", "field1", "field2", "field3") == []
318+
assert r.hexpiretime("test:hash", "field1", "field2", "field3") == [-2, -2, -2]
319319

320320

321321
@skip_if_server_version_lt("7.3.240")
@@ -332,7 +332,7 @@ def test_hpexpiretime_multiple_fields_mixed_conditions(r):
332332
@skip_if_server_version_lt("7.3.240")
333333
def test_hpexpiretime_nonexistent_key(r):
334334
r.delete("test:hash")
335-
assert r.hpexpiretime("test:hash", "field1", "field2", "field3") == []
335+
assert r.hpexpiretime("test:hash", "field1", "field2", "field3") == [-2, -2, -2]
336336

337337

338338
@skip_if_server_version_lt("7.3.240")
@@ -349,7 +349,7 @@ def test_httl_multiple_fields_mixed_conditions(r):
349349
@skip_if_server_version_lt("7.3.240")
350350
def test_httl_nonexistent_key(r):
351351
r.delete("test:hash")
352-
assert r.httl("test:hash", "field1", "field2", "field3") == []
352+
assert r.httl("test:hash", "field1", "field2", "field3") == [-2, -2, -2]
353353

354354

355355
@skip_if_server_version_lt("7.3.240")
@@ -366,4 +366,4 @@ def test_hpttl_multiple_fields_mixed_conditions(r):
366366
@skip_if_server_version_lt("7.3.240")
367367
def test_hpttl_nonexistent_key(r):
368368
r.delete("test:hash")
369-
assert r.hpttl("test:hash", "field1", "field2", "field3") == []
369+
assert r.hpttl("test:hash", "field1", "field2", "field3") == [-2, -2, -2]

tests/test_json.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def test_mset(client):
130130
def test_clear(client):
131131
client.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4])
132132
assert 1 == client.json().clear("arr", Path.root_path())
133-
assert_resp_response(client, client.json().get("arr"), [], [[[]]])
133+
assert_resp_response(client, client.json().get("arr"), [], [])
134134

135135

136136
@pytest.mark.redismod

tests/test_search.py

+17-16
Original file line numberDiff line numberDiff line change
@@ -2369,27 +2369,27 @@ def test_search_missing_fields(client):
23692369

23702370
with pytest.raises(redis.exceptions.ResponseError) as e:
23712371
client.ft().search(
2372-
Query("ismissing(@title)").dialect(5).return_field("id").no_content()
2372+
Query("ismissing(@title)").dialect(2).return_field("id").no_content()
23732373
)
23742374
assert "to be defined with 'INDEXMISSING'" in e.value.args[0]
23752375

23762376
res = client.ft().search(
2377-
Query("ismissing(@features)").dialect(5).return_field("id").no_content()
2377+
Query("ismissing(@features)").dialect(2).return_field("id").no_content()
23782378
)
23792379
_assert_search_result(client, res, ["property:2"])
23802380

23812381
res = client.ft().search(
2382-
Query("-ismissing(@features)").dialect(5).return_field("id").no_content()
2382+
Query("-ismissing(@features)").dialect(2).return_field("id").no_content()
23832383
)
23842384
_assert_search_result(client, res, ["property:1", "property:3"])
23852385

23862386
res = client.ft().search(
2387-
Query("ismissing(@description)").dialect(5).return_field("id").no_content()
2387+
Query("ismissing(@description)").dialect(2).return_field("id").no_content()
23882388
)
23892389
_assert_search_result(client, res, ["property:3"])
23902390

23912391
res = client.ft().search(
2392-
Query("-ismissing(@description)").dialect(5).return_field("id").no_content()
2392+
Query("-ismissing(@description)").dialect(2).return_field("id").no_content()
23932393
)
23942394
_assert_search_result(client, res, ["property:1", "property:2"])
23952395

@@ -2438,27 +2438,29 @@ def test_search_empty_fields(client):
24382438

24392439
with pytest.raises(redis.exceptions.ResponseError) as e:
24402440
client.ft().search(
2441-
Query("@title:''").dialect(5).return_field("id").no_content()
2441+
Query("@title:''").dialect(2).return_field("id").no_content()
24422442
)
2443-
assert "to be defined with `INDEXEMPTY`" in e.value.args[0]
2443+
assert "Use `INDEXEMPTY` in field creation" in e.value.args[0]
24442444

24452445
res = client.ft().search(
2446-
Query("@features:{ }").dialect(5).return_field("id").no_content()
2446+
Query("@features:{$empty}").dialect(2).return_field("id").no_content(),
2447+
query_params={"empty": ""},
24472448
)
24482449
_assert_search_result(client, res, ["property:2"])
24492450

24502451
res = client.ft().search(
2451-
Query("-@features:{ }").dialect(5).return_field("id").no_content()
2452+
Query("-@features:{$empty}").dialect(2).return_field("id").no_content(),
2453+
query_params={"empty": ""},
24522454
)
24532455
_assert_search_result(client, res, ["property:1", "property:3"])
24542456

24552457
res = client.ft().search(
2456-
Query("@description:''").dialect(5).return_field("id").no_content()
2458+
Query("@description:''").dialect(2).return_field("id").no_content()
24572459
)
24582460
_assert_search_result(client, res, ["property:3"])
24592461

24602462
res = client.ft().search(
2461-
Query("-@description:''").dialect(5).return_field("id").no_content()
2463+
Query("-@description:''").dialect(2).return_field("id").no_content()
24622464
)
24632465
_assert_search_result(client, res, ["property:1", "property:2"])
24642466

@@ -2503,22 +2505,21 @@ def test_special_characters_in_fields(client):
25032505
)
25042506
_assert_search_result(client, res, ["resource:1"])
25052507

2506-
# with dialect 5 no need to escape the - even without params
2508+
# with double quotes exact match no need to escape the - even without params
25072509
res = client.ft().search(
2508-
Query("@uuid:{123e4567-e89b-12d3-a456-426614174000}").dialect(5)
2510+
Query('@uuid:{"123e4567-e89b-12d3-a456-426614174000"}').dialect(2)
25092511
)
25102512
_assert_search_result(client, res, ["resource:1"])
25112513

2512-
# also no need to escape ' with dialect 5
2513-
res = client.ft().search(Query("@tags:{new-year's-resolutions}").dialect(5))
2514+
res = client.ft().search(Query('@tags:{"new-year\'s-resolutions"}').dialect(2))
25142515
_assert_search_result(client, res, ["resource:2"])
25152516

25162517
# possible to search numeric fields by single value
25172518
res = client.ft().search(Query("@rating:[4]").dialect(2))
25182519
_assert_search_result(client, res, ["resource:2"])
25192520

25202521
# some chars still need escaping
2521-
res = client.ft().search(Query(r"@tags:{\$btc}").dialect(5))
2522+
res = client.ft().search(Query(r"@tags:{\$btc}").dialect(2))
25222523
_assert_search_result(client, res, ["resource:1"])
25232524

25242525

0 commit comments

Comments
 (0)