redis 5.3.0b5__py3-none-any.whl → 6.0.0b2__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.
Files changed (44) hide show
  1. redis/__init__.py +2 -11
  2. redis/_parsers/base.py +14 -2
  3. redis/asyncio/client.py +27 -14
  4. redis/asyncio/cluster.py +85 -59
  5. redis/asyncio/connection.py +76 -23
  6. redis/asyncio/lock.py +26 -5
  7. redis/asyncio/sentinel.py +11 -1
  8. redis/asyncio/utils.py +1 -1
  9. redis/auth/token.py +6 -2
  10. redis/backoff.py +15 -0
  11. redis/client.py +23 -14
  12. redis/cluster.py +112 -48
  13. redis/commands/cluster.py +1 -11
  14. redis/commands/core.py +219 -207
  15. redis/commands/helpers.py +0 -70
  16. redis/commands/redismodules.py +5 -17
  17. redis/commands/search/aggregation.py +3 -1
  18. redis/commands/search/commands.py +41 -14
  19. redis/commands/search/dialect.py +3 -0
  20. redis/commands/search/profile_information.py +14 -0
  21. redis/commands/search/query.py +5 -1
  22. redis/commands/vectorset/__init__.py +46 -0
  23. redis/commands/vectorset/commands.py +367 -0
  24. redis/commands/vectorset/utils.py +94 -0
  25. redis/connection.py +76 -27
  26. redis/exceptions.py +4 -1
  27. redis/lock.py +24 -4
  28. redis/ocsp.py +2 -1
  29. redis/sentinel.py +3 -1
  30. redis/utils.py +114 -1
  31. {redis-5.3.0b5.dist-info → redis-6.0.0b2.dist-info}/METADATA +57 -23
  32. {redis-5.3.0b5.dist-info → redis-6.0.0b2.dist-info}/RECORD +35 -39
  33. {redis-5.3.0b5.dist-info → redis-6.0.0b2.dist-info}/WHEEL +1 -2
  34. redis/commands/graph/__init__.py +0 -263
  35. redis/commands/graph/commands.py +0 -313
  36. redis/commands/graph/edge.py +0 -91
  37. redis/commands/graph/exceptions.py +0 -3
  38. redis/commands/graph/execution_plan.py +0 -211
  39. redis/commands/graph/node.py +0 -88
  40. redis/commands/graph/path.py +0 -78
  41. redis/commands/graph/query_result.py +0 -588
  42. redis-5.3.0b5.dist-info/top_level.txt +0 -1
  43. /redis/commands/search/{indexDefinition.py → index_definition.py} +0 -0
  44. {redis-5.3.0b5.dist-info → redis-6.0.0b2.dist-info/licenses}/LICENSE +0 -0
@@ -1,78 +0,0 @@
1
- from .edge import Edge
2
- from .node import Node
3
-
4
-
5
- class Path:
6
- def __init__(self, nodes, edges):
7
- if not (isinstance(nodes, list) and isinstance(edges, list)):
8
- raise TypeError("nodes and edges must be list")
9
-
10
- self._nodes = nodes
11
- self._edges = edges
12
- self.append_type = Node
13
-
14
- @classmethod
15
- def new_empty_path(cls):
16
- return cls([], [])
17
-
18
- def nodes(self):
19
- return self._nodes
20
-
21
- def edges(self):
22
- return self._edges
23
-
24
- def get_node(self, index):
25
- return self._nodes[index]
26
-
27
- def get_relationship(self, index):
28
- return self._edges[index]
29
-
30
- def first_node(self):
31
- return self._nodes[0]
32
-
33
- def last_node(self):
34
- return self._nodes[-1]
35
-
36
- def edge_count(self):
37
- return len(self._edges)
38
-
39
- def nodes_count(self):
40
- return len(self._nodes)
41
-
42
- def add_node(self, node):
43
- if not isinstance(node, self.append_type):
44
- raise AssertionError("Add Edge before adding Node")
45
- self._nodes.append(node)
46
- self.append_type = Edge
47
- return self
48
-
49
- def add_edge(self, edge):
50
- if not isinstance(edge, self.append_type):
51
- raise AssertionError("Add Node before adding Edge")
52
- self._edges.append(edge)
53
- self.append_type = Node
54
- return self
55
-
56
- def __eq__(self, other):
57
- # Type checking
58
- if not isinstance(other, Path):
59
- return False
60
-
61
- return self.nodes() == other.nodes() and self.edges() == other.edges()
62
-
63
- def __str__(self):
64
- res = "<"
65
- edge_count = self.edge_count()
66
- for i in range(0, edge_count):
67
- node_id = self.get_node(i).id
68
- res += "(" + str(node_id) + ")"
69
- edge = self.get_relationship(i)
70
- res += (
71
- "-[" + str(int(edge.id)) + "]->"
72
- if edge.src_node == node_id
73
- else "<-[" + str(int(edge.id)) + "]-"
74
- )
75
- node_id = self.get_node(edge_count).id
76
- res += "(" + str(node_id) + ")"
77
- res += ">"
78
- return res
@@ -1,588 +0,0 @@
1
- import sys
2
- from collections import OrderedDict
3
-
4
- # from prettytable import PrettyTable
5
- from redis import ResponseError
6
-
7
- from .edge import Edge
8
- from .exceptions import VersionMismatchException
9
- from .node import Node
10
- from .path import Path
11
-
12
- LABELS_ADDED = "Labels added"
13
- LABELS_REMOVED = "Labels removed"
14
- NODES_CREATED = "Nodes created"
15
- NODES_DELETED = "Nodes deleted"
16
- RELATIONSHIPS_DELETED = "Relationships deleted"
17
- PROPERTIES_SET = "Properties set"
18
- PROPERTIES_REMOVED = "Properties removed"
19
- RELATIONSHIPS_CREATED = "Relationships created"
20
- INDICES_CREATED = "Indices created"
21
- INDICES_DELETED = "Indices deleted"
22
- CACHED_EXECUTION = "Cached execution"
23
- INTERNAL_EXECUTION_TIME = "internal execution time"
24
-
25
- STATS = [
26
- LABELS_ADDED,
27
- LABELS_REMOVED,
28
- NODES_CREATED,
29
- PROPERTIES_SET,
30
- PROPERTIES_REMOVED,
31
- RELATIONSHIPS_CREATED,
32
- NODES_DELETED,
33
- RELATIONSHIPS_DELETED,
34
- INDICES_CREATED,
35
- INDICES_DELETED,
36
- CACHED_EXECUTION,
37
- INTERNAL_EXECUTION_TIME,
38
- ]
39
-
40
-
41
- class ResultSetColumnTypes:
42
- COLUMN_UNKNOWN = 0
43
- COLUMN_SCALAR = 1
44
- COLUMN_NODE = 2 # Unused as of RedisGraph v2.1.0, retained for backwards compatibility. # noqa
45
- COLUMN_RELATION = 3 # Unused as of RedisGraph v2.1.0, retained for backwards compatibility. # noqa
46
-
47
-
48
- class ResultSetScalarTypes:
49
- VALUE_UNKNOWN = 0
50
- VALUE_NULL = 1
51
- VALUE_STRING = 2
52
- VALUE_INTEGER = 3
53
- VALUE_BOOLEAN = 4
54
- VALUE_DOUBLE = 5
55
- VALUE_ARRAY = 6
56
- VALUE_EDGE = 7
57
- VALUE_NODE = 8
58
- VALUE_PATH = 9
59
- VALUE_MAP = 10
60
- VALUE_POINT = 11
61
-
62
-
63
- class QueryResult:
64
- def __init__(self, graph, response, profile=False):
65
- """
66
- A class that represents a result of the query operation.
67
-
68
- Args:
69
-
70
- graph:
71
- The graph on which the query was executed.
72
- response:
73
- The response from the server.
74
- profile:
75
- A boolean indicating if the query command was "GRAPH.PROFILE"
76
- """
77
- self.graph = graph
78
- self.header = []
79
- self.result_set = []
80
-
81
- # in case of an error an exception will be raised
82
- self._check_for_errors(response)
83
-
84
- if len(response) == 1:
85
- self.parse_statistics(response[0])
86
- elif profile:
87
- self.parse_profile(response)
88
- else:
89
- # start by parsing statistics, matches the one we have
90
- self.parse_statistics(response[-1]) # Last element.
91
- self.parse_results(response)
92
-
93
- def _check_for_errors(self, response):
94
- """
95
- Check if the response contains an error.
96
- """
97
- if isinstance(response[0], ResponseError):
98
- error = response[0]
99
- if str(error) == "version mismatch":
100
- version = response[1]
101
- error = VersionMismatchException(version)
102
- raise error
103
-
104
- # If we encountered a run-time error, the last response
105
- # element will be an exception
106
- if isinstance(response[-1], ResponseError):
107
- raise response[-1]
108
-
109
- def parse_results(self, raw_result_set):
110
- """
111
- Parse the query execution result returned from the server.
112
- """
113
- self.header = self.parse_header(raw_result_set)
114
-
115
- # Empty header.
116
- if len(self.header) == 0:
117
- return
118
-
119
- self.result_set = self.parse_records(raw_result_set)
120
-
121
- def parse_statistics(self, raw_statistics):
122
- """
123
- Parse the statistics returned in the response.
124
- """
125
- self.statistics = {}
126
-
127
- # decode statistics
128
- for idx, stat in enumerate(raw_statistics):
129
- if isinstance(stat, bytes):
130
- raw_statistics[idx] = stat.decode()
131
-
132
- for s in STATS:
133
- v = self._get_value(s, raw_statistics)
134
- if v is not None:
135
- self.statistics[s] = v
136
-
137
- def parse_header(self, raw_result_set):
138
- """
139
- Parse the header of the result.
140
- """
141
- # An array of column name/column type pairs.
142
- header = raw_result_set[0]
143
- return header
144
-
145
- def parse_records(self, raw_result_set):
146
- """
147
- Parses the result set and returns a list of records.
148
- """
149
- records = [
150
- [
151
- self.parse_record_types[self.header[idx][0]](cell)
152
- for idx, cell in enumerate(row)
153
- ]
154
- for row in raw_result_set[1]
155
- ]
156
-
157
- return records
158
-
159
- def parse_entity_properties(self, props):
160
- """
161
- Parse node / edge properties.
162
- """
163
- # [[name, value type, value] X N]
164
- properties = {}
165
- for prop in props:
166
- prop_name = self.graph.get_property(prop[0])
167
- prop_value = self.parse_scalar(prop[1:])
168
- properties[prop_name] = prop_value
169
-
170
- return properties
171
-
172
- def parse_string(self, cell):
173
- """
174
- Parse the cell as a string.
175
- """
176
- if isinstance(cell, bytes):
177
- return cell.decode()
178
- elif not isinstance(cell, str):
179
- return str(cell)
180
- else:
181
- return cell
182
-
183
- def parse_node(self, cell):
184
- """
185
- Parse the cell to a node.
186
- """
187
- # Node ID (integer),
188
- # [label string offset (integer)],
189
- # [[name, value type, value] X N]
190
-
191
- node_id = int(cell[0])
192
- labels = None
193
- if len(cell[1]) > 0:
194
- labels = []
195
- for inner_label in cell[1]:
196
- labels.append(self.graph.get_label(inner_label))
197
- properties = self.parse_entity_properties(cell[2])
198
- return Node(node_id=node_id, label=labels, properties=properties)
199
-
200
- def parse_edge(self, cell):
201
- """
202
- Parse the cell to an edge.
203
- """
204
- # Edge ID (integer),
205
- # reltype string offset (integer),
206
- # src node ID offset (integer),
207
- # dest node ID offset (integer),
208
- # [[name, value, value type] X N]
209
-
210
- edge_id = int(cell[0])
211
- relation = self.graph.get_relation(cell[1])
212
- src_node_id = int(cell[2])
213
- dest_node_id = int(cell[3])
214
- properties = self.parse_entity_properties(cell[4])
215
- return Edge(
216
- src_node_id, relation, dest_node_id, edge_id=edge_id, properties=properties
217
- )
218
-
219
- def parse_path(self, cell):
220
- """
221
- Parse the cell to a path.
222
- """
223
- nodes = self.parse_scalar(cell[0])
224
- edges = self.parse_scalar(cell[1])
225
- return Path(nodes, edges)
226
-
227
- def parse_map(self, cell):
228
- """
229
- Parse the cell as a map.
230
- """
231
- m = OrderedDict()
232
- n_entries = len(cell)
233
-
234
- # A map is an array of key value pairs.
235
- # 1. key (string)
236
- # 2. array: (value type, value)
237
- for i in range(0, n_entries, 2):
238
- key = self.parse_string(cell[i])
239
- m[key] = self.parse_scalar(cell[i + 1])
240
-
241
- return m
242
-
243
- def parse_point(self, cell):
244
- """
245
- Parse the cell to point.
246
- """
247
- p = {}
248
- # A point is received an array of the form: [latitude, longitude]
249
- # It is returned as a map of the form: {"latitude": latitude, "longitude": longitude} # noqa
250
- p["latitude"] = float(cell[0])
251
- p["longitude"] = float(cell[1])
252
- return p
253
-
254
- def parse_null(self, cell):
255
- """
256
- Parse a null value.
257
- """
258
- return None
259
-
260
- def parse_integer(self, cell):
261
- """
262
- Parse the integer value from the cell.
263
- """
264
- return int(cell)
265
-
266
- def parse_boolean(self, value):
267
- """
268
- Parse the cell value as a boolean.
269
- """
270
- value = value.decode() if isinstance(value, bytes) else value
271
- try:
272
- scalar = True if strtobool(value) else False
273
- except ValueError:
274
- sys.stderr.write("unknown boolean type\n")
275
- scalar = None
276
- return scalar
277
-
278
- def parse_double(self, cell):
279
- """
280
- Parse the cell as a double.
281
- """
282
- return float(cell)
283
-
284
- def parse_array(self, value):
285
- """
286
- Parse an array of values.
287
- """
288
- scalar = [self.parse_scalar(value[i]) for i in range(len(value))]
289
- return scalar
290
-
291
- def parse_unknown(self, cell):
292
- """
293
- Parse a cell of unknown type.
294
- """
295
- sys.stderr.write("Unknown type\n")
296
- return None
297
-
298
- def parse_scalar(self, cell):
299
- """
300
- Parse a scalar value from a cell in the result set.
301
- """
302
- scalar_type = int(cell[0])
303
- value = cell[1]
304
- scalar = self.parse_scalar_types[scalar_type](value)
305
-
306
- return scalar
307
-
308
- def parse_profile(self, response):
309
- self.result_set = [x[0 : x.index(",")].strip() for x in response]
310
-
311
- def is_empty(self):
312
- return len(self.result_set) == 0
313
-
314
- @staticmethod
315
- def _get_value(prop, statistics):
316
- for stat in statistics:
317
- if prop in stat:
318
- return float(stat.split(": ")[1].split(" ")[0])
319
-
320
- return None
321
-
322
- def _get_stat(self, stat):
323
- return self.statistics[stat] if stat in self.statistics else 0
324
-
325
- @property
326
- def labels_added(self):
327
- """Returns the number of labels added in the query"""
328
- return self._get_stat(LABELS_ADDED)
329
-
330
- @property
331
- def labels_removed(self):
332
- """Returns the number of labels removed in the query"""
333
- return self._get_stat(LABELS_REMOVED)
334
-
335
- @property
336
- def nodes_created(self):
337
- """Returns the number of nodes created in the query"""
338
- return self._get_stat(NODES_CREATED)
339
-
340
- @property
341
- def nodes_deleted(self):
342
- """Returns the number of nodes deleted in the query"""
343
- return self._get_stat(NODES_DELETED)
344
-
345
- @property
346
- def properties_set(self):
347
- """Returns the number of properties set in the query"""
348
- return self._get_stat(PROPERTIES_SET)
349
-
350
- @property
351
- def properties_removed(self):
352
- """Returns the number of properties removed in the query"""
353
- return self._get_stat(PROPERTIES_REMOVED)
354
-
355
- @property
356
- def relationships_created(self):
357
- """Returns the number of relationships created in the query"""
358
- return self._get_stat(RELATIONSHIPS_CREATED)
359
-
360
- @property
361
- def relationships_deleted(self):
362
- """Returns the number of relationships deleted in the query"""
363
- return self._get_stat(RELATIONSHIPS_DELETED)
364
-
365
- @property
366
- def indices_created(self):
367
- """Returns the number of indices created in the query"""
368
- return self._get_stat(INDICES_CREATED)
369
-
370
- @property
371
- def indices_deleted(self):
372
- """Returns the number of indices deleted in the query"""
373
- return self._get_stat(INDICES_DELETED)
374
-
375
- @property
376
- def cached_execution(self):
377
- """Returns whether or not the query execution plan was cached"""
378
- return self._get_stat(CACHED_EXECUTION) == 1
379
-
380
- @property
381
- def run_time_ms(self):
382
- """Returns the server execution time of the query"""
383
- return self._get_stat(INTERNAL_EXECUTION_TIME)
384
-
385
- @property
386
- def parse_scalar_types(self):
387
- return {
388
- ResultSetScalarTypes.VALUE_NULL: self.parse_null,
389
- ResultSetScalarTypes.VALUE_STRING: self.parse_string,
390
- ResultSetScalarTypes.VALUE_INTEGER: self.parse_integer,
391
- ResultSetScalarTypes.VALUE_BOOLEAN: self.parse_boolean,
392
- ResultSetScalarTypes.VALUE_DOUBLE: self.parse_double,
393
- ResultSetScalarTypes.VALUE_ARRAY: self.parse_array,
394
- ResultSetScalarTypes.VALUE_NODE: self.parse_node,
395
- ResultSetScalarTypes.VALUE_EDGE: self.parse_edge,
396
- ResultSetScalarTypes.VALUE_PATH: self.parse_path,
397
- ResultSetScalarTypes.VALUE_MAP: self.parse_map,
398
- ResultSetScalarTypes.VALUE_POINT: self.parse_point,
399
- ResultSetScalarTypes.VALUE_UNKNOWN: self.parse_unknown,
400
- }
401
-
402
- @property
403
- def parse_record_types(self):
404
- return {
405
- ResultSetColumnTypes.COLUMN_SCALAR: self.parse_scalar,
406
- ResultSetColumnTypes.COLUMN_NODE: self.parse_node,
407
- ResultSetColumnTypes.COLUMN_RELATION: self.parse_edge,
408
- ResultSetColumnTypes.COLUMN_UNKNOWN: self.parse_unknown,
409
- }
410
-
411
-
412
- class AsyncQueryResult(QueryResult):
413
- """
414
- Async version for the QueryResult class - a class that
415
- represents a result of the query operation.
416
- """
417
-
418
- def __init__(self):
419
- """
420
- To init the class you must call self.initialize()
421
- """
422
- pass
423
-
424
- async def initialize(self, graph, response, profile=False):
425
- """
426
- Initializes the class.
427
- Args:
428
-
429
- graph:
430
- The graph on which the query was executed.
431
- response:
432
- The response from the server.
433
- profile:
434
- A boolean indicating if the query command was "GRAPH.PROFILE"
435
- """
436
- self.graph = graph
437
- self.header = []
438
- self.result_set = []
439
-
440
- # in case of an error an exception will be raised
441
- self._check_for_errors(response)
442
-
443
- if len(response) == 1:
444
- self.parse_statistics(response[0])
445
- elif profile:
446
- self.parse_profile(response)
447
- else:
448
- # start by parsing statistics, matches the one we have
449
- self.parse_statistics(response[-1]) # Last element.
450
- await self.parse_results(response)
451
-
452
- return self
453
-
454
- async def parse_node(self, cell):
455
- """
456
- Parses a node from the cell.
457
- """
458
- # Node ID (integer),
459
- # [label string offset (integer)],
460
- # [[name, value type, value] X N]
461
-
462
- labels = None
463
- if len(cell[1]) > 0:
464
- labels = []
465
- for inner_label in cell[1]:
466
- labels.append(await self.graph.get_label(inner_label))
467
- properties = await self.parse_entity_properties(cell[2])
468
- node_id = int(cell[0])
469
- return Node(node_id=node_id, label=labels, properties=properties)
470
-
471
- async def parse_scalar(self, cell):
472
- """
473
- Parses a scalar value from the server response.
474
- """
475
- scalar_type = int(cell[0])
476
- value = cell[1]
477
- try:
478
- scalar = await self.parse_scalar_types[scalar_type](value)
479
- except TypeError:
480
- # Not all of the functions are async
481
- scalar = self.parse_scalar_types[scalar_type](value)
482
-
483
- return scalar
484
-
485
- async def parse_records(self, raw_result_set):
486
- """
487
- Parses the result set and returns a list of records.
488
- """
489
- records = []
490
- for row in raw_result_set[1]:
491
- record = [
492
- await self.parse_record_types[self.header[idx][0]](cell)
493
- for idx, cell in enumerate(row)
494
- ]
495
- records.append(record)
496
-
497
- return records
498
-
499
- async def parse_results(self, raw_result_set):
500
- """
501
- Parse the query execution result returned from the server.
502
- """
503
- self.header = self.parse_header(raw_result_set)
504
-
505
- # Empty header.
506
- if len(self.header) == 0:
507
- return
508
-
509
- self.result_set = await self.parse_records(raw_result_set)
510
-
511
- async def parse_entity_properties(self, props):
512
- """
513
- Parse node / edge properties.
514
- """
515
- # [[name, value type, value] X N]
516
- properties = {}
517
- for prop in props:
518
- prop_name = await self.graph.get_property(prop[0])
519
- prop_value = await self.parse_scalar(prop[1:])
520
- properties[prop_name] = prop_value
521
-
522
- return properties
523
-
524
- async def parse_edge(self, cell):
525
- """
526
- Parse the cell to an edge.
527
- """
528
- # Edge ID (integer),
529
- # reltype string offset (integer),
530
- # src node ID offset (integer),
531
- # dest node ID offset (integer),
532
- # [[name, value, value type] X N]
533
-
534
- edge_id = int(cell[0])
535
- relation = await self.graph.get_relation(cell[1])
536
- src_node_id = int(cell[2])
537
- dest_node_id = int(cell[3])
538
- properties = await self.parse_entity_properties(cell[4])
539
- return Edge(
540
- src_node_id, relation, dest_node_id, edge_id=edge_id, properties=properties
541
- )
542
-
543
- async def parse_path(self, cell):
544
- """
545
- Parse the cell to a path.
546
- """
547
- nodes = await self.parse_scalar(cell[0])
548
- edges = await self.parse_scalar(cell[1])
549
- return Path(nodes, edges)
550
-
551
- async def parse_map(self, cell):
552
- """
553
- Parse the cell to a map.
554
- """
555
- m = OrderedDict()
556
- n_entries = len(cell)
557
-
558
- # A map is an array of key value pairs.
559
- # 1. key (string)
560
- # 2. array: (value type, value)
561
- for i in range(0, n_entries, 2):
562
- key = self.parse_string(cell[i])
563
- m[key] = await self.parse_scalar(cell[i + 1])
564
-
565
- return m
566
-
567
- async def parse_array(self, value):
568
- """
569
- Parse array value.
570
- """
571
- scalar = [await self.parse_scalar(value[i]) for i in range(len(value))]
572
- return scalar
573
-
574
-
575
- def strtobool(val):
576
- """
577
- Convert a string representation of truth to true (1) or false (0).
578
- True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
579
- are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
580
- 'val' is anything else.
581
- """
582
- val = val.lower()
583
- if val in ("y", "yes", "t", "true", "on", "1"):
584
- return True
585
- elif val in ("n", "no", "f", "false", "off", "0"):
586
- return False
587
- else:
588
- raise ValueError(f"invalid truth value {val!r}")
@@ -1 +0,0 @@
1
- redis