redis 6.4.0__py3-none-any.whl → 7.0.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- redis/__init__.py +1 -1
- redis/_parsers/base.py +173 -8
- redis/_parsers/hiredis.py +16 -10
- redis/_parsers/resp3.py +11 -5
- redis/asyncio/client.py +45 -2
- redis/asyncio/cluster.py +46 -3
- redis/cache.py +1 -0
- redis/client.py +68 -13
- redis/cluster.py +3 -2
- redis/commands/core.py +285 -285
- redis/commands/helpers.py +0 -20
- redis/commands/search/query.py +12 -12
- redis/commands/vectorset/__init__.py +1 -1
- redis/commands/vectorset/commands.py +43 -25
- redis/commands/vectorset/utils.py +40 -4
- redis/connection.py +828 -59
- redis/maintenance_events.py +785 -0
- {redis-6.4.0.dist-info → redis-7.0.0b1.dist-info}/METADATA +1 -1
- {redis-6.4.0.dist-info → redis-7.0.0b1.dist-info}/RECORD +21 -20
- {redis-6.4.0.dist-info → redis-7.0.0b1.dist-info}/WHEEL +0 -0
- {redis-6.4.0.dist-info → redis-7.0.0b1.dist-info}/licenses/LICENSE +0 -0
redis/commands/helpers.py
CHANGED
|
@@ -72,26 +72,6 @@ def parse_to_list(response):
|
|
|
72
72
|
return res
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
def parse_list_to_dict(response):
|
|
76
|
-
res = {}
|
|
77
|
-
for i in range(0, len(response), 2):
|
|
78
|
-
if isinstance(response[i], list):
|
|
79
|
-
res["Child iterators"].append(parse_list_to_dict(response[i]))
|
|
80
|
-
try:
|
|
81
|
-
if isinstance(response[i + 1], list):
|
|
82
|
-
res["Child iterators"].append(parse_list_to_dict(response[i + 1]))
|
|
83
|
-
except IndexError:
|
|
84
|
-
pass
|
|
85
|
-
elif isinstance(response[i + 1], list):
|
|
86
|
-
res["Child iterators"] = [parse_list_to_dict(response[i + 1])]
|
|
87
|
-
else:
|
|
88
|
-
try:
|
|
89
|
-
res[response[i]] = float(response[i + 1])
|
|
90
|
-
except (TypeError, ValueError):
|
|
91
|
-
res[response[i]] = response[i + 1]
|
|
92
|
-
return res
|
|
93
|
-
|
|
94
|
-
|
|
95
75
|
def random_string(length=10):
|
|
96
76
|
"""
|
|
97
77
|
Returns a random N character long string.
|
redis/commands/search/query.py
CHANGED
|
@@ -9,7 +9,7 @@ class Query:
|
|
|
9
9
|
the query string. The query string is set in the constructor, and other
|
|
10
10
|
options have setter functions.
|
|
11
11
|
|
|
12
|
-
The setter functions return the query object
|
|
12
|
+
The setter functions return the query object so they can be chained.
|
|
13
13
|
i.e. `Query("foo").verbatim().filter(...)` etc.
|
|
14
14
|
"""
|
|
15
15
|
|
|
@@ -95,12 +95,12 @@ class Query:
|
|
|
95
95
|
) -> "Query":
|
|
96
96
|
"""
|
|
97
97
|
Return an abridged format of the field, containing only the segments of
|
|
98
|
-
the field
|
|
98
|
+
the field that contain the matching term(s).
|
|
99
99
|
|
|
100
100
|
If `fields` is specified, then only the mentioned fields are
|
|
101
|
-
summarized; otherwise all results are summarized.
|
|
101
|
+
summarized; otherwise, all results are summarized.
|
|
102
102
|
|
|
103
|
-
Server
|
|
103
|
+
Server-side defaults are used for each option (except `fields`)
|
|
104
104
|
if not specified
|
|
105
105
|
|
|
106
106
|
- **fields** List of fields to summarize. All fields are summarized
|
|
@@ -130,7 +130,7 @@ class Query:
|
|
|
130
130
|
"""
|
|
131
131
|
Apply specified markup to matched term(s) within the returned field(s).
|
|
132
132
|
|
|
133
|
-
- **fields** If specified then only those mentioned fields are
|
|
133
|
+
- **fields** If specified, then only those mentioned fields are
|
|
134
134
|
highlighted, otherwise all fields are highlighted
|
|
135
135
|
- **tags** A list of two strings to surround the match.
|
|
136
136
|
"""
|
|
@@ -154,7 +154,7 @@ class Query:
|
|
|
154
154
|
return self
|
|
155
155
|
|
|
156
156
|
def slop(self, slop: int) -> "Query":
|
|
157
|
-
"""Allow a maximum of N intervening non
|
|
157
|
+
"""Allow a maximum of N intervening non-matched terms between
|
|
158
158
|
phrase terms (0 means exact phrase).
|
|
159
159
|
"""
|
|
160
160
|
self._slop = slop
|
|
@@ -169,7 +169,7 @@ class Query:
|
|
|
169
169
|
"""
|
|
170
170
|
Match only documents where the query terms appear in
|
|
171
171
|
the same order in the document.
|
|
172
|
-
i.e
|
|
172
|
+
i.e., for the query "hello world", we do not match "world hello"
|
|
173
173
|
"""
|
|
174
174
|
self._in_order = True
|
|
175
175
|
return self
|
|
@@ -258,7 +258,7 @@ class Query:
|
|
|
258
258
|
return self
|
|
259
259
|
|
|
260
260
|
def verbatim(self) -> "Query":
|
|
261
|
-
"""Set the query to be verbatim, i.e
|
|
261
|
+
"""Set the query to be verbatim, i.e., use no query expansion
|
|
262
262
|
or stemming.
|
|
263
263
|
"""
|
|
264
264
|
self._verbatim = True
|
|
@@ -292,7 +292,7 @@ class Query:
|
|
|
292
292
|
"""
|
|
293
293
|
Limit the search to specific TEXT fields only.
|
|
294
294
|
|
|
295
|
-
- **fields**: A list of strings
|
|
295
|
+
- **fields**: A list of strings; case-sensitive field names
|
|
296
296
|
from the defined schema.
|
|
297
297
|
"""
|
|
298
298
|
self._fields = fields
|
|
@@ -301,7 +301,7 @@ class Query:
|
|
|
301
301
|
def add_filter(self, flt: "Filter") -> "Query":
|
|
302
302
|
"""
|
|
303
303
|
Add a numeric or geo filter to the query.
|
|
304
|
-
**Currently only one of each filter is supported by the engine**
|
|
304
|
+
**Currently, only one of each filter is supported by the engine**
|
|
305
305
|
|
|
306
306
|
- **flt**: A NumericFilter or GeoFilter object, used on a
|
|
307
307
|
corresponding field
|
|
@@ -315,14 +315,14 @@ class Query:
|
|
|
315
315
|
Add a sortby field to the query.
|
|
316
316
|
|
|
317
317
|
- **field** - the name of the field to sort by
|
|
318
|
-
- **asc** - when `True`, sorting will be done in
|
|
318
|
+
- **asc** - when `True`, sorting will be done in ascending order
|
|
319
319
|
"""
|
|
320
320
|
self._sortby = SortbyField(field, asc)
|
|
321
321
|
return self
|
|
322
322
|
|
|
323
323
|
def expander(self, expander: str) -> "Query":
|
|
324
324
|
"""
|
|
325
|
-
Add
|
|
325
|
+
Add an expander field to the query.
|
|
326
326
|
|
|
327
327
|
- **expander** - the name of the expander
|
|
328
328
|
"""
|
|
@@ -24,12 +24,12 @@ class VectorSet(VectorSetCommands):
|
|
|
24
24
|
# Set the module commands' callbacks
|
|
25
25
|
self._MODULE_CALLBACKS = {
|
|
26
26
|
VEMB_CMD: parse_vemb_result,
|
|
27
|
+
VSIM_CMD: parse_vsim_result,
|
|
27
28
|
VGETATTR_CMD: lambda r: r and json.loads(r) or None,
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
self._RESP2_MODULE_CALLBACKS = {
|
|
31
32
|
VINFO_CMD: lambda r: r and pairs_to_dict(r) or None,
|
|
32
|
-
VSIM_CMD: parse_vsim_result,
|
|
33
33
|
VLINKS_CMD: parse_vlinks_result,
|
|
34
34
|
}
|
|
35
35
|
self._RESP3_MODULE_CALLBACKS = {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from enum import Enum
|
|
3
|
-
from typing import Awaitable, Dict, List, Optional, Union
|
|
3
|
+
from typing import Any, Awaitable, Dict, List, Optional, Union
|
|
4
4
|
|
|
5
5
|
from redis.client import NEVER_DECODE
|
|
6
6
|
from redis.commands.helpers import get_protocol_version
|
|
@@ -19,6 +19,15 @@ VSETATTR_CMD = "VSETATTR"
|
|
|
19
19
|
VGETATTR_CMD = "VGETATTR"
|
|
20
20
|
VRANDMEMBER_CMD = "VRANDMEMBER"
|
|
21
21
|
|
|
22
|
+
# Return type for vsim command
|
|
23
|
+
VSimResult = Optional[
|
|
24
|
+
List[
|
|
25
|
+
Union[
|
|
26
|
+
List[EncodableT], Dict[EncodableT, Number], Dict[EncodableT, Dict[str, Any]]
|
|
27
|
+
]
|
|
28
|
+
]
|
|
29
|
+
]
|
|
30
|
+
|
|
22
31
|
|
|
23
32
|
class QuantizationOptions(Enum):
|
|
24
33
|
"""Quantization options for the VADD command."""
|
|
@@ -33,6 +42,7 @@ class CallbacksOptions(Enum):
|
|
|
33
42
|
|
|
34
43
|
RAW = "RAW"
|
|
35
44
|
WITHSCORES = "WITHSCORES"
|
|
45
|
+
WITHATTRIBS = "WITHATTRIBS"
|
|
36
46
|
ALLOW_DECODING = "ALLOW_DECODING"
|
|
37
47
|
RESP3 = "RESP3"
|
|
38
48
|
|
|
@@ -77,7 +87,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
77
87
|
``numlinks`` sets the number of links to create for the vector.
|
|
78
88
|
If not provided, the default number of links is used.
|
|
79
89
|
|
|
80
|
-
For more information see https://redis.io/commands/vadd
|
|
90
|
+
For more information, see https://redis.io/commands/vadd.
|
|
81
91
|
"""
|
|
82
92
|
if not vector or not element:
|
|
83
93
|
raise DataError("Both vector and element must be provided")
|
|
@@ -123,6 +133,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
123
133
|
key: KeyT,
|
|
124
134
|
input: Union[List[float], bytes, str],
|
|
125
135
|
with_scores: Optional[bool] = False,
|
|
136
|
+
with_attribs: Optional[bool] = False,
|
|
126
137
|
count: Optional[int] = None,
|
|
127
138
|
ef: Optional[Number] = None,
|
|
128
139
|
filter: Optional[str] = None,
|
|
@@ -130,25 +141,24 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
130
141
|
truth: Optional[bool] = False,
|
|
131
142
|
no_thread: Optional[bool] = False,
|
|
132
143
|
epsilon: Optional[Number] = None,
|
|
133
|
-
) -> Union[
|
|
134
|
-
Awaitable[Optional[List[Union[List[EncodableT], Dict[EncodableT, Number]]]]],
|
|
135
|
-
Optional[List[Union[List[EncodableT], Dict[EncodableT, Number]]]],
|
|
136
|
-
]:
|
|
144
|
+
) -> Union[Awaitable[VSimResult], VSimResult]:
|
|
137
145
|
"""
|
|
138
146
|
Compare a vector or element ``input`` with the other vectors in a vector set ``key``.
|
|
139
147
|
|
|
140
|
-
``with_scores`` sets if
|
|
141
|
-
|
|
148
|
+
``with_scores`` sets if similarity scores should be returned for each element in the result.
|
|
149
|
+
|
|
150
|
+
``with_attribs`` ``with_attribs`` sets if the results should be returned with the
|
|
151
|
+
attributes of the elements in the result, or None when no attributes are present.
|
|
142
152
|
|
|
143
153
|
``count`` sets the number of results to return.
|
|
144
154
|
|
|
145
155
|
``ef`` sets the exploration factor.
|
|
146
156
|
|
|
147
|
-
``filter`` sets filter that should be applied for the search.
|
|
157
|
+
``filter`` sets the filter that should be applied for the search.
|
|
148
158
|
|
|
149
159
|
``filter_ef`` sets the max filtering effort.
|
|
150
160
|
|
|
151
|
-
``truth`` when enabled forces the command to perform linear scan.
|
|
161
|
+
``truth`` when enabled, forces the command to perform a linear scan.
|
|
152
162
|
|
|
153
163
|
``no_thread`` when enabled forces the command to execute the search
|
|
154
164
|
on the data structure in the main thread.
|
|
@@ -156,7 +166,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
156
166
|
``epsilon`` floating point between 0 and 1, if specified will return
|
|
157
167
|
only elements with distance no further than the specified one.
|
|
158
168
|
|
|
159
|
-
For more information see https://redis.io/commands/vsim
|
|
169
|
+
For more information, see https://redis.io/commands/vsim.
|
|
160
170
|
"""
|
|
161
171
|
|
|
162
172
|
if not input:
|
|
@@ -173,9 +183,17 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
173
183
|
else:
|
|
174
184
|
pieces.extend(["ELE", input])
|
|
175
185
|
|
|
176
|
-
if with_scores:
|
|
177
|
-
|
|
178
|
-
|
|
186
|
+
if with_scores or with_attribs:
|
|
187
|
+
if get_protocol_version(self.client) in ["3", 3]:
|
|
188
|
+
options[CallbacksOptions.RESP3.value] = True
|
|
189
|
+
|
|
190
|
+
if with_scores:
|
|
191
|
+
pieces.append("WITHSCORES")
|
|
192
|
+
options[CallbacksOptions.WITHSCORES.value] = True
|
|
193
|
+
|
|
194
|
+
if with_attribs:
|
|
195
|
+
pieces.append("WITHATTRIBS")
|
|
196
|
+
options[CallbacksOptions.WITHATTRIBS.value] = True
|
|
179
197
|
|
|
180
198
|
if count:
|
|
181
199
|
pieces.extend(["COUNT", count])
|
|
@@ -210,7 +228,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
210
228
|
|
|
211
229
|
Raises `redis.exceptions.ResponseError` if the vector set doesn't exist.
|
|
212
230
|
|
|
213
|
-
For more information see https://redis.io/commands/vdim
|
|
231
|
+
For more information, see https://redis.io/commands/vdim.
|
|
214
232
|
"""
|
|
215
233
|
return self.execute_command(VDIM_CMD, key)
|
|
216
234
|
|
|
@@ -220,7 +238,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
220
238
|
|
|
221
239
|
Raises `redis.exceptions.ResponseError` if the vector set doesn't exist.
|
|
222
240
|
|
|
223
|
-
For more information see https://redis.io/commands/vcard
|
|
241
|
+
For more information, see https://redis.io/commands/vcard.
|
|
224
242
|
"""
|
|
225
243
|
return self.execute_command(VCARD_CMD, key)
|
|
226
244
|
|
|
@@ -228,7 +246,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
228
246
|
"""
|
|
229
247
|
Remove an element from a vector set.
|
|
230
248
|
|
|
231
|
-
For more information see https://redis.io/commands/vrem
|
|
249
|
+
For more information, see https://redis.io/commands/vrem.
|
|
232
250
|
"""
|
|
233
251
|
return self.execute_command(VREM_CMD, key, element)
|
|
234
252
|
|
|
@@ -242,10 +260,10 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
242
260
|
Get the approximated vector of an element ``element`` from vector set ``key``.
|
|
243
261
|
|
|
244
262
|
``raw`` is a boolean flag that indicates whether to return the
|
|
245
|
-
|
|
263
|
+
internal representation used by the vector.
|
|
246
264
|
|
|
247
265
|
|
|
248
|
-
For more information see https://redis.io/commands/
|
|
266
|
+
For more information, see https://redis.io/commands/vemb.
|
|
249
267
|
"""
|
|
250
268
|
options = {}
|
|
251
269
|
pieces = []
|
|
@@ -293,7 +311,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
293
311
|
If the ``WITHSCORES`` option is provided, the result is a list of dicts,
|
|
294
312
|
where each dict contains the neighbors for one level, with the scores as values.
|
|
295
313
|
|
|
296
|
-
For more information see https://redis.io/commands/vlinks
|
|
314
|
+
For more information, see https://redis.io/commands/vlinks
|
|
297
315
|
"""
|
|
298
316
|
options = {}
|
|
299
317
|
pieces = []
|
|
@@ -309,7 +327,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
309
327
|
"""
|
|
310
328
|
Get information about a vector set.
|
|
311
329
|
|
|
312
|
-
For more information see https://redis.io/commands/vinfo
|
|
330
|
+
For more information, see https://redis.io/commands/vinfo.
|
|
313
331
|
"""
|
|
314
332
|
return self.execute_command(VINFO_CMD, key)
|
|
315
333
|
|
|
@@ -320,7 +338,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
320
338
|
Associate or remove JSON attributes ``attributes`` of element ``element``
|
|
321
339
|
for vector set ``key``.
|
|
322
340
|
|
|
323
|
-
For more information see https://redis.io/commands/vsetattr
|
|
341
|
+
For more information, see https://redis.io/commands/vsetattr
|
|
324
342
|
"""
|
|
325
343
|
if attributes is None:
|
|
326
344
|
attributes_json = "{}"
|
|
@@ -336,12 +354,12 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
336
354
|
self, key: KeyT, element: str
|
|
337
355
|
) -> Union[Optional[Awaitable[dict]], Optional[dict]]:
|
|
338
356
|
"""
|
|
339
|
-
Retrieve the JSON attributes of an element ``
|
|
357
|
+
Retrieve the JSON attributes of an element ``element `` for vector set ``key``.
|
|
340
358
|
|
|
341
359
|
If the element does not exist, or if the vector set does not exist, None is
|
|
342
360
|
returned.
|
|
343
361
|
|
|
344
|
-
For more information see https://redis.io/commands/vgetattr
|
|
362
|
+
For more information, see https://redis.io/commands/vgetattr.
|
|
345
363
|
"""
|
|
346
364
|
return self.execute_command(VGETATTR_CMD, key, element)
|
|
347
365
|
|
|
@@ -365,7 +383,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
365
383
|
|
|
366
384
|
If the vector set does not exist, ``None`` is returned.
|
|
367
385
|
|
|
368
|
-
For more information see https://redis.io/commands/vrandmember
|
|
386
|
+
For more information, see https://redis.io/commands/vrandmember.
|
|
369
387
|
"""
|
|
370
388
|
pieces = []
|
|
371
389
|
pieces.append(key)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
1
3
|
from redis._parsers.helpers import pairs_to_dict
|
|
2
4
|
from redis.commands.vectorset.commands import CallbacksOptions
|
|
3
5
|
|
|
@@ -75,19 +77,53 @@ def parse_vsim_result(response, **options):
|
|
|
75
77
|
structures depending on input options.
|
|
76
78
|
Parsing VSIM result into:
|
|
77
79
|
- List[List[str]]
|
|
78
|
-
- List[Dict[str, Number]]
|
|
80
|
+
- List[Dict[str, Number]] - when with_scores is used (without attributes)
|
|
81
|
+
- List[Dict[str, Mapping[str, Any]]] - when with_attribs is used (without scores)
|
|
82
|
+
- List[Dict[str, Union[Number, Mapping[str, Any]]]] - when with_scores and with_attribs are used
|
|
83
|
+
|
|
79
84
|
"""
|
|
80
85
|
if response is None:
|
|
81
86
|
return response
|
|
82
87
|
|
|
83
|
-
|
|
88
|
+
withscores = bool(options.get(CallbacksOptions.WITHSCORES.value))
|
|
89
|
+
withattribs = bool(options.get(CallbacksOptions.WITHATTRIBS.value))
|
|
90
|
+
|
|
91
|
+
# Exactly one of withscores or withattribs is True
|
|
92
|
+
if (withscores and not withattribs) or (not withscores and withattribs):
|
|
84
93
|
# Redis will return a list of list of pairs.
|
|
85
94
|
# This list have to be transformed to dict
|
|
86
95
|
result_dict = {}
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
if options.get(CallbacksOptions.RESP3.value):
|
|
97
|
+
resp_dict = response
|
|
98
|
+
else:
|
|
99
|
+
resp_dict = pairs_to_dict(response)
|
|
100
|
+
for key, value in resp_dict.items():
|
|
101
|
+
if withscores:
|
|
102
|
+
value = float(value)
|
|
103
|
+
else:
|
|
104
|
+
value = json.loads(value) if value else None
|
|
105
|
+
|
|
89
106
|
result_dict[key] = value
|
|
90
107
|
return result_dict
|
|
108
|
+
elif withscores and withattribs:
|
|
109
|
+
it = iter(response)
|
|
110
|
+
result_dict = {}
|
|
111
|
+
if options.get(CallbacksOptions.RESP3.value):
|
|
112
|
+
for elem, data in response.items():
|
|
113
|
+
if data[1] is not None:
|
|
114
|
+
attribs_dict = json.loads(data[1])
|
|
115
|
+
else:
|
|
116
|
+
attribs_dict = None
|
|
117
|
+
result_dict[elem] = {"score": data[0], "attributes": attribs_dict}
|
|
118
|
+
else:
|
|
119
|
+
for elem, score, attribs in zip(it, it, it):
|
|
120
|
+
if attribs is not None:
|
|
121
|
+
attribs_dict = json.loads(attribs)
|
|
122
|
+
else:
|
|
123
|
+
attribs_dict = None
|
|
124
|
+
|
|
125
|
+
result_dict[elem] = {"score": float(score), "attributes": attribs_dict}
|
|
126
|
+
return result_dict
|
|
91
127
|
else:
|
|
92
128
|
# return the list of elements for each level
|
|
93
129
|
# list of lists
|