coredis 5.5.0__cp313-cp313-macosx_11_0_arm64.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 (100) hide show
  1. 22fe76227e35f92ab5c3__mypyc.cpython-313-darwin.so +0 -0
  2. coredis/__init__.py +42 -0
  3. coredis/_enum.py +42 -0
  4. coredis/_json.py +11 -0
  5. coredis/_packer.cpython-313-darwin.so +0 -0
  6. coredis/_packer.py +71 -0
  7. coredis/_protocols.py +50 -0
  8. coredis/_py_311_typing.py +20 -0
  9. coredis/_py_312_typing.py +17 -0
  10. coredis/_sidecar.py +114 -0
  11. coredis/_utils.cpython-313-darwin.so +0 -0
  12. coredis/_utils.py +440 -0
  13. coredis/_version.py +34 -0
  14. coredis/_version.pyi +1 -0
  15. coredis/cache.py +801 -0
  16. coredis/client/__init__.py +6 -0
  17. coredis/client/basic.py +1240 -0
  18. coredis/client/cluster.py +1265 -0
  19. coredis/commands/__init__.py +64 -0
  20. coredis/commands/_key_spec.py +517 -0
  21. coredis/commands/_utils.py +108 -0
  22. coredis/commands/_validators.py +159 -0
  23. coredis/commands/_wrappers.py +175 -0
  24. coredis/commands/bitfield.py +110 -0
  25. coredis/commands/constants.py +662 -0
  26. coredis/commands/core.py +8484 -0
  27. coredis/commands/function.py +408 -0
  28. coredis/commands/monitor.py +168 -0
  29. coredis/commands/pubsub.py +905 -0
  30. coredis/commands/request.py +108 -0
  31. coredis/commands/script.py +296 -0
  32. coredis/commands/sentinel.py +246 -0
  33. coredis/config.py +50 -0
  34. coredis/connection.py +906 -0
  35. coredis/constants.cpython-313-darwin.so +0 -0
  36. coredis/constants.py +37 -0
  37. coredis/credentials.py +45 -0
  38. coredis/exceptions.py +360 -0
  39. coredis/experimental/__init__.py +1 -0
  40. coredis/globals.py +23 -0
  41. coredis/modules/__init__.py +121 -0
  42. coredis/modules/autocomplete.py +138 -0
  43. coredis/modules/base.py +262 -0
  44. coredis/modules/filters.py +1319 -0
  45. coredis/modules/graph.py +362 -0
  46. coredis/modules/json.py +691 -0
  47. coredis/modules/response/__init__.py +0 -0
  48. coredis/modules/response/_callbacks/__init__.py +0 -0
  49. coredis/modules/response/_callbacks/autocomplete.py +42 -0
  50. coredis/modules/response/_callbacks/graph.py +237 -0
  51. coredis/modules/response/_callbacks/json.py +21 -0
  52. coredis/modules/response/_callbacks/search.py +221 -0
  53. coredis/modules/response/_callbacks/timeseries.py +158 -0
  54. coredis/modules/response/types.py +179 -0
  55. coredis/modules/search.py +1089 -0
  56. coredis/modules/timeseries.py +1139 -0
  57. coredis/parser.cpython-313-darwin.so +0 -0
  58. coredis/parser.py +344 -0
  59. coredis/pipeline.py +1225 -0
  60. coredis/pool/__init__.py +11 -0
  61. coredis/pool/basic.py +453 -0
  62. coredis/pool/cluster.py +517 -0
  63. coredis/pool/nodemanager.py +340 -0
  64. coredis/py.typed +0 -0
  65. coredis/recipes/__init__.py +0 -0
  66. coredis/recipes/credentials/__init__.py +5 -0
  67. coredis/recipes/credentials/iam_provider.py +63 -0
  68. coredis/recipes/locks/__init__.py +5 -0
  69. coredis/recipes/locks/extend.lua +17 -0
  70. coredis/recipes/locks/lua_lock.py +281 -0
  71. coredis/recipes/locks/release.lua +10 -0
  72. coredis/response/__init__.py +5 -0
  73. coredis/response/_callbacks/__init__.py +538 -0
  74. coredis/response/_callbacks/acl.py +32 -0
  75. coredis/response/_callbacks/cluster.py +183 -0
  76. coredis/response/_callbacks/command.py +86 -0
  77. coredis/response/_callbacks/connection.py +31 -0
  78. coredis/response/_callbacks/geo.py +58 -0
  79. coredis/response/_callbacks/hash.py +85 -0
  80. coredis/response/_callbacks/keys.py +59 -0
  81. coredis/response/_callbacks/module.py +33 -0
  82. coredis/response/_callbacks/script.py +85 -0
  83. coredis/response/_callbacks/sentinel.py +179 -0
  84. coredis/response/_callbacks/server.py +241 -0
  85. coredis/response/_callbacks/sets.py +44 -0
  86. coredis/response/_callbacks/sorted_set.py +204 -0
  87. coredis/response/_callbacks/streams.py +185 -0
  88. coredis/response/_callbacks/strings.py +70 -0
  89. coredis/response/_callbacks/vector_sets.py +159 -0
  90. coredis/response/_utils.py +33 -0
  91. coredis/response/types.py +416 -0
  92. coredis/retry.py +233 -0
  93. coredis/sentinel.py +477 -0
  94. coredis/stream.py +369 -0
  95. coredis/tokens.py +2286 -0
  96. coredis/typing.py +593 -0
  97. coredis-5.5.0.dist-info/METADATA +211 -0
  98. coredis-5.5.0.dist-info/RECORD +100 -0
  99. coredis-5.5.0.dist-info/WHEEL +6 -0
  100. coredis-5.5.0.dist-info/licenses/LICENSE +23 -0
coredis/typing.py ADDED
@@ -0,0 +1,593 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import inspect
5
+ import sys
6
+ from collections import OrderedDict
7
+ from collections.abc import (
8
+ AsyncGenerator,
9
+ AsyncIterator,
10
+ Awaitable,
11
+ Callable,
12
+ Coroutine,
13
+ Generator,
14
+ Hashable,
15
+ Iterable,
16
+ Iterator,
17
+ Mapping,
18
+ MutableMapping,
19
+ MutableSequence,
20
+ MutableSet,
21
+ Sequence,
22
+ Set,
23
+ ValuesView,
24
+ )
25
+ from types import GenericAlias, ModuleType, UnionType
26
+ from typing import (
27
+ TYPE_CHECKING,
28
+ Any,
29
+ AnyStr,
30
+ ClassVar,
31
+ Final,
32
+ Generic,
33
+ Literal,
34
+ NamedTuple,
35
+ ParamSpec,
36
+ Protocol,
37
+ TypedDict,
38
+ TypeGuard,
39
+ TypeVar,
40
+ cast,
41
+ get_origin,
42
+ get_type_hints,
43
+ runtime_checkable,
44
+ )
45
+
46
+ from beartype import __version__ as beartype_version
47
+ from beartype import beartype
48
+ from packaging import version
49
+
50
+ if TYPE_CHECKING:
51
+ infer_hint: Callable[..., Any]
52
+ is_bearable: Callable[[Any, Any], bool]
53
+ is_subhint: Callable[[Any, Any], bool]
54
+ else:
55
+ if version.parse(beartype_version) < version.parse("0.22"):
56
+ from beartype.door import infer_hint
57
+ else:
58
+ from beartype.bite import infer_hint
59
+
60
+ from beartype.door import is_bearable, is_subhint
61
+ from typing_extensions import (
62
+ NotRequired,
63
+ Self,
64
+ Unpack,
65
+ )
66
+
67
+ from coredis.config import Config
68
+
69
+ RUNTIME_TYPECHECKS = Config.runtime_checks and not TYPE_CHECKING
70
+
71
+ P = ParamSpec("P")
72
+ T_co = TypeVar("T_co", covariant=True)
73
+ R = TypeVar("R")
74
+
75
+
76
+ def safe_beartype(func: Callable[P, R]) -> Callable[P, R]:
77
+ return beartype(func)
78
+
79
+
80
+ def add_runtime_checks(func: Callable[P, R]) -> Callable[P, R]:
81
+ if RUNTIME_TYPECHECKS and not TYPE_CHECKING:
82
+ return beartype(func)
83
+
84
+ return func
85
+
86
+
87
+ class RedisError(Exception):
88
+ """
89
+ Base exception from which all other exceptions in coredis
90
+ derive from.
91
+ """
92
+
93
+
94
+ class Node(TypedDict):
95
+ """
96
+ Definition of a cluster node
97
+ """
98
+
99
+ host: str
100
+ port: int
101
+
102
+
103
+ class RedisCommandP(Protocol):
104
+ """
105
+ Protocol of a redis command with all associated arguments
106
+ converted into the shape expected by the redis server.
107
+ Used by :meth:`~coredis.Redis.execute_command`
108
+ """
109
+
110
+ #: The name of the redis command
111
+ name: bytes
112
+ #: All arguments to be passed to the command
113
+ arguments: tuple[RedisValueT, ...]
114
+
115
+
116
+ @dataclasses.dataclass
117
+ class RedisCommand:
118
+ """
119
+ Convenience data class that conforms to :class:`~coredis.typing.RedisCommandP`
120
+ """
121
+
122
+ #: The name of the redis command
123
+ name: bytes
124
+ #: All arguments to be passed to the command
125
+ arguments: tuple[RedisValueT, ...]
126
+
127
+
128
+ class ExecutionParameters(TypedDict):
129
+ """
130
+ Extra parameters that can be passed to :meth:`~coredis.Redis.execute_command`
131
+ """
132
+
133
+ #: Whether to decode the response
134
+ #: (ignoring the value of :paramref:`~coredis.Redis.decode_responses`)
135
+ decode: NotRequired[bool]
136
+ slot_arguments_range: NotRequired[tuple[int, int]]
137
+
138
+
139
+ #: Represents the acceptable types of a redis key
140
+ KeyT = str | bytes
141
+
142
+
143
+ class Serializable(Generic[R]):
144
+ """
145
+ Wrapper to be used to pass arbitrary types to redis commands
146
+ to be eventually serialized by :class:`coredis.typing.TypeAdapter.serialize`
147
+
148
+ Wrapping a value in :class:`Serializable` will pass type checking
149
+ wherever a method expects a :class:`coredis.typing.ValueT` - however
150
+ it will still fail if there is no serializer registered through the instance
151
+ of :class:`coredis.typing.TypeAdapter` that is associated with the client.
152
+
153
+ For example::
154
+
155
+ class MyThing:
156
+ ...
157
+
158
+ client = coredis.Redis()
159
+
160
+ # This will pass type checking but will fail with an :exc:`LookupError`
161
+ # at runtime
162
+ await client.set("fubar", coredis.typing.Serializable(MyThing()))
163
+
164
+ # however, if a serializer is registered, the above would succeed
165
+ @client.type_adapter.serializer
166
+ def _(value: MyThing) -> str:
167
+ ... # some way to convert it to a string
168
+ """
169
+
170
+ def __init__(self, value: R) -> None:
171
+ self.value = value
172
+
173
+
174
+ AdaptableType = type | UnionType | GenericAlias
175
+
176
+
177
+ class TypeAdapter:
178
+ """
179
+ Used by the coredis clients :class:`~coredis.Redis` and :class:`~coredis.RedisCluster`
180
+ through :paramref:`~coredis.Redis.type_adapter` for adapting complex types that require
181
+ custom serialization/deserialization with redis commands.
182
+
183
+ For example to use Decimal types with some common redis operations::
184
+
185
+ from decimal import Decimal
186
+ from typing import Any, Mapping, Iterable
187
+ from coredis import Redis
188
+ from coredis.typing import TypeAdapter, Serializable
189
+
190
+ adapter = TypeAdapter()
191
+
192
+ @adapter.serializer
193
+ def decimal_to_str(value: Decimal) -> str:
194
+ return str(value)
195
+
196
+ @adapter.deserializer
197
+ def value_to_decimal(value: str|bytes) -> Decimal:
198
+ return Decimal(value.decode("utf-8") if isinstance(value, bytes) else value)
199
+
200
+ @adapter.deserializer
201
+ def list_to_decimal_list(items: Iterable[str|bytes]) -> list[Decimal]:
202
+ return [value_to_decimal(value) for value in items]
203
+
204
+ @adapter.deserializer
205
+ def mapping_to_decimal_mapping(mapping: Mapping[str|bytes, str|bytes]) -> dict[str|bytes, Decimal]:
206
+ return {key: value_to_decimal(value) for key, value in mapping.items()}
207
+
208
+ client = coredis.Redis(type_adapter=adapter, decode_responses=True)
209
+ await client.set("key", Serializable(Decimal(1.5)))
210
+ await client.lpush("list", [Serializable(Decimal(1.5))])
211
+ await client.hset("dict", {"first": Serializable(Decimal(1.5))})
212
+ assert Decimal(1.5) == await client.get("key").transform(Decimal)
213
+ assert [Decimal(1.5)] == await client.lrange("list", 0, 0).transform(list[Decimal])
214
+ assert {"first": Decimal(1.5)} == await client.hgetall("dict").transform(dict[str, Decimal])
215
+ """
216
+
217
+ def __init__(
218
+ self,
219
+ ) -> None:
220
+ self.__serializers: dict[
221
+ AdaptableType,
222
+ tuple[Callable[[Any], RedisValueT], int],
223
+ ] = {}
224
+ self.__deserializers: dict[
225
+ AdaptableType,
226
+ dict[AdaptableType, tuple[Callable[..., Any], int]],
227
+ ] = {}
228
+ self.__deserializer_cache: dict[
229
+ tuple[AdaptableType, AdaptableType | GenericAlias],
230
+ Callable[..., Any],
231
+ ] = {}
232
+ self.__serializer_cache: dict[AdaptableType, Callable[[Any], RedisValueT]] = {}
233
+
234
+ @classmethod
235
+ def format_type(cls, type_like: AdaptableType) -> str:
236
+ if get_origin(type_like):
237
+ return str(type_like)
238
+ else:
239
+ return getattr(type_like, "__name__", str(type_like))
240
+
241
+ def register(
242
+ self,
243
+ type: type[R] | UnionType,
244
+ serializer: Callable[[R], RedisValueT],
245
+ deserializer: Callable[[Any], R],
246
+ deserializable_type: type = object,
247
+ ) -> None:
248
+ """
249
+ Register both a serializer and a deserializer for :paramref:`type`
250
+
251
+ :param type: The type that should be serialized/deserialized
252
+ :param serializer: a function that receives an instance of :paramref:`type`
253
+ and returns a value of type :data:`coredis.typing.RedisValueT`
254
+ :param deserializer: a function that accepts the return types from
255
+ the redis commands that are expected to be used when deserializing
256
+ to :paramref:`type`.
257
+ :param deserializable_type: the types of values :paramref:`deserializer` should
258
+ be considered for
259
+ """
260
+ self.register_serializer(type, serializer)
261
+ self.register_deserializer(type, deserializer, deserializable_type)
262
+
263
+ def register_serializer(
264
+ self,
265
+ serializable_type: type[R] | UnionType,
266
+ serializer: Callable[[R], RedisValueT],
267
+ ) -> None:
268
+ """
269
+ Register a serializer for :paramref:`type`
270
+
271
+ :param type: The type that will be serialized
272
+ :param serializer: a function that receives an instance of :paramref:`type`
273
+ and returns a value of type :data:`coredis.typing.RedisValueT`
274
+ """
275
+ self.__serializers.setdefault(serializable_type, (serializer, 0))
276
+ self.__serializer_cache.clear()
277
+
278
+ def register_deserializer(
279
+ self,
280
+ deserialized_type: type[R] | UnionType,
281
+ deserializer: Callable[[Any], R],
282
+ deserializable_type: AdaptableType = object,
283
+ ) -> None:
284
+ """
285
+ Register a deserializer for :paramref:`type` and automatically register
286
+ deserializers for common collection types that use this type.
287
+
288
+ :param type: The type that should be deserialized
289
+ :param deserializer: a function that accepts the return types from
290
+ the redis commands that are expected to be used when deserializing
291
+ to :paramref:`type`.
292
+ :param deserializable_type: the types of values :paramref:`deserializer` should
293
+ be considered for
294
+ """
295
+
296
+ def register_collection_deserializer(
297
+ collection_type: AdaptableType,
298
+ deserializable_type: AdaptableType,
299
+ deserializer: Callable[[Any], Any],
300
+ ) -> None:
301
+ self.__deserializers.setdefault(collection_type, {}).setdefault(
302
+ deserializable_type,
303
+ (deserializer, -1),
304
+ )
305
+
306
+ # Register the base deserializer
307
+ self.__deserializers.setdefault(deserialized_type, {})[deserializable_type or object] = (
308
+ deserializer,
309
+ 0,
310
+ )
311
+
312
+ # Register collection deserializers
313
+ register_collection_deserializer(
314
+ GenericAlias(list, (deserialized_type,)),
315
+ GenericAlias(Iterable, deserializable_type),
316
+ lambda v: [deserializer(item) for item in v],
317
+ )
318
+ register_collection_deserializer(
319
+ GenericAlias(set, (deserialized_type,)),
320
+ GenericAlias(Iterable, deserializable_type),
321
+ lambda v: {deserializer(item) for item in v},
322
+ )
323
+ register_collection_deserializer(
324
+ GenericAlias(tuple, (deserialized_type, ...)),
325
+ GenericAlias(Iterable, deserializable_type),
326
+ lambda v: tuple([deserializer(item) for item in v]),
327
+ )
328
+
329
+ # Register dictionary deserializers for existing types
330
+ for t in list(self.__deserializers):
331
+ if t != deserialized_type:
332
+ for rt in list(self.__deserializers[t]):
333
+ _deserializer, priority = self.__deserializers[t][rt]
334
+ if priority >= 0:
335
+ register_collection_deserializer(
336
+ GenericAlias(dict, (t, deserialized_type)),
337
+ GenericAlias(Mapping, (rt, deserializable_type)),
338
+ lambda m, key_deserializer=_deserializer: { # type: ignore
339
+ key_deserializer(k): deserializer(v) for k, v in m.items()
340
+ },
341
+ )
342
+ register_collection_deserializer(
343
+ GenericAlias(dict, (deserialized_type, t)),
344
+ GenericAlias(Mapping, (deserializable_type, rt)),
345
+ lambda m, value_deserializer=_deserializer: { # type: ignore
346
+ deserializer(k): value_deserializer(v) for k, v in m.items()
347
+ },
348
+ )
349
+
350
+ # Register dictionary deserializers for primitive types
351
+ for t in {bytes, str}:
352
+ register_collection_deserializer(
353
+ GenericAlias(dict, (t, deserialized_type)),
354
+ GenericAlias(Mapping, (t, deserializable_type)),
355
+ lambda v: {k: deserializer(v) for k, v in v.items()},
356
+ )
357
+ register_collection_deserializer(
358
+ GenericAlias(dict, (deserialized_type, t)),
359
+ GenericAlias(Mapping, (deserializable_type, t)),
360
+ lambda v: {deserializer(k): v for k, v in v.items()},
361
+ )
362
+
363
+ self.__deserializer_cache.clear()
364
+
365
+ def serializer(self, func: Callable[[R], RedisValueT]) -> Callable[[R], RedisValueT]:
366
+ """
367
+ Decorator for registering a serializer
368
+
369
+ :param func: A serialization function that accepts an instance of
370
+ type `R` and returns one of the types defined by :data:`coredis.typing.RedisValueT`
371
+ The acceptable serializable types are inferred
372
+ from the annotations in the function signature.
373
+
374
+ :raises ValueError: when the appropriate serializable type cannot be
375
+ inferred.
376
+ """
377
+ if (parameters := list(inspect.signature(func).parameters.keys())) and (
378
+ input_hint := get_type_hints(func).get(parameters[0])
379
+ ):
380
+ self.register_serializer(input_hint, func)
381
+ return func
382
+ else:
383
+ raise ValueError(
384
+ "Unable to infer custom input type from decorated function. Check type annotations."
385
+ )
386
+
387
+ def deserializer(self, func: Callable[[Any], R]) -> Callable[[Any], R]:
388
+ """
389
+ Decorator for registering a deserializer
390
+
391
+ :param func: A deserialization function that returns an instance of
392
+ type `R` that can be used with :meth:`deserialize`. The acceptable
393
+ deserializable types and the expected deserialized type are inferred
394
+ from the annotations in the function signature.
395
+
396
+ :raises ValueError: when the appropriate input/output types cannot be
397
+ inferred.
398
+ """
399
+ if (
400
+ (parameters := list(inspect.signature(func).parameters.keys()))
401
+ and (input_hint := get_type_hints(func).get(parameters[0]))
402
+ ) and (response_type := get_type_hints(func).get("return")):
403
+ self.register_deserializer(response_type, func, input_hint)
404
+ return func
405
+ else:
406
+ raise ValueError(
407
+ "Unable to infer response type from decorated function. Check annotations."
408
+ )
409
+
410
+ def serialize(self, value: Serializable[R]) -> RedisValueT:
411
+ """
412
+ Serializes :paramref:`value` into one of the types represented by
413
+ :data:`~coredis.typing.RedisValueT` using a serializer registered
414
+ via :meth:`register_serializer` or decorated by :meth:`serializer`.
415
+
416
+ :param: a value wrapped in :class:`coredis.typing.Serializable`
417
+ """
418
+ value_type = cast(AdaptableType, infer_hint(value.value))
419
+ if not (transform_function := self.__serializer_cache.get(value_type, None)):
420
+ candidate: tuple[AdaptableType, Callable[[R], RedisValueT] | None] = (object, None)
421
+
422
+ for t in self.__serializers:
423
+ if is_bearable(value.value, t):
424
+ if not candidate[1] or is_subhint(t, candidate[0]):
425
+ candidate = (t, self.__serializers[t][0])
426
+ if candidate[1]:
427
+ transform_function = candidate[1]
428
+ self.__serializer_cache[value_type] = transform_function
429
+ if not transform_function:
430
+ raise LookupError(
431
+ f"No registered serializer to serialize {self.format_type(value_type)}"
432
+ )
433
+ return transform_function(value.value)
434
+
435
+ def deserialize(self, value: Any, return_type: type[R]) -> R:
436
+ """
437
+ Deserializes :paramref:`value` into an instance of :paramref:`return_type`
438
+ using a deserializer registered via :meth:`register_deserializer` or decorated
439
+ by :meth:`deserializer`.
440
+
441
+ :param value: the value to be deserialized (typically something returned by one of
442
+ the redis commands)
443
+ :param return_type: The type to deserialize to
444
+ """
445
+ value_type = cast(AdaptableType, infer_hint(value))
446
+ if not (deserializer := self.__deserializer_cache.get((value_type, return_type), None)):
447
+ if exact_match := self.__deserializers.get(return_type, {}).get(value_type, None):
448
+ deserializer = exact_match[0]
449
+ else:
450
+ candidate: tuple[AdaptableType, AdaptableType, Callable[[Any], R] | None, int] = (
451
+ object,
452
+ object,
453
+ None,
454
+ -100,
455
+ )
456
+ for registered_type, transforms in self.__deserializers.items():
457
+ if is_subhint(return_type, registered_type):
458
+ for expected_value_type in transforms:
459
+ if (
460
+ is_bearable(value, expected_value_type)
461
+ and is_subhint(registered_type, candidate[0])
462
+ and is_subhint(expected_value_type, candidate[1])
463
+ and transforms[expected_value_type][1] >= candidate[3]
464
+ ):
465
+ candidate = (
466
+ registered_type,
467
+ expected_value_type,
468
+ transforms[expected_value_type][0],
469
+ transforms[expected_value_type][1],
470
+ )
471
+ deserializer = candidate[2]
472
+ if deserializer:
473
+ deserialized = deserializer(value)
474
+ if RUNTIME_TYPECHECKS and not is_subhint(
475
+ transformed_type := cast(type, infer_hint(deserialized)), return_type
476
+ ):
477
+ raise TypeError(
478
+ f"Invalid deserializer. Requested {self.format_type(return_type)} but deserializer returned {self.format_type(transformed_type)}"
479
+ )
480
+ self.__deserializer_cache[(value_type, return_type)] = deserializer
481
+ return deserialized
482
+ elif is_subhint(value_type, return_type):
483
+ return cast(R, value)
484
+ else:
485
+ raise LookupError(
486
+ f"No registered deserializer to convert {self.format_type(value_type)} to {self.format_type(return_type)}"
487
+ )
488
+
489
+
490
+ #: Represents the different python primitives that are accepted
491
+ #: as input parameters for commands that can be used with loosely
492
+ #: defined types. These will eventually be serialized before being
493
+ #: sent to redis.
494
+ #:
495
+ #: Additionally any object wrapped in a :class:`Serializable` will be
496
+ #: accepted and will be serialized using an appropriate type adapter
497
+ #: registered with the client. See :ref:`api/typing:custom types` for more details.
498
+ ValueT = str | bytes | int | float | Serializable[Any]
499
+
500
+ #: The canonical type used for input parameters that represent "strings"
501
+ #: that are transmitted to redis.
502
+ StringT = str | bytes
503
+
504
+ CommandArgList = list[ValueT]
505
+
506
+ #: Primitive types that we can expect to be sent to redis with
507
+ #: simple serialization. The internals of coredis
508
+ #: pass around arguments to redis commands as this type.
509
+ RedisValueT = str | bytes | int | float
510
+
511
+ #: Restricted union of container types accepted as arguments to apis
512
+ #: that accept a variable number values for an argument (such as keys, values).
513
+ #: This is used instead of :class:`typing.Iterable` as the latter allows
514
+ #: :class:`str` to be passed in as valid values for :class:`Iterable[str]` or :class:`bytes`
515
+ #: to be passed in as a valid value for :class:`Iterable[bytes]` which is never the actual
516
+ #: expectation in the scope of coredis.
517
+ #: For example::
518
+ #:
519
+ #: def length(values: Parameters[ValueT]) -> int:
520
+ #: return len(list(values))
521
+ #:
522
+ #: length(["1", 2, 3, 4]) # valid
523
+ #: length({"1", 2, 3, 4}) # valid
524
+ #: length(("1", 2, 3, 4)) # valid
525
+ #: length({"1": 2}.keys()) # valid
526
+ #: length({"1": 2}.values()) # valid
527
+ #: length(map(str, range(10))) # valid
528
+ #: length({"1": 2}) # invalid
529
+ #: length("123") # invalid
530
+ #: length(b"123") # invalid
531
+ Parameters = list[T_co] | Set[T_co] | tuple[T_co, ...] | ValuesView[T_co] | Iterator[T_co]
532
+
533
+ #: Primitives returned by redis
534
+ ResponsePrimitive = StringT | int | float | bool | None
535
+
536
+ if sys.version_info >= (3, 12):
537
+ from ._py_312_typing import JsonType, ResponseType
538
+ else:
539
+ from ._py_311_typing import JsonType, ResponseType
540
+
541
+
542
+ __all__ = [
543
+ "Serializable",
544
+ "AnyStr",
545
+ "AsyncIterator",
546
+ "AsyncGenerator",
547
+ "Awaitable",
548
+ "Callable",
549
+ "ClassVar",
550
+ "CommandArgList",
551
+ "Coroutine",
552
+ "Final",
553
+ "Generic",
554
+ "Generator",
555
+ "Hashable",
556
+ "Iterable",
557
+ "Iterator",
558
+ "JsonType",
559
+ "KeyT",
560
+ "Literal",
561
+ "Mapping",
562
+ "ModuleType",
563
+ "MutableMapping",
564
+ "MutableSet",
565
+ "MutableSequence",
566
+ "NamedTuple",
567
+ "Node",
568
+ "NotRequired",
569
+ "OrderedDict",
570
+ "Parameters",
571
+ "ParamSpec",
572
+ "Protocol",
573
+ "RedisCommand",
574
+ "RedisCommandP",
575
+ "ExecutionParameters",
576
+ "ResponsePrimitive",
577
+ "ResponseType",
578
+ "runtime_checkable",
579
+ "Self",
580
+ "Sequence",
581
+ "StringT",
582
+ "TypeGuard",
583
+ "TypedDict",
584
+ "TypeVar",
585
+ "Unpack",
586
+ "ValueT",
587
+ "RedisValueT",
588
+ "ValuesView",
589
+ "TYPE_CHECKING",
590
+ "TypeAdapter",
591
+ "ValueT",
592
+ "RUNTIME_TYPECHECKS",
593
+ ]