dycw-utilities 0.133.7__py3-none-any.whl → 0.134.1__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.
- {dycw_utilities-0.133.7.dist-info → dycw_utilities-0.134.1.dist-info}/METADATA +1 -1
- {dycw_utilities-0.133.7.dist-info → dycw_utilities-0.134.1.dist-info}/RECORD +40 -39
- utilities/__init__.py +1 -1
- utilities/arq.py +13 -20
- utilities/asyncio.py +59 -74
- utilities/atools.py +10 -13
- utilities/cachetools.py +11 -17
- utilities/click.py +31 -51
- utilities/concurrent.py +7 -10
- utilities/dataclasses.py +69 -91
- utilities/enum.py +24 -21
- utilities/eventkit.py +34 -48
- utilities/functions.py +133 -168
- utilities/functools.py +18 -19
- utilities/hypothesis.py +34 -44
- utilities/iterables.py +165 -179
- utilities/luigi.py +3 -15
- utilities/memory_profiler.py +11 -15
- utilities/more_itertools.py +85 -94
- utilities/operator.py +5 -7
- utilities/optuna.py +6 -6
- utilities/pathlib.py +1 -0
- utilities/period.py +7 -9
- utilities/polars.py +5 -16
- utilities/pqdm.py +7 -8
- utilities/pudb.py +62 -0
- utilities/pydantic.py +2 -4
- utilities/pytest.py +14 -23
- utilities/python_dotenv.py +5 -9
- utilities/random.py +2 -3
- utilities/redis.py +163 -181
- utilities/slack_sdk.py +2 -2
- utilities/sqlalchemy.py +4 -14
- utilities/timer.py +6 -0
- utilities/typed_settings.py +7 -10
- utilities/types.py +10 -94
- utilities/typing.py +32 -43
- utilities/uuid.py +1 -0
- {dycw_utilities-0.133.7.dist-info → dycw_utilities-0.134.1.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.133.7.dist-info → dycw_utilities-0.134.1.dist-info}/licenses/LICENSE +0 -0
utilities/redis.py
CHANGED
@@ -9,12 +9,10 @@ from operator import itemgetter
|
|
9
9
|
from typing import (
|
10
10
|
TYPE_CHECKING,
|
11
11
|
Any,
|
12
|
-
Generic,
|
13
12
|
Literal,
|
14
13
|
Self,
|
15
14
|
TypedDict,
|
16
15
|
TypeGuard,
|
17
|
-
TypeVar,
|
18
16
|
assert_never,
|
19
17
|
cast,
|
20
18
|
overload,
|
@@ -51,22 +49,6 @@ if TYPE_CHECKING:
|
|
51
49
|
from utilities.types import MaybeType, TypeLike
|
52
50
|
|
53
51
|
|
54
|
-
_K = TypeVar("_K")
|
55
|
-
_K1 = TypeVar("_K1")
|
56
|
-
_K2 = TypeVar("_K2")
|
57
|
-
_K3 = TypeVar("_K3")
|
58
|
-
_T = TypeVar("_T")
|
59
|
-
_T1 = TypeVar("_T1")
|
60
|
-
_T2 = TypeVar("_T2")
|
61
|
-
_T3 = TypeVar("_T3")
|
62
|
-
_T4 = TypeVar("_T4")
|
63
|
-
_T5 = TypeVar("_T5")
|
64
|
-
_V = TypeVar("_V")
|
65
|
-
_V1 = TypeVar("_V1")
|
66
|
-
_V2 = TypeVar("_V2")
|
67
|
-
_V3 = TypeVar("_V3")
|
68
|
-
|
69
|
-
|
70
52
|
_PUBLISH_TIMEOUT: TimeDelta = SECOND
|
71
53
|
|
72
54
|
|
@@ -74,21 +56,21 @@ _PUBLISH_TIMEOUT: TimeDelta = SECOND
|
|
74
56
|
|
75
57
|
|
76
58
|
@dataclass(kw_only=True)
|
77
|
-
class RedisHashMapKey
|
59
|
+
class RedisHashMapKey[K, V]:
|
78
60
|
"""A hashmap key in a redis store."""
|
79
61
|
|
80
62
|
name: str
|
81
|
-
key: TypeLike[
|
82
|
-
key_serializer: Callable[[
|
83
|
-
key_deserializer: Callable[[bytes],
|
84
|
-
value: TypeLike[
|
85
|
-
value_serializer: Callable[[
|
86
|
-
value_deserializer: Callable[[bytes],
|
63
|
+
key: TypeLike[K]
|
64
|
+
key_serializer: Callable[[K], bytes] | None = None
|
65
|
+
key_deserializer: Callable[[bytes], K] | None = None
|
66
|
+
value: TypeLike[V]
|
67
|
+
value_serializer: Callable[[V], bytes] | None = None
|
68
|
+
value_deserializer: Callable[[bytes], V] | None = None
|
87
69
|
timeout: TimeDelta | None = None
|
88
70
|
error: MaybeType[BaseException] = TimeoutError
|
89
71
|
ttl: TimeDelta | None = None
|
90
72
|
|
91
|
-
async def delete(self, redis: Redis, key:
|
73
|
+
async def delete(self, redis: Redis, key: K, /) -> int:
|
92
74
|
"""Delete a key from a hashmap in `redis`."""
|
93
75
|
ser = _serialize( # skipif-ci-and-not-linux
|
94
76
|
key, serializer=self.key_serializer
|
@@ -99,7 +81,7 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
99
81
|
return await cast("Awaitable[int]", redis.hdel(self.name, ser))
|
100
82
|
raise ImpossibleCaseError(case=[f"{redis=}", f"{key=}"]) # pragma: no cover
|
101
83
|
|
102
|
-
async def exists(self, redis: Redis, key:
|
84
|
+
async def exists(self, redis: Redis, key: K, /) -> bool:
|
103
85
|
"""Check if the key exists in a hashmap in `redis`."""
|
104
86
|
ser = _serialize( # skipif-ci-and-not-linux
|
105
87
|
key, serializer=self.key_serializer
|
@@ -109,14 +91,14 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
109
91
|
):
|
110
92
|
return await cast("Awaitable[bool]", redis.hexists(self.name, ser))
|
111
93
|
|
112
|
-
async def get(self, redis: Redis, key:
|
94
|
+
async def get(self, redis: Redis, key: K, /) -> V:
|
113
95
|
"""Get a value from a hashmap in `redis`."""
|
114
96
|
result = one(await self.get_many(redis, [key])) # skipif-ci-and-not-linux
|
115
97
|
if result is None: # skipif-ci-and-not-linux
|
116
98
|
raise KeyError(self.name, key)
|
117
99
|
return result # skipif-ci-and-not-linux
|
118
100
|
|
119
|
-
async def get_all(self, redis: Redis, /) -> Mapping[
|
101
|
+
async def get_all(self, redis: Redis, /) -> Mapping[K, V]:
|
120
102
|
"""Get a value from a hashmap in `redis`."""
|
121
103
|
async with timeout_td( # skipif-ci-and-not-linux
|
122
104
|
self.timeout, error=self.error
|
@@ -131,9 +113,7 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
131
113
|
for key, value in result.items()
|
132
114
|
}
|
133
115
|
|
134
|
-
async def get_many(
|
135
|
-
self, redis: Redis, keys: Iterable[_K], /
|
136
|
-
) -> Sequence[_V | None]:
|
116
|
+
async def get_many(self, redis: Redis, keys: Iterable[K], /) -> Sequence[V | None]:
|
137
117
|
"""Get multiple values from a hashmap in `redis`."""
|
138
118
|
keys = list(keys) # skipif-ci-and-not-linux
|
139
119
|
if len(keys) == 0: # skipif-ci-and-not-linux
|
@@ -154,7 +134,7 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
154
134
|
for data in result
|
155
135
|
]
|
156
136
|
|
157
|
-
async def keys(self, redis: Redis, /) -> Sequence[
|
137
|
+
async def keys(self, redis: Redis, /) -> Sequence[K]:
|
158
138
|
"""Get the keys of a hashmap in `redis`."""
|
159
139
|
async with timeout_td( # skipif-ci-and-not-linux
|
160
140
|
self.timeout, error=self.error
|
@@ -171,11 +151,11 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
171
151
|
):
|
172
152
|
return await cast("Awaitable[int]", redis.hlen(self.name))
|
173
153
|
|
174
|
-
async def set(self, redis: Redis, key:
|
154
|
+
async def set(self, redis: Redis, key: K, value: V, /) -> int:
|
175
155
|
"""Set a value in a hashmap in `redis`."""
|
176
156
|
return await self.set_many(redis, {key: value}) # skipif-ci-and-not-linux
|
177
157
|
|
178
|
-
async def set_many(self, redis: Redis, mapping: Mapping[
|
158
|
+
async def set_many(self, redis: Redis, mapping: Mapping[K, V], /) -> int:
|
179
159
|
"""Set multiple value(s) in a hashmap in `redis`."""
|
180
160
|
if len(mapping) == 0: # skipif-ci-and-not-linux
|
181
161
|
return 0
|
@@ -195,7 +175,7 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
195
175
|
await redis.pexpire(self.name, self.ttl.py_timedelta())
|
196
176
|
return result # skipif-ci-and-not-linux
|
197
177
|
|
198
|
-
async def values(self, redis: Redis, /) -> Sequence[
|
178
|
+
async def values(self, redis: Redis, /) -> Sequence[V]:
|
199
179
|
"""Get the values of a hashmap in `redis`."""
|
200
180
|
async with timeout_td( # skipif-ci-and-not-linux
|
201
181
|
self.timeout, error=self.error
|
@@ -207,159 +187,159 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
207
187
|
|
208
188
|
|
209
189
|
@overload
|
210
|
-
def redis_hash_map_key(
|
190
|
+
def redis_hash_map_key[K, V](
|
211
191
|
name: str,
|
212
|
-
key: type[
|
213
|
-
value: type[
|
192
|
+
key: type[K],
|
193
|
+
value: type[V],
|
214
194
|
/,
|
215
195
|
*,
|
216
|
-
key_serializer: Callable[[
|
196
|
+
key_serializer: Callable[[K], bytes] | None = None,
|
217
197
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
218
|
-
value_serializer: Callable[[
|
219
|
-
value_deserializer: Callable[[bytes],
|
198
|
+
value_serializer: Callable[[V], bytes] | None = None,
|
199
|
+
value_deserializer: Callable[[bytes], V] | None = None,
|
220
200
|
timeout: TimeDelta | None = None,
|
221
201
|
error: type[Exception] = TimeoutError,
|
222
202
|
ttl: TimeDelta | None = None,
|
223
|
-
) -> RedisHashMapKey[
|
203
|
+
) -> RedisHashMapKey[K, V]: ...
|
224
204
|
@overload
|
225
|
-
def redis_hash_map_key(
|
205
|
+
def redis_hash_map_key[K, V1, V2](
|
226
206
|
name: str,
|
227
|
-
key: type[
|
228
|
-
value: tuple[type[
|
207
|
+
key: type[K],
|
208
|
+
value: tuple[type[V1], type[V2]],
|
229
209
|
/,
|
230
210
|
*,
|
231
|
-
key_serializer: Callable[[
|
211
|
+
key_serializer: Callable[[K], bytes] | None = None,
|
232
212
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
233
|
-
value_serializer: Callable[[
|
234
|
-
value_deserializer: Callable[[bytes],
|
213
|
+
value_serializer: Callable[[V1 | V2], bytes] | None = None,
|
214
|
+
value_deserializer: Callable[[bytes], V1 | V2] | None = None,
|
235
215
|
timeout: TimeDelta | None = None,
|
236
216
|
error: type[Exception] = TimeoutError,
|
237
217
|
ttl: TimeDelta | None = None,
|
238
|
-
) -> RedisHashMapKey[
|
218
|
+
) -> RedisHashMapKey[K, V1 | V2]: ...
|
239
219
|
@overload
|
240
|
-
def redis_hash_map_key(
|
220
|
+
def redis_hash_map_key[K, V1, V2, V3](
|
241
221
|
name: str,
|
242
|
-
key: type[
|
243
|
-
value: tuple[type[
|
222
|
+
key: type[K],
|
223
|
+
value: tuple[type[V1], type[V2], type[V3]],
|
244
224
|
/,
|
245
225
|
*,
|
246
|
-
key_serializer: Callable[[
|
226
|
+
key_serializer: Callable[[K], bytes] | None = None,
|
247
227
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
248
|
-
value_serializer: Callable[[
|
249
|
-
value_deserializer: Callable[[bytes],
|
228
|
+
value_serializer: Callable[[V1 | V2 | V3], bytes] | None = None,
|
229
|
+
value_deserializer: Callable[[bytes], V1 | V2 | V3] | None = None,
|
250
230
|
timeout: TimeDelta | None = None,
|
251
231
|
error: type[Exception] = TimeoutError,
|
252
232
|
ttl: TimeDelta | None = None,
|
253
|
-
) -> RedisHashMapKey[
|
233
|
+
) -> RedisHashMapKey[K, V1 | V2 | V3]: ...
|
254
234
|
@overload
|
255
|
-
def redis_hash_map_key(
|
235
|
+
def redis_hash_map_key[K1, K2, V](
|
256
236
|
name: str,
|
257
|
-
key: tuple[type[
|
258
|
-
value: type[
|
237
|
+
key: tuple[type[K1], type[K2]],
|
238
|
+
value: type[V],
|
259
239
|
/,
|
260
240
|
*,
|
261
|
-
key_serializer: Callable[[
|
241
|
+
key_serializer: Callable[[K1 | K2], bytes] | None = None,
|
262
242
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
263
|
-
value_serializer: Callable[[
|
264
|
-
value_deserializer: Callable[[bytes],
|
243
|
+
value_serializer: Callable[[V], bytes] | None = None,
|
244
|
+
value_deserializer: Callable[[bytes], V] | None = None,
|
265
245
|
timeout: TimeDelta | None = None,
|
266
246
|
error: type[Exception] = TimeoutError,
|
267
247
|
ttl: TimeDelta | None = None,
|
268
|
-
) -> RedisHashMapKey[
|
248
|
+
) -> RedisHashMapKey[K1 | K2, V]: ...
|
269
249
|
@overload
|
270
|
-
def redis_hash_map_key(
|
250
|
+
def redis_hash_map_key[K1, K2, V1, V2](
|
271
251
|
name: str,
|
272
|
-
key: tuple[type[
|
273
|
-
value: tuple[type[
|
252
|
+
key: tuple[type[K1], type[K2]],
|
253
|
+
value: tuple[type[V1], type[V2]],
|
274
254
|
/,
|
275
255
|
*,
|
276
|
-
key_serializer: Callable[[
|
256
|
+
key_serializer: Callable[[K1 | K2], bytes] | None = None,
|
277
257
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
278
|
-
value_serializer: Callable[[
|
279
|
-
value_deserializer: Callable[[bytes],
|
258
|
+
value_serializer: Callable[[V1 | V2], bytes] | None = None,
|
259
|
+
value_deserializer: Callable[[bytes], V1 | V2] | None = None,
|
280
260
|
timeout: TimeDelta | None = None,
|
281
261
|
error: type[Exception] = TimeoutError,
|
282
262
|
ttl: TimeDelta | None = None,
|
283
|
-
) -> RedisHashMapKey[
|
263
|
+
) -> RedisHashMapKey[K1 | K2, V1 | V2]: ...
|
284
264
|
@overload
|
285
|
-
def redis_hash_map_key(
|
265
|
+
def redis_hash_map_key[K1, K2, V1, V2, V3](
|
286
266
|
name: str,
|
287
|
-
key: tuple[type[
|
288
|
-
value: tuple[type[
|
267
|
+
key: tuple[type[K1], type[K2]],
|
268
|
+
value: tuple[type[V1], type[V2], type[V3]],
|
289
269
|
/,
|
290
270
|
*,
|
291
|
-
key_serializer: Callable[[
|
271
|
+
key_serializer: Callable[[K1 | K2], bytes] | None = None,
|
292
272
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
293
|
-
value_serializer: Callable[[
|
294
|
-
value_deserializer: Callable[[bytes],
|
273
|
+
value_serializer: Callable[[V1 | V2 | V3], bytes] | None = None,
|
274
|
+
value_deserializer: Callable[[bytes], V1 | V2 | V3] | None = None,
|
295
275
|
timeout: TimeDelta | None = None,
|
296
276
|
error: type[Exception] = TimeoutError,
|
297
277
|
ttl: TimeDelta | None = None,
|
298
|
-
) -> RedisHashMapKey[
|
278
|
+
) -> RedisHashMapKey[K1 | K2, V1 | V2 | V3]: ...
|
299
279
|
@overload
|
300
|
-
def redis_hash_map_key(
|
280
|
+
def redis_hash_map_key[K1, K2, K3, V](
|
301
281
|
name: str,
|
302
|
-
key: tuple[type[
|
303
|
-
value: type[
|
282
|
+
key: tuple[type[K1], type[K2], type[K3]],
|
283
|
+
value: type[V],
|
304
284
|
/,
|
305
285
|
*,
|
306
|
-
key_serializer: Callable[[
|
286
|
+
key_serializer: Callable[[K1 | K2 | K3], bytes] | None = None,
|
307
287
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
308
|
-
value_serializer: Callable[[
|
309
|
-
value_deserializer: Callable[[bytes],
|
288
|
+
value_serializer: Callable[[V], bytes] | None = None,
|
289
|
+
value_deserializer: Callable[[bytes], V] | None = None,
|
310
290
|
timeout: TimeDelta | None = None,
|
311
291
|
error: type[Exception] = TimeoutError,
|
312
292
|
ttl: TimeDelta | None = None,
|
313
|
-
) -> RedisHashMapKey[
|
293
|
+
) -> RedisHashMapKey[K1 | K2 | K3, V]: ...
|
314
294
|
@overload
|
315
|
-
def redis_hash_map_key(
|
295
|
+
def redis_hash_map_key[K1, K2, K3, V1, V2](
|
316
296
|
name: str,
|
317
|
-
key: tuple[type[
|
318
|
-
value: tuple[type[
|
297
|
+
key: tuple[type[K1], type[K2], type[K3]],
|
298
|
+
value: tuple[type[V1], type[V2]],
|
319
299
|
/,
|
320
300
|
*,
|
321
|
-
key_serializer: Callable[[
|
301
|
+
key_serializer: Callable[[K1 | K2 | K3], bytes] | None = None,
|
322
302
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
323
|
-
value_serializer: Callable[[
|
324
|
-
value_deserializer: Callable[[bytes],
|
303
|
+
value_serializer: Callable[[V1 | V2], bytes] | None = None,
|
304
|
+
value_deserializer: Callable[[bytes], V1 | V2] | None = None,
|
325
305
|
timeout: TimeDelta | None = None,
|
326
306
|
error: type[Exception] = TimeoutError,
|
327
307
|
ttl: TimeDelta | None = None,
|
328
|
-
) -> RedisHashMapKey[
|
308
|
+
) -> RedisHashMapKey[K1 | K2 | K3, V1 | V2]: ...
|
329
309
|
@overload
|
330
|
-
def redis_hash_map_key(
|
310
|
+
def redis_hash_map_key[K1, K2, K3, V1, V2, V3](
|
331
311
|
name: str,
|
332
|
-
key: tuple[type[
|
333
|
-
value: tuple[type[
|
312
|
+
key: tuple[type[K1], type[K2], type[K3]],
|
313
|
+
value: tuple[type[V1], type[V2], type[V3]],
|
334
314
|
/,
|
335
315
|
*,
|
336
|
-
key_serializer: Callable[[
|
316
|
+
key_serializer: Callable[[K1 | K2 | K3], bytes] | None = None,
|
337
317
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
338
|
-
value_serializer: Callable[[
|
339
|
-
value_deserializer: Callable[[bytes],
|
318
|
+
value_serializer: Callable[[V1 | V2 | V3], bytes] | None = None,
|
319
|
+
value_deserializer: Callable[[bytes], V1 | V2 | V3] | None = None,
|
340
320
|
timeout: TimeDelta | None = None,
|
341
321
|
error: type[Exception] = TimeoutError,
|
342
322
|
ttl: TimeDelta | None = None,
|
343
|
-
) -> RedisHashMapKey[
|
323
|
+
) -> RedisHashMapKey[K1 | K2 | K3, V1 | V2 | V3]: ...
|
344
324
|
@overload
|
345
|
-
def redis_hash_map_key(
|
325
|
+
def redis_hash_map_key[K, K1, K2, K3, V, V1, V2, V3](
|
346
326
|
name: str,
|
347
|
-
key: TypeLike[
|
348
|
-
value: TypeLike[
|
327
|
+
key: TypeLike[K],
|
328
|
+
value: TypeLike[V],
|
349
329
|
/,
|
350
330
|
*,
|
351
|
-
key_serializer: Callable[[
|
331
|
+
key_serializer: Callable[[K1 | K2 | K3], bytes] | None = None,
|
352
332
|
key_deserializer: Callable[[bytes], Any] | None = None,
|
353
|
-
value_serializer: Callable[[
|
354
|
-
value_deserializer: Callable[[bytes],
|
333
|
+
value_serializer: Callable[[V1 | V2 | V3], bytes] | None = None,
|
334
|
+
value_deserializer: Callable[[bytes], V1 | V2 | V3] | None = None,
|
355
335
|
timeout: TimeDelta | None = None,
|
356
336
|
error: type[Exception] = TimeoutError,
|
357
337
|
ttl: TimeDelta | None = None,
|
358
|
-
) -> RedisHashMapKey[
|
359
|
-
def redis_hash_map_key(
|
338
|
+
) -> RedisHashMapKey[K, V]: ...
|
339
|
+
def redis_hash_map_key[K, V](
|
360
340
|
name: str,
|
361
|
-
key: TypeLike[
|
362
|
-
value: TypeLike[
|
341
|
+
key: TypeLike[K],
|
342
|
+
value: TypeLike[V],
|
363
343
|
/,
|
364
344
|
*,
|
365
345
|
key_serializer: Callable[[Any], bytes] | None = None,
|
@@ -369,7 +349,7 @@ def redis_hash_map_key(
|
|
369
349
|
timeout: TimeDelta | None = None,
|
370
350
|
ttl: TimeDelta | None = None,
|
371
351
|
error: type[Exception] = TimeoutError,
|
372
|
-
) -> RedisHashMapKey[
|
352
|
+
) -> RedisHashMapKey[K, V]:
|
373
353
|
"""Create a redis key."""
|
374
354
|
return RedisHashMapKey( # skipif-ci-and-not-linux
|
375
355
|
name=name,
|
@@ -389,13 +369,13 @@ def redis_hash_map_key(
|
|
389
369
|
|
390
370
|
|
391
371
|
@dataclass(kw_only=True)
|
392
|
-
class RedisKey
|
372
|
+
class RedisKey[T]:
|
393
373
|
"""A key in a redis store."""
|
394
374
|
|
395
375
|
name: str
|
396
|
-
type: TypeLike[
|
397
|
-
serializer: Callable[[
|
398
|
-
deserializer: Callable[[bytes],
|
376
|
+
type: TypeLike[T]
|
377
|
+
serializer: Callable[[T], bytes] | None = None
|
378
|
+
deserializer: Callable[[bytes], T] | None = None
|
399
379
|
timeout: TimeDelta | None = None
|
400
380
|
error: MaybeType[BaseException] = TimeoutError
|
401
381
|
ttl: TimeDelta | None = None
|
@@ -419,7 +399,7 @@ class RedisKey(Generic[_T]):
|
|
419
399
|
case _ as never:
|
420
400
|
assert_never(never)
|
421
401
|
|
422
|
-
async def get(self, redis: Redis, /) ->
|
402
|
+
async def get(self, redis: Redis, /) -> T:
|
423
403
|
"""Get a value from `redis`."""
|
424
404
|
async with timeout_td( # skipif-ci-and-not-linux
|
425
405
|
self.timeout, error=self.error
|
@@ -431,7 +411,7 @@ class RedisKey(Generic[_T]):
|
|
431
411
|
result, deserializer=self.deserializer
|
432
412
|
)
|
433
413
|
|
434
|
-
async def set(self, redis: Redis, value:
|
414
|
+
async def set(self, redis: Redis, value: T, /) -> int:
|
435
415
|
"""Set a value in `redis`."""
|
436
416
|
ser = _serialize(value, serializer=self.serializer) # skipif-ci-and-not-linux
|
437
417
|
ttl = ( # skipif-ci-and-not-linux
|
@@ -447,80 +427,80 @@ class RedisKey(Generic[_T]):
|
|
447
427
|
|
448
428
|
|
449
429
|
@overload
|
450
|
-
def redis_key(
|
430
|
+
def redis_key[T](
|
451
431
|
name: str,
|
452
|
-
type_: type[
|
432
|
+
type_: type[T],
|
453
433
|
/,
|
454
434
|
*,
|
455
|
-
serializer: Callable[[
|
456
|
-
deserializer: Callable[[bytes],
|
435
|
+
serializer: Callable[[T], bytes] | None = None,
|
436
|
+
deserializer: Callable[[bytes], T] | None = None,
|
457
437
|
timeout: TimeDelta | None = None,
|
458
438
|
error: type[Exception] = TimeoutError,
|
459
439
|
ttl: TimeDelta | None = None,
|
460
|
-
) -> RedisKey[
|
440
|
+
) -> RedisKey[T]: ...
|
461
441
|
@overload
|
462
|
-
def redis_key(
|
442
|
+
def redis_key[T1, T2](
|
463
443
|
name: str,
|
464
|
-
type_: tuple[type[
|
444
|
+
type_: tuple[type[T1], type[T2]],
|
465
445
|
/,
|
466
446
|
*,
|
467
|
-
serializer: Callable[[
|
468
|
-
deserializer: Callable[[bytes],
|
447
|
+
serializer: Callable[[T1 | T2], bytes] | None = None,
|
448
|
+
deserializer: Callable[[bytes], T1 | T2] | None = None,
|
469
449
|
timeout: TimeDelta | None = None,
|
470
450
|
error: type[Exception] = TimeoutError,
|
471
451
|
ttl: TimeDelta | None = None,
|
472
|
-
) -> RedisKey[
|
452
|
+
) -> RedisKey[T1 | T2]: ...
|
473
453
|
@overload
|
474
|
-
def redis_key(
|
454
|
+
def redis_key[T1, T2, T3](
|
475
455
|
name: str,
|
476
|
-
type_: tuple[type[
|
456
|
+
type_: tuple[type[T1], type[T2], type[T3]],
|
477
457
|
/,
|
478
458
|
*,
|
479
|
-
serializer: Callable[[
|
480
|
-
deserializer: Callable[[bytes],
|
459
|
+
serializer: Callable[[T1 | T2 | T3], bytes] | None = None,
|
460
|
+
deserializer: Callable[[bytes], T1 | T2 | T3] | None = None,
|
481
461
|
timeout: TimeDelta | None = None,
|
482
462
|
error: type[Exception] = TimeoutError,
|
483
463
|
ttl: TimeDelta | None = None,
|
484
|
-
) -> RedisKey[
|
464
|
+
) -> RedisKey[T1 | T2 | T3]: ...
|
485
465
|
@overload
|
486
|
-
def redis_key(
|
466
|
+
def redis_key[T1, T2, T3, T4](
|
487
467
|
name: str,
|
488
|
-
type_: tuple[type[
|
468
|
+
type_: tuple[type[T1], type[T2], type[T3], type[T4]],
|
489
469
|
/,
|
490
470
|
*,
|
491
|
-
serializer: Callable[[
|
492
|
-
deserializer: Callable[[bytes],
|
471
|
+
serializer: Callable[[T1 | T2 | T3 | T4], bytes] | None = None,
|
472
|
+
deserializer: Callable[[bytes], T1 | T2 | T3 | T4] | None = None,
|
493
473
|
timeout: TimeDelta | None = None,
|
494
474
|
error: type[Exception] = TimeoutError,
|
495
475
|
ttl: TimeDelta | None = None,
|
496
|
-
) -> RedisKey[
|
476
|
+
) -> RedisKey[T1 | T2 | T3 | T4]: ...
|
497
477
|
@overload
|
498
|
-
def redis_key(
|
478
|
+
def redis_key[T1, T2, T3, T4, T5](
|
499
479
|
name: str,
|
500
|
-
type_: tuple[type[
|
480
|
+
type_: tuple[type[T1], type[T2], type[T3], type[T4], type[T5]],
|
501
481
|
/,
|
502
482
|
*,
|
503
|
-
serializer: Callable[[
|
504
|
-
deserializer: Callable[[bytes],
|
483
|
+
serializer: Callable[[T1 | T2 | T3 | T4 | T5], bytes] | None = None,
|
484
|
+
deserializer: Callable[[bytes], T1 | T2 | T3 | T4 | T5] | None = None,
|
505
485
|
timeout: TimeDelta | None = None,
|
506
486
|
error: type[Exception] = TimeoutError,
|
507
487
|
ttl: TimeDelta | None = None,
|
508
|
-
) -> RedisKey[
|
488
|
+
) -> RedisKey[T1 | T2 | T3 | T4 | T5]: ...
|
509
489
|
@overload
|
510
|
-
def redis_key(
|
490
|
+
def redis_key[T, T1, T2, T3, T4, T5](
|
511
491
|
name: str,
|
512
|
-
type_: TypeLike[
|
492
|
+
type_: TypeLike[T],
|
513
493
|
/,
|
514
494
|
*,
|
515
|
-
serializer: Callable[[
|
516
|
-
deserializer: Callable[[bytes],
|
495
|
+
serializer: Callable[[T1 | T2 | T3 | T4 | T5], bytes] | None = None,
|
496
|
+
deserializer: Callable[[bytes], T1 | T2 | T3 | T4 | T5] | None = None,
|
517
497
|
timeout: TimeDelta | None = None,
|
518
498
|
error: type[Exception] = TimeoutError,
|
519
499
|
ttl: TimeDelta | None = None,
|
520
|
-
) -> RedisKey[
|
521
|
-
def redis_key(
|
500
|
+
) -> RedisKey[T]: ...
|
501
|
+
def redis_key[T](
|
522
502
|
name: str,
|
523
|
-
type_: TypeLike[
|
503
|
+
type_: TypeLike[T],
|
524
504
|
/,
|
525
505
|
*,
|
526
506
|
serializer: Callable[[Any], bytes] | None = None,
|
@@ -528,7 +508,7 @@ def redis_key(
|
|
528
508
|
timeout: TimeDelta | None = None,
|
529
509
|
error: type[Exception] = TimeoutError,
|
530
510
|
ttl: TimeDelta | None = None,
|
531
|
-
) -> RedisKey[
|
511
|
+
) -> RedisKey[T]:
|
532
512
|
"""Create a redis key."""
|
533
513
|
return RedisKey( # skipif-ci-and-not-linux
|
534
514
|
name=name,
|
@@ -545,13 +525,13 @@ def redis_key(
|
|
545
525
|
|
546
526
|
|
547
527
|
@overload
|
548
|
-
async def publish(
|
528
|
+
async def publish[T](
|
549
529
|
redis: Redis,
|
550
530
|
channel: str,
|
551
|
-
data:
|
531
|
+
data: T,
|
552
532
|
/,
|
553
533
|
*,
|
554
|
-
serializer: Callable[[
|
534
|
+
serializer: Callable[[T], EncodableT],
|
555
535
|
timeout: TimeDelta = _PUBLISH_TIMEOUT,
|
556
536
|
) -> ResponseT: ...
|
557
537
|
@overload
|
@@ -565,22 +545,22 @@ async def publish(
|
|
565
545
|
timeout: TimeDelta = _PUBLISH_TIMEOUT,
|
566
546
|
) -> ResponseT: ...
|
567
547
|
@overload
|
568
|
-
async def publish(
|
548
|
+
async def publish[T](
|
569
549
|
redis: Redis,
|
570
550
|
channel: str,
|
571
|
-
data: bytes | str |
|
551
|
+
data: bytes | str | T,
|
572
552
|
/,
|
573
553
|
*,
|
574
|
-
serializer: Callable[[
|
554
|
+
serializer: Callable[[T], EncodableT] | None = None,
|
575
555
|
timeout: TimeDelta = _PUBLISH_TIMEOUT,
|
576
556
|
) -> ResponseT: ...
|
577
|
-
async def publish(
|
557
|
+
async def publish[T](
|
578
558
|
redis: Redis,
|
579
559
|
channel: str,
|
580
|
-
data: bytes | str |
|
560
|
+
data: bytes | str | T,
|
581
561
|
/,
|
582
562
|
*,
|
583
|
-
serializer: Callable[[
|
563
|
+
serializer: Callable[[T], EncodableT] | None = None,
|
584
564
|
timeout: TimeDelta = _PUBLISH_TIMEOUT,
|
585
565
|
) -> ResponseT:
|
586
566
|
"""Publish an object to a channel."""
|
@@ -613,7 +593,7 @@ class PublishError(Exception):
|
|
613
593
|
|
614
594
|
|
615
595
|
@dataclass(kw_only=True)
|
616
|
-
class PublishService(Looper[tuple[str,
|
596
|
+
class PublishService[T](Looper[tuple[str, T]]):
|
617
597
|
"""Service to publish items to Redis."""
|
618
598
|
|
619
599
|
# base
|
@@ -622,7 +602,7 @@ class PublishService(Looper[tuple[str, _T]]):
|
|
622
602
|
empty_upon_exit: bool = field(default=True, repr=False)
|
623
603
|
# self
|
624
604
|
redis: Redis
|
625
|
-
serializer: Callable[[
|
605
|
+
serializer: Callable[[T], EncodableT] = serialize
|
626
606
|
publish_timeout: TimeDelta = _PUBLISH_TIMEOUT
|
627
607
|
|
628
608
|
@override
|
@@ -643,7 +623,7 @@ class PublishService(Looper[tuple[str, _T]]):
|
|
643
623
|
|
644
624
|
|
645
625
|
@dataclass(kw_only=True)
|
646
|
-
class PublishServiceMixin
|
626
|
+
class PublishServiceMixin[T]:
|
647
627
|
"""Mix-in for the publish service."""
|
648
628
|
|
649
629
|
# base - looper
|
@@ -656,10 +636,10 @@ class PublishServiceMixin(Generic[_T]):
|
|
656
636
|
_is_pending_restart: Event = field(default_factory=Event, init=False, repr=False)
|
657
637
|
# base - publish service
|
658
638
|
publish_service_redis: Redis
|
659
|
-
publish_service_serializer: Callable[[
|
639
|
+
publish_service_serializer: Callable[[T], EncodableT] = serialize
|
660
640
|
publish_service_publish_timeout: TimeDelta = _PUBLISH_TIMEOUT
|
661
641
|
# self
|
662
|
-
_publish_service: PublishService[
|
642
|
+
_publish_service: PublishService[T] = field(init=False, repr=False)
|
663
643
|
|
664
644
|
def __post_init__(self) -> None:
|
665
645
|
with suppress_super_object_attribute_error(): # skipif-ci-and-not-linux
|
@@ -732,27 +712,27 @@ def subscribe(
|
|
732
712
|
) -> AsyncIterator[Task[None]]: ...
|
733
713
|
@overload
|
734
714
|
@asynccontextmanager
|
735
|
-
def subscribe(
|
715
|
+
def subscribe[T](
|
736
716
|
redis: Redis,
|
737
717
|
channels: MaybeIterable[str],
|
738
|
-
queue: Queue[
|
718
|
+
queue: Queue[T],
|
739
719
|
/,
|
740
720
|
*,
|
741
721
|
timeout: TimeDelta | None = _SUBSCRIBE_TIMEOUT,
|
742
722
|
sleep: TimeDelta = _SUBSCRIBE_SLEEP,
|
743
|
-
output: Callable[[bytes],
|
744
|
-
filter_: Callable[[
|
723
|
+
output: Callable[[bytes], T],
|
724
|
+
filter_: Callable[[T], bool] | None = None,
|
745
725
|
) -> AsyncIterator[Task[None]]: ...
|
746
726
|
@asynccontextmanager
|
747
|
-
async def subscribe(
|
727
|
+
async def subscribe[T](
|
748
728
|
redis: Redis,
|
749
729
|
channels: MaybeIterable[str],
|
750
|
-
queue: Queue[_RedisMessage] | Queue[bytes] | Queue[
|
730
|
+
queue: Queue[_RedisMessage] | Queue[bytes] | Queue[T],
|
751
731
|
/,
|
752
732
|
*,
|
753
733
|
timeout: TimeDelta | None = _SUBSCRIBE_TIMEOUT,
|
754
734
|
sleep: TimeDelta = _SUBSCRIBE_SLEEP,
|
755
|
-
output: Literal["raw", "bytes", "text"] | Callable[[bytes],
|
735
|
+
output: Literal["raw", "bytes", "text"] | Callable[[bytes], T] = "text",
|
756
736
|
filter_: Callable[[Any], bool] | None = None,
|
757
737
|
) -> AsyncIterator[Task[None]]:
|
758
738
|
"""Subscribe to the data of a given channel(s)."""
|
@@ -769,7 +749,7 @@ async def subscribe(
|
|
769
749
|
|
770
750
|
case Callable() as deserialize:
|
771
751
|
|
772
|
-
def transform(message: _RedisMessage, /) ->
|
752
|
+
def transform(message: _RedisMessage, /) -> T:
|
773
753
|
return deserialize(message["data"])
|
774
754
|
|
775
755
|
case _ as never:
|
@@ -852,7 +832,7 @@ class _RedisMessage(TypedDict):
|
|
852
832
|
|
853
833
|
|
854
834
|
@dataclass(kw_only=True)
|
855
|
-
class SubscribeService(Looper[
|
835
|
+
class SubscribeService[T](Looper[T]):
|
856
836
|
"""Service to subscribe to Redis."""
|
857
837
|
|
858
838
|
# base
|
@@ -862,10 +842,10 @@ class SubscribeService(Looper[_T]):
|
|
862
842
|
# self
|
863
843
|
redis: Redis
|
864
844
|
channel: str
|
865
|
-
deserializer: Callable[[bytes],
|
845
|
+
deserializer: Callable[[bytes], T] = deserialize
|
866
846
|
subscribe_timeout: TimeDelta | None = _SUBSCRIBE_TIMEOUT
|
867
847
|
subscribe_sleep: TimeDelta = _SUBSCRIBE_SLEEP
|
868
|
-
filter_: Callable[[
|
848
|
+
filter_: Callable[[T], bool] | None = None
|
869
849
|
_is_subscribed: Event = field(default_factory=Event, init=False, repr=False)
|
870
850
|
|
871
851
|
@override
|
@@ -922,7 +902,7 @@ class SubscribeService(Looper[_T]):
|
|
922
902
|
|
923
903
|
|
924
904
|
@dataclass(kw_only=True)
|
925
|
-
class SubscribeServiceMixin
|
905
|
+
class SubscribeServiceMixin[T]:
|
926
906
|
"""Mix-in for the subscribe service."""
|
927
907
|
|
928
908
|
# base - looper
|
@@ -935,11 +915,11 @@ class SubscribeServiceMixin(Generic[_T]):
|
|
935
915
|
# base - looper
|
936
916
|
subscribe_service_redis: Redis
|
937
917
|
subscribe_service_channel: str
|
938
|
-
subscribe_service_deserializer: Callable[[bytes],
|
918
|
+
subscribe_service_deserializer: Callable[[bytes], T] = deserialize
|
939
919
|
subscribe_service_subscribe_sleep: TimeDelta = _SUBSCRIBE_SLEEP
|
940
920
|
subscribe_service_subscribe_timeout: TimeDelta | None = _SUBSCRIBE_TIMEOUT
|
941
921
|
# self
|
942
|
-
_subscribe_service: SubscribeService[
|
922
|
+
_subscribe_service: SubscribeService[T] = field(init=False, repr=False)
|
943
923
|
|
944
924
|
def __post_init__(self) -> None:
|
945
925
|
with suppress_super_object_attribute_error(): # skipif-ci-and-not-linux
|
@@ -1029,7 +1009,9 @@ async def yield_redis(
|
|
1029
1009
|
##
|
1030
1010
|
|
1031
1011
|
|
1032
|
-
def _serialize
|
1012
|
+
def _serialize[T](
|
1013
|
+
obj: T, /, *, serializer: Callable[[T], bytes] | None = None
|
1014
|
+
) -> bytes:
|
1033
1015
|
if serializer is None: # skipif-ci-and-not-linux
|
1034
1016
|
from utilities.orjson import serialize as serializer_use
|
1035
1017
|
else: # skipif-ci-and-not-linux
|
@@ -1037,9 +1019,9 @@ def _serialize(obj: _T, /, *, serializer: Callable[[_T], bytes] | None = None) -
|
|
1037
1019
|
return serializer_use(obj) # skipif-ci-and-not-linux
|
1038
1020
|
|
1039
1021
|
|
1040
|
-
def _deserialize(
|
1041
|
-
data: bytes, /, *, deserializer: Callable[[bytes],
|
1042
|
-
) ->
|
1022
|
+
def _deserialize[T](
|
1023
|
+
data: bytes, /, *, deserializer: Callable[[bytes], T] | None = None
|
1024
|
+
) -> T:
|
1043
1025
|
if deserializer is None: # skipif-ci-and-not-linux
|
1044
1026
|
from utilities.orjson import deserialize as deserializer_use
|
1045
1027
|
else: # skipif-ci-and-not-linux
|