Skip to content

Added Redis 8.0 to test matrix #3469

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 21, 2025
2 changes: 1 addition & 1 deletion .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
max-parallel: 15
fail-fast: false
matrix:
redis-version: [ '${{ needs.redis_version.outputs.CURRENT }}', '7.2.6', '6.2.16']
redis-version: ['8.0-M02', '${{ needs.redis_version.outputs.CURRENT }}', '7.2.6', '6.2.16']
python-version: ['3.8', '3.12']
parser-backend: ['plain']
event-loop: ['asyncio']
Expand Down
2 changes: 1 addition & 1 deletion doctests/query_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from redis.commands.search import Search
from redis.commands.search.aggregation import AggregateRequest
from redis.commands.search.field import NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
import redis.commands.search.reducers as reducers

r = redis.Redis(decode_responses=True)
Expand Down
2 changes: 1 addition & 1 deletion doctests/query_combined.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import warnings
from redis.commands.json.path import Path
from redis.commands.search.field import NumericField, TagField, TextField, VectorField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query
from sentence_transformers import SentenceTransformer

Expand Down
2 changes: 1 addition & 1 deletion doctests/query_em.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query

r = redis.Redis(decode_responses=True)
Expand Down
2 changes: 1 addition & 1 deletion doctests/query_ft.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query

r = redis.Redis(decode_responses=True)
Expand Down
2 changes: 1 addition & 1 deletion doctests/query_geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import GeoField, GeoShapeField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query

r = redis.Redis(decode_responses=True)
Expand Down
2 changes: 1 addition & 1 deletion doctests/query_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query

r = redis.Redis(decode_responses=True)
Expand Down
2 changes: 1 addition & 1 deletion doctests/search_quickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import redis.commands.search.reducers as reducers
from redis.commands.json.path import Path
from redis.commands.search.field import NumericField, TagField, TextField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query

# HIDE_END
Expand Down
2 changes: 1 addition & 1 deletion doctests/search_vss.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
TextField,
VectorField,
)
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query
from sentence_transformers import SentenceTransformer

Expand Down
23 changes: 0 additions & 23 deletions redis/commands/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,29 +79,6 @@ def parse_list_to_dict(response):
return res


def parse_to_dict(response):
if response is None:
return {}

res = {}
for det in response:
if not isinstance(det, list) or not det:
continue
if len(det) == 1:
res[det[0]] = True
elif isinstance(det[1], list):
res[det[0]] = parse_list_to_dict(det[1])
else:
try: # try to set the attribute. may be provided without value
try: # try to convert the value to float
res[det[0]] = float(det[1])
except (TypeError, ValueError):
res[det[0]] = det[1]
except IndexError:
pass
return res


def random_string(length=10):
"""
Returns a random N character long string.
Expand Down
9 changes: 5 additions & 4 deletions redis/commands/search/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
from redis.client import NEVER_DECODE, Pipeline
from redis.utils import deprecated_function

from ..helpers import get_protocol_version, parse_to_dict
from ..helpers import get_protocol_version
from ._util import to_string
from .aggregation import AggregateRequest, AggregateResult, Cursor
from .document import Document
from .field import Field
from .indexDefinition import IndexDefinition
from .index_definition import IndexDefinition
from .profile_information import ProfileInformation
from .query import Query
from .result import Result
from .suggestion import SuggestionParser
Expand Down Expand Up @@ -67,7 +68,7 @@ class SearchCommands:

def _parse_results(self, cmd, res, **kwargs):
if get_protocol_version(self.client) in ["3", 3]:
return res
return ProfileInformation(res) if cmd == "FT.PROFILE" else res
else:
return self._RESP2_MODULE_CALLBACKS[cmd](res, **kwargs)

Expand Down Expand Up @@ -101,7 +102,7 @@ def _parse_profile(self, res, **kwargs):
with_scores=query._with_scores,
)

return result, parse_to_dict(res[1])
return result, ProfileInformation(res[1])

def _parse_spellcheck(self, res, **kwargs):
corrections = {}
Expand Down
14 changes: 14 additions & 0 deletions redis/commands/search/profile_information.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import Any


class ProfileInformation:
"""
Wrapper around FT.PROFILE response
"""

def __init__(self, info: Any) -> None:
self._info: Any = info

@property
def info(self) -> Any:
return self._info
18 changes: 17 additions & 1 deletion tests/test_asyncio/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@
TextField,
VectorField,
)
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import GeoFilter, NumericFilter, Query
from redis.commands.search.result import Result
from redis.commands.search.suggestion import Suggestion
from tests.conftest import (
is_resp2_connection,
skip_if_redis_enterprise,
skip_if_resp_version,
skip_if_server_version_gte,
skip_if_server_version_lt,
skip_ifmodversion_lt,
)

Expand Down Expand Up @@ -1111,6 +1113,7 @@ async def test_get(decoded_r: redis.Redis):
@pytest.mark.redismod
@pytest.mark.onlynoncluster
@skip_ifmodversion_lt("2.2.0", "search")
@skip_if_server_version_gte("7.9.0")
async def test_config(decoded_r: redis.Redis):
assert await decoded_r.ft().config_set("TIMEOUT", "100")
with pytest.raises(redis.ResponseError):
Expand All @@ -1121,6 +1124,19 @@ async def test_config(decoded_r: redis.Redis):
assert "100" == res["TIMEOUT"]


@pytest.mark.redismod
@pytest.mark.onlynoncluster
@skip_if_server_version_lt("7.9.0")
async def test_config_with_removed_ftconfig(decoded_r: redis.Redis):
assert await decoded_r.config_set("timeout", "100")
with pytest.raises(redis.ResponseError):
await decoded_r.config_set("timeout", "null")
res = await decoded_r.config_get("*")
assert "100" == res["timeout"]
res = await decoded_r.config_get("timeout")
assert "100" == res["timeout"]


@pytest.mark.redismod
@pytest.mark.onlynoncluster
async def test_aggregations_groupby(decoded_r: redis.Redis):
Expand Down
26 changes: 26 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,7 @@ def try_delete_libs(self, r, *lib_names):

@pytest.mark.onlynoncluster
@skip_if_server_version_lt("7.1.140")
@skip_if_server_version_gte("7.9.0")
def test_tfunction_load_delete(self, stack_r):
self.try_delete_libs(stack_r, "lib1")
lib_code = self.generate_lib_code("lib1")
Expand All @@ -1831,6 +1832,7 @@ def test_tfunction_load_delete(self, stack_r):

@pytest.mark.onlynoncluster
@skip_if_server_version_lt("7.1.140")
@skip_if_server_version_gte("7.9.0")
def test_tfunction_list(self, stack_r):
self.try_delete_libs(stack_r, "lib1", "lib2", "lib3")
assert stack_r.tfunction_load(self.generate_lib_code("lib1"))
Expand Down Expand Up @@ -1861,6 +1863,7 @@ def test_tfunction_list(self, stack_r):

@pytest.mark.onlynoncluster
@skip_if_server_version_lt("7.1.140")
@skip_if_server_version_gte("7.9.0")
def test_tfcall(self, stack_r):
self.try_delete_libs(stack_r, "lib1")
assert stack_r.tfunction_load(self.generate_lib_code("lib1"))
Expand Down Expand Up @@ -4329,6 +4332,7 @@ def test_xgroup_create_mkstream(self, r):
assert r.xinfo_groups(stream) == expected

@skip_if_server_version_lt("7.0.0")
@skip_if_server_version_gte("7.9.0")
def test_xgroup_create_entriesread(self, r: redis.Redis):
stream = "stream"
group = "group"
Expand All @@ -4350,6 +4354,28 @@ def test_xgroup_create_entriesread(self, r: redis.Redis):
]
assert r.xinfo_groups(stream) == expected

@skip_if_server_version_lt("7.9.0")
def test_xgroup_create_entriesread_with_fixed_lag_field(self, r: redis.Redis):
stream = "stream"
group = "group"
r.xadd(stream, {"foo": "bar"})

# no group is setup yet, no info to obtain
assert r.xinfo_groups(stream) == []

assert r.xgroup_create(stream, group, 0, entries_read=7)
expected = [
{
"name": group.encode(),
"consumers": 0,
"pending": 0,
"last-delivered-id": b"0-0",
"entries-read": 7,
"lag": 1,
}
]
assert r.xinfo_groups(stream) == expected

@skip_if_server_version_lt("5.0.0")
def test_xgroup_delconsumer(self, r):
stream = "stream"
Expand Down
35 changes: 0 additions & 35 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
delist,
list_or_args,
nativestr,
parse_to_dict,
parse_to_list,
quote_string,
random_string,
Expand All @@ -26,40 +25,6 @@ def test_parse_to_list():
assert parse_to_list(r) == ["hello", "my name", 45, 555.55, "is simon!", None]


def test_parse_to_dict():
assert parse_to_dict(None) == {}
r = [
["Some number", "1.0345"],
["Some string", "hello"],
[
"Child iterators",
[
"Time",
"0.2089",
"Counter",
3,
"Child iterators",
["Type", "bar", "Time", "0.0729", "Counter", 3],
["Type", "barbar", "Time", "0.058", "Counter", 3],
["Type", "barbarbar", "Time", "0.0234", "Counter", 3],
],
],
]
assert parse_to_dict(r) == {
"Child iterators": {
"Child iterators": [
{"Counter": 3.0, "Time": 0.0729, "Type": "bar"},
{"Counter": 3.0, "Time": 0.058, "Type": "barbar"},
{"Counter": 3.0, "Time": 0.0234, "Type": "barbarbar"},
],
"Counter": 3.0,
"Time": 0.2089,
},
"Some number": 1.0345,
"Some string": "hello",
}


def test_nativestr():
assert nativestr("teststr") == "teststr"
assert nativestr(b"teststr") == "teststr"
Expand Down
Loading
Loading