coredis 4.24.0__py3-none-any.whl → 5.0.0rc1__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.

Potentially problematic release.


This version of coredis might be problematic. Click here for more details.

Files changed (77) hide show
  1. coredis/__init__.py +1 -3
  2. coredis/_packer.py +10 -10
  3. coredis/_protocols.py +23 -32
  4. coredis/_py_311_typing.py +20 -0
  5. coredis/_py_312_typing.py +17 -0
  6. coredis/_utils.py +49 -51
  7. coredis/_version.py +3 -3
  8. coredis/cache.py +57 -82
  9. coredis/client/__init__.py +1 -2
  10. coredis/client/basic.py +129 -56
  11. coredis/client/cluster.py +147 -70
  12. coredis/commands/__init__.py +27 -7
  13. coredis/commands/_key_spec.py +11 -10
  14. coredis/commands/_utils.py +1 -1
  15. coredis/commands/_validators.py +30 -20
  16. coredis/commands/_wrappers.py +19 -99
  17. coredis/commands/bitfield.py +10 -2
  18. coredis/commands/constants.py +20 -3
  19. coredis/commands/core.py +1627 -1246
  20. coredis/commands/function.py +21 -19
  21. coredis/commands/monitor.py +0 -71
  22. coredis/commands/pubsub.py +7 -142
  23. coredis/commands/request.py +108 -0
  24. coredis/commands/script.py +9 -9
  25. coredis/commands/sentinel.py +60 -49
  26. coredis/connection.py +14 -15
  27. coredis/exceptions.py +2 -2
  28. coredis/experimental/__init__.py +0 -4
  29. coredis/globals.py +3 -0
  30. coredis/modules/autocomplete.py +28 -30
  31. coredis/modules/base.py +15 -31
  32. coredis/modules/filters.py +269 -245
  33. coredis/modules/graph.py +61 -62
  34. coredis/modules/json.py +172 -140
  35. coredis/modules/response/_callbacks/autocomplete.py +5 -4
  36. coredis/modules/response/_callbacks/graph.py +34 -29
  37. coredis/modules/response/_callbacks/json.py +5 -3
  38. coredis/modules/response/_callbacks/search.py +49 -53
  39. coredis/modules/response/_callbacks/timeseries.py +18 -30
  40. coredis/modules/response/types.py +1 -5
  41. coredis/modules/search.py +186 -169
  42. coredis/modules/timeseries.py +184 -164
  43. coredis/parser.py +6 -19
  44. coredis/pipeline.py +391 -422
  45. coredis/pool/basic.py +7 -7
  46. coredis/pool/cluster.py +3 -3
  47. coredis/pool/nodemanager.py +10 -3
  48. coredis/response/_callbacks/__init__.py +76 -57
  49. coredis/response/_callbacks/acl.py +0 -3
  50. coredis/response/_callbacks/cluster.py +25 -16
  51. coredis/response/_callbacks/command.py +8 -6
  52. coredis/response/_callbacks/connection.py +4 -3
  53. coredis/response/_callbacks/geo.py +17 -13
  54. coredis/response/_callbacks/hash.py +13 -11
  55. coredis/response/_callbacks/keys.py +9 -5
  56. coredis/response/_callbacks/module.py +2 -3
  57. coredis/response/_callbacks/script.py +6 -8
  58. coredis/response/_callbacks/sentinel.py +21 -17
  59. coredis/response/_callbacks/server.py +36 -14
  60. coredis/response/_callbacks/sets.py +3 -4
  61. coredis/response/_callbacks/sorted_set.py +27 -24
  62. coredis/response/_callbacks/streams.py +22 -13
  63. coredis/response/_callbacks/strings.py +7 -6
  64. coredis/response/_callbacks/vector_sets.py +126 -0
  65. coredis/response/types.py +13 -4
  66. coredis/sentinel.py +1 -1
  67. coredis/stream.py +4 -3
  68. coredis/tokens.py +343 -16
  69. coredis/typing.py +432 -79
  70. {coredis-4.24.0.dist-info → coredis-5.0.0rc1.dist-info}/METADATA +4 -5
  71. coredis-5.0.0rc1.dist-info/RECORD +95 -0
  72. coredis/client/keydb.py +0 -336
  73. coredis/pipeline.pyi +0 -2103
  74. coredis-4.24.0.dist-info/RECORD +0 -93
  75. {coredis-4.24.0.dist-info → coredis-5.0.0rc1.dist-info}/WHEEL +0 -0
  76. {coredis-4.24.0.dist-info → coredis-5.0.0rc1.dist-info}/licenses/LICENSE +0 -0
  77. {coredis-4.24.0.dist-info → coredis-5.0.0rc1.dist-info}/top_level.txt +0 -0
coredis/pool/basic.py CHANGED
@@ -20,7 +20,7 @@ from coredis.connection import (
20
20
  UnixDomainSocketConnection,
21
21
  )
22
22
  from coredis.exceptions import ConnectionError
23
- from coredis.typing import Callable, ClassVar, TypeVar, ValueT
23
+ from coredis.typing import Callable, ClassVar, RedisValueT, TypeVar
24
24
 
25
25
  _CPT = TypeVar("_CPT", bound="ConnectionPool")
26
26
 
@@ -250,9 +250,9 @@ class ConnectionPool:
250
250
  async def get_connection(
251
251
  self,
252
252
  command_name: bytes | None = None,
253
- *args: ValueT,
253
+ *args: RedisValueT,
254
254
  acquire: bool = True,
255
- **kwargs: ValueT | None,
255
+ **kwargs: RedisValueT | None,
256
256
  ) -> Connection:
257
257
  """Gets a connection from the pool"""
258
258
  self.checkpid()
@@ -290,7 +290,7 @@ class ConnectionPool:
290
290
  connection.disconnect()
291
291
  self._created_connections -= 1
292
292
 
293
- def _make_connection(self, **options: ValueT | None) -> Connection:
293
+ def _make_connection(self, **options: RedisValueT | None) -> Connection:
294
294
  """
295
295
  Creates a new connection
296
296
  """
@@ -347,7 +347,7 @@ class BlockingConnectionPool(ConnectionPool):
347
347
  timeout: int = 20,
348
348
  max_idle_time: int = 0,
349
349
  idle_check_interval: int = 1,
350
- **connection_kwargs: ValueT | None,
350
+ **connection_kwargs: RedisValueT | None,
351
351
  ):
352
352
  self.timeout = timeout
353
353
  self.queue_class = queue_class
@@ -394,9 +394,9 @@ class BlockingConnectionPool(ConnectionPool):
394
394
  async def get_connection(
395
395
  self,
396
396
  command_name: bytes | None = None,
397
- *args: ValueT,
397
+ *args: RedisValueT,
398
398
  acquire: bool = True,
399
- **kwargs: ValueT | None,
399
+ **kwargs: RedisValueT | None,
400
400
  ) -> Connection:
401
401
  """Gets a connection from the pool"""
402
402
  self.checkpid()
coredis/pool/cluster.py CHANGED
@@ -21,8 +21,8 @@ from coredis.typing import (
21
21
  ClassVar,
22
22
  Iterable,
23
23
  Node,
24
+ RedisValueT,
24
25
  StringT,
25
- ValueT,
26
26
  )
27
27
 
28
28
 
@@ -205,9 +205,9 @@ class ClusterConnectionPool(ConnectionPool):
205
205
  async def get_connection(
206
206
  self,
207
207
  command_name: bytes | None = None,
208
- *keys: ValueT,
208
+ *keys: RedisValueT,
209
209
  acquire: bool = True,
210
- **options: ValueT | None,
210
+ **options: RedisValueT | None,
211
211
  ) -> Connection:
212
212
  # Only pubsub command/connection should be allowed here
213
213
 
@@ -17,8 +17,8 @@ from coredis.typing import (
17
17
  Iterator,
18
18
  Literal,
19
19
  Node,
20
+ RedisValueT,
20
21
  StringT,
21
- ValueT,
22
22
  )
23
23
 
24
24
  HASH_SLOTS = 16384
@@ -85,8 +85,8 @@ class NodeManager:
85
85
  self.nodemanager_follow_cluster = nodemanager_follow_cluster
86
86
  self.replicas_per_shard = 0
87
87
 
88
- def keys_to_nodes_by_slot(self, *keys: ValueT) -> dict[str, dict[int, list[ValueT]]]:
89
- mapping: dict[str, dict[int, list[ValueT]]] = {}
88
+ def keys_to_nodes_by_slot(self, *keys: RedisValueT) -> dict[str, dict[int, list[RedisValueT]]]:
89
+ mapping: dict[str, dict[int, list[RedisValueT]]] = {}
90
90
  for k in keys:
91
91
  node = self.node_from_slot(hash_slot(b(k)))
92
92
  if node:
@@ -99,6 +99,13 @@ class NodeManager:
99
99
  return node
100
100
  return None # noqa
101
101
 
102
+ def nodes_from_slots(self, *slots: int) -> dict[str, list[int]]:
103
+ mapping: dict[str, list[int]] = {}
104
+ for slot in slots:
105
+ if node := self.node_from_slot(slot):
106
+ mapping.setdefault(node.name, []).append(slot)
107
+ return mapping
108
+
102
109
  def all_nodes(self) -> Iterator[ManagedNode]:
103
110
  yield from self.nodes.values()
104
111
 
@@ -10,7 +10,7 @@ import itertools
10
10
  from abc import ABC, ABCMeta, abstractmethod
11
11
  from typing import TYPE_CHECKING, Any, cast
12
12
 
13
- from coredis._utils import b
13
+ from coredis._utils import b, nativestr
14
14
  from coredis.exceptions import ClusterResponseError, ResponseError
15
15
  from coredis.typing import (
16
16
  AnyStr,
@@ -22,12 +22,12 @@ from coredis.typing import (
22
22
  Mapping,
23
23
  ParamSpec,
24
24
  Protocol,
25
+ RedisValueT,
25
26
  ResponsePrimitive,
26
27
  ResponseType,
27
28
  Sequence,
28
29
  StringT,
29
30
  TypeVar,
30
- ValueT,
31
31
  add_runtime_checks,
32
32
  runtime_checkable,
33
33
  )
@@ -69,11 +69,13 @@ class ClusterCallbackMeta(ABCMeta):
69
69
  class ResponseCallback(ABC, Generic[RESP, RESP3, R], metaclass=ResponseCallbackMeta):
70
70
  version: Literal[2, 3]
71
71
 
72
+ def __init__(self, **options: Any) -> None:
73
+ self.options = options
74
+
72
75
  def __call__(
73
76
  self,
74
77
  response: RESP | RESP3 | ResponseError,
75
78
  version: Literal[2, 3] = 2,
76
- **options: ValueT | None,
77
79
  ) -> R:
78
80
  self.version = version
79
81
  if isinstance(response, ResponseError):
@@ -81,15 +83,15 @@ class ResponseCallback(ABC, Generic[RESP, RESP3, R], metaclass=ResponseCallbackM
81
83
  if exc_to_response:
82
84
  return exc_to_response
83
85
  if version == 3:
84
- return self.transform_3(cast(RESP3, response), **options)
85
- return self.transform(cast(RESP, response), **options)
86
+ return self.transform_3(cast(RESP3, response))
87
+ return self.transform(cast(RESP, response))
86
88
 
87
89
  @abstractmethod
88
- def transform(self, response: RESP, **options: ValueT | None) -> R:
90
+ def transform(self, response: RESP) -> R:
89
91
  pass
90
92
 
91
- def transform_3(self, response: RESP3, **options: ValueT | None) -> R:
92
- return self.transform(cast(RESP, response), **options)
93
+ def transform_3(self, response: RESP3) -> R:
94
+ return self.transform(cast(RESP, response))
93
95
 
94
96
  def handle_exception(self, exc: BaseException) -> R | None:
95
97
  return exc # type: ignore
@@ -97,13 +99,11 @@ class ResponseCallback(ABC, Generic[RESP, RESP3, R], metaclass=ResponseCallbackM
97
99
 
98
100
  @runtime_checkable
99
101
  class AsyncPreProcessingCallback(Protocol):
100
- async def pre_process(
101
- self, client: Client[Any], response: ResponseType, **options: ValueT | None
102
- ) -> None: ...
102
+ async def pre_process(self, client: Client[Any], response: ResponseType) -> None: ...
103
103
 
104
104
 
105
105
  class NoopCallback(ResponseCallback[R, R, R]):
106
- def transform(self, response: R, **kwargs: ValueT | None) -> R:
106
+ def transform(self, response: R) -> R:
107
107
  return response
108
108
 
109
109
 
@@ -112,22 +112,21 @@ class ClusterMultiNodeCallback(ABC, Generic[R], metaclass=ClusterCallbackMeta):
112
112
  self,
113
113
  responses: Mapping[str, R | ResponseError],
114
114
  version: int = 2,
115
- **kwargs: ValueT | None,
116
115
  ) -> R:
117
116
  if version == 3:
118
- return self.combine_3(responses, **kwargs)
119
- return self.combine(responses, **kwargs)
117
+ return self.combine_3(responses)
118
+ return self.combine(responses)
120
119
 
121
120
  @property
122
121
  @abstractmethod
123
122
  def response_policy(self) -> str: ...
124
123
 
125
124
  @abstractmethod
126
- def combine(self, responses: Mapping[str, R], **kwargs: ValueT | None) -> R:
125
+ def combine(self, responses: Mapping[str, R], **options: Any) -> R:
127
126
  pass
128
127
 
129
- def combine_3(self, responses: Mapping[str, R], **kwargs: ValueT | None) -> R:
130
- return self.combine(responses, **kwargs)
128
+ def combine_3(self, responses: Mapping[str, R], **options: Any) -> R:
129
+ return self.combine(responses, **options)
131
130
 
132
131
  @classmethod
133
132
  def raise_any(cls, values: Iterable[R]) -> None:
@@ -140,7 +139,7 @@ class ClusterBoolCombine(ClusterMultiNodeCallback[bool]):
140
139
  def __init__(self, any: bool = False):
141
140
  self.any = any
142
141
 
143
- def combine(self, responses: Mapping[str, bool], **kwargs: ValueT | None) -> bool:
142
+ def combine(self, responses: Mapping[str, bool], **options: Any) -> bool:
144
143
  values = tuple(responses.values())
145
144
  self.raise_any(values)
146
145
  assert (isinstance(value, bool) for value in values)
@@ -157,7 +156,7 @@ class ClusterBoolCombine(ClusterMultiNodeCallback[bool]):
157
156
 
158
157
  class ClusterAlignedBoolsCombine(ClusterMultiNodeCallback[tuple[bool, ...]]):
159
158
  def combine(
160
- self, responses: Mapping[str, tuple[bool, ...]], **kwargs: ValueT | None
159
+ self, responses: Mapping[str, tuple[bool, ...]], **options: Any
161
160
  ) -> tuple[bool, ...]:
162
161
  return tuple(all(k) for k in zip(*responses.values()))
163
162
 
@@ -170,7 +169,7 @@ class ClusterEnsureConsistent(ClusterMultiNodeCallback[R | None]):
170
169
  def __init__(self, ensure_consistent: bool = True):
171
170
  self.ensure_consistent = ensure_consistent
172
171
 
173
- def combine(self, responses: Mapping[str, R | None], **kwargs: ValueT | None) -> R | None:
172
+ def combine(self, responses: Mapping[str, R | None], **options: Any) -> R | None:
174
173
  values = tuple(responses.values())
175
174
  self.raise_any(values)
176
175
  if self.ensure_consistent and len(set(values)) != 1:
@@ -189,7 +188,7 @@ class ClusterEnsureConsistent(ClusterMultiNodeCallback[R | None]):
189
188
 
190
189
 
191
190
  class ClusterFirstNonException(ClusterMultiNodeCallback[R | None]):
192
- def combine(self, responses: Mapping[str, R | None], **kwargs: ValueT | None) -> R | None:
191
+ def combine(self, responses: Mapping[str, R | None], **options: Any) -> R | None:
193
192
  for r in responses.values():
194
193
  if not isinstance(r, BaseException):
195
194
  return r
@@ -203,7 +202,7 @@ class ClusterFirstNonException(ClusterMultiNodeCallback[R | None]):
203
202
 
204
203
 
205
204
  class ClusterMergeSets(ClusterMultiNodeCallback[set[R]]):
206
- def combine(self, responses: Mapping[str, set[R]], **kwargs: ValueT | None) -> set[R]:
205
+ def combine(self, responses: Mapping[str, set[R]], **options: Any) -> set[R]:
207
206
  self.raise_any(responses.values())
208
207
  return set(itertools.chain(*responses.values()))
209
208
 
@@ -213,11 +212,7 @@ class ClusterMergeSets(ClusterMultiNodeCallback[set[R]]):
213
212
 
214
213
 
215
214
  class ClusterSum(ClusterMultiNodeCallback[int]):
216
- def combine(
217
- self,
218
- responses: Mapping[str, int | ResponseError],
219
- **kwargs: ValueT | None,
220
- ) -> int:
215
+ def combine(self, responses: Mapping[str, int | ResponseError], **options: Any) -> int:
221
216
  self.raise_any(responses.values())
222
217
  return sum(responses.values())
223
218
 
@@ -231,7 +226,7 @@ class ClusterMergeMapping(ClusterMultiNodeCallback[dict[CK_co, CR_co]]):
231
226
  self.value_combine = value_combine
232
227
 
233
228
  def combine(
234
- self, responses: Mapping[str, dict[CK_co, CR_co]], **kwargs: ValueT | None
229
+ self, responses: Mapping[str, dict[CK_co, CR_co]], **options: Any
235
230
  ) -> dict[CK_co, CR_co]:
236
231
  self.raise_any(responses.values())
237
232
  response: dict[CK_co, CR_co] = {}
@@ -246,9 +241,7 @@ class ClusterMergeMapping(ClusterMultiNodeCallback[dict[CK_co, CR_co]]):
246
241
 
247
242
 
248
243
  class ClusterConcatenateTuples(ClusterMultiNodeCallback[tuple[R, ...]]):
249
- def combine(
250
- self, responses: Mapping[str, tuple[R, ...]], **kwargs: ValueT | None
251
- ) -> tuple[R, ...]:
244
+ def combine(self, responses: Mapping[str, tuple[R, ...]], **options: Any) -> tuple[R, ...]:
252
245
  self.raise_any(responses.values())
253
246
  return tuple(itertools.chain(*responses.values()))
254
247
 
@@ -263,12 +256,14 @@ class SimpleStringCallback(ResponseCallback[StringT | None, StringT | None, bool
263
256
  raise_on_error: type[Exception] | None = None,
264
257
  prefix_match: bool = False,
265
258
  ok_values: set[str] = {"OK"},
259
+ **options: Any,
266
260
  ):
267
261
  self.raise_on_error = raise_on_error
268
262
  self.prefix_match = prefix_match
269
263
  self.ok_values = {b(v) for v in ok_values}
264
+ super().__init__(**options)
270
265
 
271
- def transform(self, response: StringT | None, **options: ValueT | None) -> bool:
266
+ def transform(self, response: StringT | None, **options: Any) -> bool:
272
267
  if response:
273
268
  if not self.prefix_match:
274
269
  success = b(response) in self.ok_values
@@ -282,14 +277,14 @@ class SimpleStringCallback(ResponseCallback[StringT | None, StringT | None, bool
282
277
 
283
278
 
284
279
  class IntCallback(ResponseCallback[int, int, int]):
285
- def transform(self, response: ResponsePrimitive, **options: ValueT | None) -> int:
280
+ def transform(self, response: ResponsePrimitive, **options: Any) -> int:
286
281
  if isinstance(response, int):
287
282
  return response
288
283
  raise ValueError(f"Unable to map {response!r} to int")
289
284
 
290
285
 
291
286
  class AnyStrCallback(ResponseCallback[StringT, StringT, AnyStr]):
292
- def transform(self, response: StringT, **options: ValueT | None) -> AnyStr:
287
+ def transform(self, response: StringT, **options: Any) -> AnyStr:
293
288
  if isinstance(response, (bytes, str)):
294
289
  return cast(AnyStr, response)
295
290
 
@@ -297,7 +292,7 @@ class AnyStrCallback(ResponseCallback[StringT, StringT, AnyStr]):
297
292
 
298
293
 
299
294
  class FloatCallback(ResponseCallback[StringT | int | float, StringT | int | float, float]):
300
- def transform(self, response: ResponseType, **options: ValueT | None) -> float:
295
+ def transform(self, response: ResponseType, **options: Any) -> float:
301
296
  if isinstance(response, float):
302
297
  return response
303
298
  if isinstance(response, (int, bytes, str)):
@@ -307,14 +302,14 @@ class FloatCallback(ResponseCallback[StringT | int | float, StringT | int | floa
307
302
 
308
303
 
309
304
  class BoolCallback(ResponseCallback[int | bool, int | bool, bool]):
310
- def transform(self, response: ResponseType, **options: ValueT | None) -> bool:
305
+ def transform(self, response: ResponseType, **options: Any) -> bool:
311
306
  if isinstance(response, bool):
312
307
  return response
313
308
  return bool(response)
314
309
 
315
310
 
316
- class SimpleStringOrIntCallback(ResponseCallback[ValueT, ValueT, bool | int]):
317
- def transform(self, response: ValueT, **options: ValueT | None) -> bool | int:
311
+ class SimpleStringOrIntCallback(ResponseCallback[RedisValueT, RedisValueT, bool | int]):
312
+ def transform(self, response: RedisValueT, **options: Any) -> bool | int:
318
313
  if isinstance(response, (int, bool)):
319
314
  return response
320
315
  elif isinstance(response, (str, bytes)):
@@ -323,28 +318,46 @@ class SimpleStringOrIntCallback(ResponseCallback[ValueT, ValueT, bool | int]):
323
318
 
324
319
 
325
320
  class TupleCallback(ResponseCallback[list[ResponseType], list[ResponseType], tuple[CR_co, ...]]):
326
- def transform(self, response: ResponseType, **options: ValueT | None) -> tuple[CR_co, ...]:
321
+ def transform(self, response: ResponseType, **options: Any) -> tuple[CR_co, ...]:
327
322
  if isinstance(response, list):
328
323
  return cast(tuple[CR_co, ...], tuple(response))
329
324
  raise ValueError(f"Unable to map {response!r} to tuple")
330
325
 
331
326
 
327
+ class ItemOrTupleCallback(
328
+ ResponseCallback[
329
+ list[ResponseType] | ResponsePrimitive,
330
+ list[ResponseType] | ResponsePrimitive,
331
+ tuple[CR_co, ...] | CR_co,
332
+ ]
333
+ ):
334
+ def transform(
335
+ self, response: list[ResponseType] | ResponsePrimitive, **options: Any
336
+ ) -> tuple[CR_co, ...] | CR_co:
337
+ if isinstance(response, list):
338
+ return cast(tuple[CR_co, ...], tuple(response))
339
+ return cast(CR_co, response)
340
+
341
+
332
342
  class MixedTupleCallback(ResponseCallback[list[ResponseType], list[ResponseType], tuple[R, S]]):
333
- def transform(self, response: ResponseType, **options: ValueT | None) -> tuple[R, S]:
343
+ def transform(self, response: ResponseType, **options: Any) -> tuple[R, S]:
334
344
  if isinstance(response, list):
335
345
  return cast(tuple[R, S], tuple(response))
336
346
  raise ValueError(f"Unable to map {response!r} to tuple")
337
347
 
338
348
 
339
349
  class ListCallback(ResponseCallback[list[ResponseType], list[ResponseType], list[CR_co]]):
340
- def transform(self, response: list[ResponseType], **options: ValueT | None) -> list[CR_co]:
350
+ def transform(self, response: list[ResponseType], **options: Any) -> list[CR_co]:
341
351
  return cast(list[CR_co], response)
342
352
 
343
353
 
344
354
  class DateTimeCallback(ResponseCallback[int | float, int | float, datetime.datetime]):
345
- def transform(self, response: int | float, **kwargs: ValueT | None) -> datetime.datetime:
355
+ def transform(
356
+ self,
357
+ response: int | float,
358
+ ) -> datetime.datetime:
346
359
  ts = float(response) if not isinstance(response, float) else response
347
- if kwargs.get("unit") == "milliseconds":
360
+ if self.options.get("unit") == "milliseconds":
348
361
  ts = ts / 1000.0
349
362
  return datetime.datetime.fromtimestamp(ts)
350
363
 
@@ -360,14 +373,16 @@ class DictCallback(
360
373
  self,
361
374
  flat: bool = True,
362
375
  recursive: list[str] | None = None,
376
+ **options: Any,
363
377
  ):
364
378
  self.flat = flat
365
379
  self.recursive = recursive or []
380
+ super().__init__(**options)
366
381
 
367
382
  def transform(
368
383
  self,
369
384
  response: Sequence[ResponseType] | dict[ResponsePrimitive, ResponseType],
370
- **options: ValueT | None,
385
+ **options: Any,
371
386
  ) -> dict[CK_co, CR_co]:
372
387
  if isinstance(response, list):
373
388
  if self.flat:
@@ -383,7 +398,7 @@ class DictCallback(
383
398
  def transform_3(
384
399
  self,
385
400
  response: Sequence[ResponseType] | dict[ResponsePrimitive, ResponseType],
386
- **options: ValueT | None,
401
+ **options: Any,
387
402
  ) -> dict[CK_co, CR_co]:
388
403
  if isinstance(response, dict):
389
404
  return cast(dict[CK_co, CR_co], response)
@@ -397,7 +412,11 @@ class DictCallback(
397
412
  dct = []
398
413
  for i in range(0, 2 * (len(item) // 2), 2):
399
414
  key, value = item[i], item[i + 1]
400
- value = self.recursive_transformer(value) if (key in self.recursive) else value
415
+ value = (
416
+ self.recursive_transformer(value)
417
+ if (nativestr(key) in self.recursive)
418
+ else value
419
+ )
401
420
  dct.append((key, value))
402
421
  return dict(dct)
403
422
  else:
@@ -417,7 +436,7 @@ class SetCallback(
417
436
  def transform(
418
437
  self,
419
438
  response: list[ResponsePrimitive] | set[ResponsePrimitive],
420
- **options: ValueT | None,
439
+ **options: Any,
421
440
  ) -> set[CR_co]:
422
441
  if isinstance(response, list):
423
442
  return cast(set[CR_co], set(response))
@@ -426,7 +445,7 @@ class SetCallback(
426
445
  def transform_3(
427
446
  self,
428
447
  response: list[ResponsePrimitive] | set[ResponsePrimitive],
429
- **options: ValueT | None,
448
+ **options: Any,
430
449
  ) -> set[CR_co]:
431
450
  if isinstance(response, set):
432
451
  return cast(set[CR_co], response)
@@ -444,20 +463,20 @@ class OneOrManyCallback(
444
463
  def transform(
445
464
  self,
446
465
  response: CR_co | list[CR_co | None] | None,
447
- **options: ValueT | None,
466
+ **options: Any,
448
467
  ) -> CR_co | list[CR_co | None] | None:
449
468
  return response
450
469
 
451
470
 
452
471
  class BoolsCallback(ResponseCallback[ResponseType, ResponseType, tuple[bool, ...]]):
453
- def transform(self, response: ResponseType, **options: ValueT | None) -> tuple[bool, ...]:
472
+ def transform(self, response: ResponseType, **options: Any) -> tuple[bool, ...]:
454
473
  if isinstance(response, list):
455
474
  return tuple(BoolCallback()(r) for r in response)
456
475
  return ()
457
476
 
458
477
 
459
478
  class FloatsCallback(ResponseCallback[ResponseType, ResponseType, tuple[float, ...]]):
460
- def transform(self, response: ResponseType, **options: ValueT | None) -> tuple[float, ...]:
479
+ def transform(self, response: ResponseType, **options: Any) -> tuple[float, ...]:
461
480
  if isinstance(response, list):
462
481
  return tuple(FloatCallback()(r) for r in response)
463
482
  return ()
@@ -473,7 +492,7 @@ class OptionalFloatCallback(
473
492
  def transform(
474
493
  self,
475
494
  response: StringT | int | float | None,
476
- **options: ValueT | None,
495
+ **options: Any,
477
496
  ) -> float | None:
478
497
  if response is None:
479
498
  return None
@@ -481,7 +500,7 @@ class OptionalFloatCallback(
481
500
 
482
501
 
483
502
  class OptionalIntCallback(ResponseCallback[int | None, int | None, int | None]):
484
- def transform(self, response: int | None, **options: ValueT | None) -> int | None:
503
+ def transform(self, response: int | None, **options: Any) -> int | None:
485
504
  if response is None:
486
505
  return None
487
506
  if isinstance(response, int):
@@ -496,7 +515,7 @@ class OptionalAnyStrCallback(
496
515
  AnyStr | None,
497
516
  ]
498
517
  ):
499
- def transform(self, response: StringT | None, **options: ValueT | None) -> AnyStr | None:
518
+ def transform(self, response: StringT | None, **options: Any) -> AnyStr | None:
500
519
  if response is None:
501
520
  return None
502
521
  if isinstance(response, (bytes, str)):
@@ -507,12 +526,12 @@ class OptionalAnyStrCallback(
507
526
  class OptionalListCallback(
508
527
  ResponseCallback[list[ResponseType], list[ResponseType], list[CR_co] | None]
509
528
  ):
510
- def transform(self, response: ResponseType, **options: ValueT | None) -> list[CR_co] | None:
529
+ def transform(self, response: ResponseType, **options: Any) -> list[CR_co] | None:
511
530
  return cast(list[CR_co], response)
512
531
 
513
532
 
514
533
  class FirstValueCallback(ResponseCallback[list[CR_co], list[CR_co], CR_co]):
515
- def transform(self, response: list[CR_co], **options: ValueT | None) -> CR_co:
534
+ def transform(self, response: list[CR_co], **options: Any) -> CR_co:
516
535
  if response:
517
536
  return response[0]
518
537
  else:
@@ -5,7 +5,6 @@ from coredis.typing import (
5
5
  AnyStr,
6
6
  ResponsePrimitive,
7
7
  Sequence,
8
- ValueT,
9
8
  )
10
9
 
11
10
 
@@ -19,7 +18,6 @@ class ACLLogCallback(
19
18
  def transform(
20
19
  self,
21
20
  response: list[Sequence[ResponsePrimitive] | None],
22
- **options: ValueT | None,
23
21
  ) -> tuple[dict[AnyStr, ResponsePrimitive] | None, ...]:
24
22
  return tuple(
25
23
  DictCallback[AnyStr, ResponsePrimitive]()(r, version=self.version)
@@ -30,6 +28,5 @@ class ACLLogCallback(
30
28
  def transform_3(
31
29
  self,
32
30
  response: list[dict[AnyStr, ResponsePrimitive] | None],
33
- **options: ValueT | None,
34
31
  ) -> tuple[dict[AnyStr, ResponsePrimitive] | None, ...]:
35
32
  return tuple(response)
@@ -7,9 +7,9 @@ from coredis.response.types import ClusterNode, ClusterNodeDetail
7
7
  from coredis.typing import (
8
8
  AnyStr,
9
9
  Mapping,
10
+ RedisValueT,
10
11
  ResponsePrimitive,
11
12
  ResponseType,
12
- ValueT,
13
13
  )
14
14
 
15
15
 
@@ -17,7 +17,8 @@ class ClusterLinksCallback(
17
17
  ResponseCallback[ResponseType, ResponseType, list[dict[AnyStr, ResponsePrimitive]]]
18
18
  ):
19
19
  def transform(
20
- self, response: ResponseType, **options: ValueT | None
20
+ self,
21
+ response: ResponseType,
21
22
  ) -> list[dict[AnyStr, ResponsePrimitive]]:
22
23
  transformed: list[dict[AnyStr, ResponsePrimitive]] = []
23
24
 
@@ -26,13 +27,17 @@ class ClusterLinksCallback(
26
27
  return transformed
27
28
 
28
29
  def transform_3(
29
- self, response: ResponseType, **options: ValueT | None
30
+ self,
31
+ response: ResponseType,
30
32
  ) -> list[dict[AnyStr, ResponsePrimitive]]:
31
33
  return response
32
34
 
33
35
 
34
36
  class ClusterInfoCallback(ResponseCallback[ResponseType, ResponseType, dict[str, str]]):
35
- def transform(self, response: ResponseType, **options: ValueT | None) -> dict[str, str]:
37
+ def transform(
38
+ self,
39
+ response: ResponseType,
40
+ ) -> dict[str, str]:
36
41
  response_str = nativestr(response)
37
42
  return dict([line.split(":") for line in response_str.splitlines() if line])
38
43
 
@@ -41,7 +46,8 @@ class ClusterSlotsCallback(
41
46
  ResponseCallback[ResponseType, ResponseType, dict[tuple[int, int], tuple[ClusterNode, ...]]]
42
47
  ):
43
48
  def transform(
44
- self, response: ResponseType, **options: ValueT | None
49
+ self,
50
+ response: ResponseType,
45
51
  ) -> dict[tuple[int, int], tuple[ClusterNode, ...]]:
46
52
  res: dict[tuple[int, int], tuple[ClusterNode, ...]] = {}
47
53
 
@@ -64,7 +70,8 @@ class ClusterSlotsCallback(
64
70
 
65
71
  class ClusterNodesCallback(ResponseCallback[ResponseType, ResponseType, list[ClusterNodeDetail]]):
66
72
  def transform(
67
- self, response: ResponseType, **options: ValueT | None
73
+ self,
74
+ response: ResponseType,
68
75
  ) -> list[ClusterNodeDetail]:
69
76
  resp: list[str] | str
70
77
 
@@ -72,11 +79,11 @@ class ClusterNodesCallback(ResponseCallback[ResponseType, ResponseType, list[Clu
72
79
  resp = [nativestr(row) for row in response]
73
80
  else:
74
81
  resp = nativestr(response)
75
- current_host = nativestr(options.get("current_host", ""))
82
+ current_host = nativestr(self.options.get("current_host", ""))
76
83
 
77
- def parse_slots(s: str) -> tuple[list[int], list[dict[str, ValueT]]]:
84
+ def parse_slots(s: str) -> tuple[list[int], list[dict[str, RedisValueT]]]:
78
85
  slots: list[int] = []
79
- migrations: list[dict[str, ValueT]] = []
86
+ migrations: list[dict[str, RedisValueT]] = []
80
87
 
81
88
  for r in s.split(" "):
82
89
  if "->-" in r:
@@ -150,17 +157,18 @@ class ClusterShardsCallback(
150
157
  ResponseCallback[
151
158
  ResponseType,
152
159
  ResponseType,
153
- list[dict[AnyStr, list[ValueT] | Mapping[AnyStr, ValueT]]],
160
+ list[dict[AnyStr, list[RedisValueT] | Mapping[AnyStr, RedisValueT]]],
154
161
  ]
155
162
  ):
156
163
  def transform(
157
- self, response: ResponseType, **options: ValueT | None
158
- ) -> list[dict[AnyStr, list[ValueT] | Mapping[AnyStr, ValueT]]]:
159
- shard_mapping: list[dict[AnyStr, list[ValueT] | Mapping[AnyStr, ValueT]]] = []
164
+ self,
165
+ response: ResponseType,
166
+ ) -> list[dict[AnyStr, list[RedisValueT] | Mapping[AnyStr, RedisValueT]]]:
167
+ shard_mapping: list[dict[AnyStr, list[RedisValueT] | Mapping[AnyStr, RedisValueT]]] = []
160
168
 
161
169
  for shard in response:
162
170
  transformed = EncodingInsensitiveDict(flat_pairs_to_dict(shard))
163
- node_mapping: list[dict[AnyStr, ValueT]] = []
171
+ node_mapping: list[dict[AnyStr, RedisValueT]] = []
164
172
  for node in transformed["nodes"]:
165
173
  node_mapping.append(flat_pairs_to_dict(node))
166
174
 
@@ -169,6 +177,7 @@ class ClusterShardsCallback(
169
177
  return shard_mapping
170
178
 
171
179
  def transform_3(
172
- self, response: ResponseType, **options: ValueT | None
173
- ) -> list[dict[AnyStr, list[ValueT] | Mapping[AnyStr, ValueT]]]:
180
+ self,
181
+ response: ResponseType,
182
+ ) -> list[dict[AnyStr, list[RedisValueT] | Mapping[AnyStr, RedisValueT]]]:
174
183
  return response