audex 1.0.7a3__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.
- audex/__init__.py +9 -0
- audex/__main__.py +7 -0
- audex/cli/__init__.py +189 -0
- audex/cli/apis/__init__.py +12 -0
- audex/cli/apis/init/__init__.py +34 -0
- audex/cli/apis/init/gencfg.py +130 -0
- audex/cli/apis/init/setup.py +330 -0
- audex/cli/apis/init/vprgroup.py +125 -0
- audex/cli/apis/serve.py +141 -0
- audex/cli/args.py +356 -0
- audex/cli/exceptions.py +44 -0
- audex/cli/helper/__init__.py +0 -0
- audex/cli/helper/ansi.py +193 -0
- audex/cli/helper/display.py +288 -0
- audex/config/__init__.py +64 -0
- audex/config/core/__init__.py +30 -0
- audex/config/core/app.py +29 -0
- audex/config/core/audio.py +45 -0
- audex/config/core/logging.py +163 -0
- audex/config/core/session.py +11 -0
- audex/config/helper/__init__.py +1 -0
- audex/config/helper/client/__init__.py +1 -0
- audex/config/helper/client/http.py +28 -0
- audex/config/helper/client/websocket.py +21 -0
- audex/config/helper/provider/__init__.py +1 -0
- audex/config/helper/provider/dashscope.py +13 -0
- audex/config/helper/provider/unisound.py +18 -0
- audex/config/helper/provider/xfyun.py +23 -0
- audex/config/infrastructure/__init__.py +31 -0
- audex/config/infrastructure/cache.py +51 -0
- audex/config/infrastructure/database.py +48 -0
- audex/config/infrastructure/recorder.py +32 -0
- audex/config/infrastructure/store.py +19 -0
- audex/config/provider/__init__.py +18 -0
- audex/config/provider/transcription.py +109 -0
- audex/config/provider/vpr.py +99 -0
- audex/container.py +40 -0
- audex/entity/__init__.py +468 -0
- audex/entity/doctor.py +109 -0
- audex/entity/doctor.pyi +51 -0
- audex/entity/fields.py +401 -0
- audex/entity/segment.py +115 -0
- audex/entity/segment.pyi +38 -0
- audex/entity/session.py +133 -0
- audex/entity/session.pyi +47 -0
- audex/entity/utterance.py +142 -0
- audex/entity/utterance.pyi +48 -0
- audex/entity/vp.py +68 -0
- audex/entity/vp.pyi +35 -0
- audex/exceptions.py +157 -0
- audex/filters/__init__.py +692 -0
- audex/filters/generated/__init__.py +21 -0
- audex/filters/generated/doctor.py +987 -0
- audex/filters/generated/segment.py +723 -0
- audex/filters/generated/session.py +978 -0
- audex/filters/generated/utterance.py +939 -0
- audex/filters/generated/vp.py +815 -0
- audex/helper/__init__.py +1 -0
- audex/helper/hash.py +33 -0
- audex/helper/mixin.py +65 -0
- audex/helper/net.py +19 -0
- audex/helper/settings/__init__.py +830 -0
- audex/helper/settings/fields.py +317 -0
- audex/helper/stream.py +153 -0
- audex/injectors/__init__.py +1 -0
- audex/injectors/config.py +12 -0
- audex/injectors/lifespan.py +7 -0
- audex/lib/__init__.py +1 -0
- audex/lib/cache/__init__.py +383 -0
- audex/lib/cache/inmemory.py +513 -0
- audex/lib/database/__init__.py +83 -0
- audex/lib/database/sqlite.py +406 -0
- audex/lib/exporter.py +189 -0
- audex/lib/injectors/__init__.py +1 -0
- audex/lib/injectors/cache.py +25 -0
- audex/lib/injectors/container.py +47 -0
- audex/lib/injectors/exporter.py +26 -0
- audex/lib/injectors/recorder.py +33 -0
- audex/lib/injectors/server.py +17 -0
- audex/lib/injectors/session.py +18 -0
- audex/lib/injectors/sqlite.py +24 -0
- audex/lib/injectors/store.py +13 -0
- audex/lib/injectors/transcription.py +42 -0
- audex/lib/injectors/usb.py +12 -0
- audex/lib/injectors/vpr.py +65 -0
- audex/lib/injectors/wifi.py +7 -0
- audex/lib/recorder.py +844 -0
- audex/lib/repos/__init__.py +149 -0
- audex/lib/repos/container.py +23 -0
- audex/lib/repos/database/__init__.py +1 -0
- audex/lib/repos/database/sqlite.py +672 -0
- audex/lib/repos/decorators.py +74 -0
- audex/lib/repos/doctor.py +286 -0
- audex/lib/repos/segment.py +302 -0
- audex/lib/repos/session.py +285 -0
- audex/lib/repos/tables/__init__.py +70 -0
- audex/lib/repos/tables/doctor.py +137 -0
- audex/lib/repos/tables/segment.py +113 -0
- audex/lib/repos/tables/session.py +140 -0
- audex/lib/repos/tables/utterance.py +131 -0
- audex/lib/repos/tables/vp.py +102 -0
- audex/lib/repos/utterance.py +288 -0
- audex/lib/repos/vp.py +286 -0
- audex/lib/restful.py +251 -0
- audex/lib/server/__init__.py +97 -0
- audex/lib/server/auth.py +98 -0
- audex/lib/server/handlers.py +248 -0
- audex/lib/server/templates/index.html.j2 +226 -0
- audex/lib/server/templates/login.html.j2 +111 -0
- audex/lib/server/templates/static/script.js +68 -0
- audex/lib/server/templates/static/style.css +579 -0
- audex/lib/server/types.py +123 -0
- audex/lib/session.py +503 -0
- audex/lib/store/__init__.py +238 -0
- audex/lib/store/localfile.py +411 -0
- audex/lib/transcription/__init__.py +33 -0
- audex/lib/transcription/dashscope.py +525 -0
- audex/lib/transcription/events.py +62 -0
- audex/lib/usb.py +554 -0
- audex/lib/vpr/__init__.py +38 -0
- audex/lib/vpr/unisound/__init__.py +185 -0
- audex/lib/vpr/unisound/types.py +469 -0
- audex/lib/vpr/xfyun/__init__.py +483 -0
- audex/lib/vpr/xfyun/types.py +679 -0
- audex/lib/websocket/__init__.py +8 -0
- audex/lib/websocket/connection.py +485 -0
- audex/lib/websocket/pool.py +991 -0
- audex/lib/wifi.py +1146 -0
- audex/lifespan.py +75 -0
- audex/service/__init__.py +27 -0
- audex/service/decorators.py +73 -0
- audex/service/doctor/__init__.py +652 -0
- audex/service/doctor/const.py +36 -0
- audex/service/doctor/exceptions.py +96 -0
- audex/service/doctor/types.py +54 -0
- audex/service/export/__init__.py +236 -0
- audex/service/export/const.py +17 -0
- audex/service/export/exceptions.py +34 -0
- audex/service/export/types.py +21 -0
- audex/service/injectors/__init__.py +1 -0
- audex/service/injectors/container.py +53 -0
- audex/service/injectors/doctor.py +34 -0
- audex/service/injectors/export.py +27 -0
- audex/service/injectors/session.py +49 -0
- audex/service/session/__init__.py +754 -0
- audex/service/session/const.py +34 -0
- audex/service/session/exceptions.py +67 -0
- audex/service/session/types.py +91 -0
- audex/types.py +39 -0
- audex/utils.py +287 -0
- audex/valueobj/__init__.py +81 -0
- audex/valueobj/common/__init__.py +1 -0
- audex/valueobj/common/auth.py +84 -0
- audex/valueobj/common/email.py +16 -0
- audex/valueobj/common/ops.py +22 -0
- audex/valueobj/common/phone.py +84 -0
- audex/valueobj/common/version.py +72 -0
- audex/valueobj/session.py +19 -0
- audex/valueobj/utterance.py +15 -0
- audex/view/__init__.py +51 -0
- audex/view/container.py +17 -0
- audex/view/decorators.py +303 -0
- audex/view/pages/__init__.py +1 -0
- audex/view/pages/dashboard/__init__.py +286 -0
- audex/view/pages/dashboard/wifi.py +407 -0
- audex/view/pages/login.py +110 -0
- audex/view/pages/recording.py +348 -0
- audex/view/pages/register.py +202 -0
- audex/view/pages/sessions/__init__.py +196 -0
- audex/view/pages/sessions/details.py +224 -0
- audex/view/pages/sessions/export.py +443 -0
- audex/view/pages/settings.py +374 -0
- audex/view/pages/voiceprint/__init__.py +1 -0
- audex/view/pages/voiceprint/enroll.py +195 -0
- audex/view/pages/voiceprint/update.py +195 -0
- audex/view/static/css/dashboard.css +452 -0
- audex/view/static/css/glass.css +22 -0
- audex/view/static/css/global.css +541 -0
- audex/view/static/css/login.css +386 -0
- audex/view/static/css/recording.css +439 -0
- audex/view/static/css/register.css +293 -0
- audex/view/static/css/sessions/styles.css +501 -0
- audex/view/static/css/settings.css +186 -0
- audex/view/static/css/voiceprint/enroll.css +43 -0
- audex/view/static/css/voiceprint/styles.css +209 -0
- audex/view/static/css/voiceprint/update.css +44 -0
- audex/view/static/images/logo.svg +95 -0
- audex/view/static/js/recording.js +42 -0
- audex-1.0.7a3.dist-info/METADATA +361 -0
- audex-1.0.7a3.dist-info/RECORD +192 -0
- audex-1.0.7a3.dist-info/WHEEL +4 -0
- audex-1.0.7a3.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import typing as t
|
|
5
|
+
|
|
6
|
+
from audex import __title__
|
|
7
|
+
from audex.helper.mixin import AsyncContextMixin
|
|
8
|
+
from audex.helper.mixin import LoggingMixin
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Empty:
|
|
12
|
+
"""Sentinel type representing an empty/missing value.
|
|
13
|
+
|
|
14
|
+
Used to distinguish between None (a valid value) and a truly missing value.
|
|
15
|
+
Always evaluates to False in boolean context.
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
```python
|
|
19
|
+
async def get_value(key: str) -> str | Empty:
|
|
20
|
+
if key not in data:
|
|
21
|
+
return EMPTY
|
|
22
|
+
return data[key]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
value = await get_value("missing")
|
|
26
|
+
if value is EMPTY:
|
|
27
|
+
print("Value not found")
|
|
28
|
+
```
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
__slots__ = ()
|
|
32
|
+
|
|
33
|
+
def __repr__(self) -> str:
|
|
34
|
+
return "<EMPTY>"
|
|
35
|
+
|
|
36
|
+
__str__ = __repr__
|
|
37
|
+
|
|
38
|
+
def __bool__(self) -> bool:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
def __eq__(self, other: object) -> bool:
|
|
42
|
+
return isinstance(other, Empty)
|
|
43
|
+
|
|
44
|
+
def __hash__(self) -> int:
|
|
45
|
+
return hash("<EMPTY>")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
EMPTY = Empty()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Placeholder:
|
|
52
|
+
"""Sentinel type representing a placeholder value.
|
|
53
|
+
|
|
54
|
+
Used to mark positions where a value will be provided later. Always
|
|
55
|
+
evaluates to True in boolean context.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
__slots__ = ()
|
|
59
|
+
|
|
60
|
+
def __repr__(self) -> str:
|
|
61
|
+
return "<PLACEHOLDER>"
|
|
62
|
+
|
|
63
|
+
__str__ = __repr__
|
|
64
|
+
|
|
65
|
+
def __bool__(self) -> bool:
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
def __getstate__(self) -> tuple[()]:
|
|
69
|
+
return ()
|
|
70
|
+
|
|
71
|
+
def __setstate__(self, state: tuple[()]) -> None:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
def __eq__(self, other: object) -> bool:
|
|
75
|
+
return isinstance(other, Placeholder)
|
|
76
|
+
|
|
77
|
+
def __hash__(self) -> int:
|
|
78
|
+
return hash("<PLACEHOLDER>")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
PLACEHOLDER = Placeholder()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class CacheMiss:
|
|
85
|
+
"""Sentinel type representing a cache miss.
|
|
86
|
+
|
|
87
|
+
Used to distinguish between cached None values and keys that don't
|
|
88
|
+
exist. Always evaluates to False in boolean context.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
__slots__ = ()
|
|
92
|
+
|
|
93
|
+
def __repr__(self) -> str:
|
|
94
|
+
return "<CACHE_MISS>"
|
|
95
|
+
|
|
96
|
+
__str__ = __repr__
|
|
97
|
+
|
|
98
|
+
def __bool__(self) -> bool:
|
|
99
|
+
return False
|
|
100
|
+
|
|
101
|
+
def __eq__(self, other: object) -> bool:
|
|
102
|
+
return isinstance(other, CacheMiss)
|
|
103
|
+
|
|
104
|
+
def __hash__(self) -> int:
|
|
105
|
+
return hash("<CACHE_MISS>")
|
|
106
|
+
|
|
107
|
+
def __getstate__(self) -> tuple[()]:
|
|
108
|
+
return ()
|
|
109
|
+
|
|
110
|
+
def __setstate__(self, state: tuple[()]) -> None:
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
CACHE_MISS = CacheMiss()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class Negative:
|
|
118
|
+
"""Sentinel type representing a negative cache entry.
|
|
119
|
+
|
|
120
|
+
Used to mark keys that are known to be absent, preventing cache
|
|
121
|
+
penetration. Always evaluates to False in boolean context.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
__slots__ = ()
|
|
125
|
+
|
|
126
|
+
def __repr__(self) -> str:
|
|
127
|
+
return "<NEGATIVE>"
|
|
128
|
+
|
|
129
|
+
__str__ = __repr__
|
|
130
|
+
|
|
131
|
+
def __bool__(self) -> bool:
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
def __eq__(self, other: object) -> bool:
|
|
135
|
+
return isinstance(other, Negative)
|
|
136
|
+
|
|
137
|
+
def __hash__(self) -> int:
|
|
138
|
+
return hash("<NEGATIVE>")
|
|
139
|
+
|
|
140
|
+
def __getstate__(self) -> tuple[()]:
|
|
141
|
+
return ()
|
|
142
|
+
|
|
143
|
+
def __setstate__(self, state: tuple[()]) -> None:
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
NEGATIVE = Negative()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class KeyBuilder:
|
|
151
|
+
"""Utility class for building cache keys with a consistent format.
|
|
152
|
+
|
|
153
|
+
Provides methods to construct namespaced cache keys and validate key formats.
|
|
154
|
+
|
|
155
|
+
Attributes:
|
|
156
|
+
split_char: Character used to split parts of the key.
|
|
157
|
+
prefix: Prefix to prepend to all keys.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
split_char: Separator character for key parts. Defaults to ":".
|
|
161
|
+
prefix: Namespace prefix for all keys. Defaults to normalized project title.
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
```python
|
|
165
|
+
builder = KeyBuilder(prefix="myapp")
|
|
166
|
+
|
|
167
|
+
# Build keys
|
|
168
|
+
user_key = builder.build("user", "123") # "myapp:user:123"
|
|
169
|
+
session_key = builder.build(
|
|
170
|
+
"session", "abc"
|
|
171
|
+
) # "myapp:session:abc"
|
|
172
|
+
|
|
173
|
+
# Validate keys
|
|
174
|
+
builder.validate("myapp:user:123") # True
|
|
175
|
+
builder.validate("other:user:123") # False
|
|
176
|
+
```
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
__slots__ = ("prefix", "split_char")
|
|
180
|
+
|
|
181
|
+
def __init__(
|
|
182
|
+
self,
|
|
183
|
+
split_char: str = ":",
|
|
184
|
+
prefix: str = __title__.lower().replace(" ", "_"),
|
|
185
|
+
) -> None:
|
|
186
|
+
self.split_char = split_char
|
|
187
|
+
self.prefix = prefix
|
|
188
|
+
|
|
189
|
+
def build(self, *parts: str) -> str:
|
|
190
|
+
"""Build a cache key by joining the prefix and parts.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
*parts: Parts to include in the key.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
The constructed cache key.
|
|
197
|
+
"""
|
|
198
|
+
return self.split_char.join((self.prefix, *parts))
|
|
199
|
+
|
|
200
|
+
def validate(self, key: str) -> bool:
|
|
201
|
+
"""Validate if a given key starts with the defined prefix.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
key: The cache key to validate.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
True if the key starts with the prefix, False otherwise.
|
|
208
|
+
"""
|
|
209
|
+
return key.startswith(self.prefix + self.split_char)
|
|
210
|
+
|
|
211
|
+
def __repr__(self) -> str:
|
|
212
|
+
return f"CACHE KEY BUILDER <{self.__class__.__name__} (prefix={self.prefix}, split_char={self.split_char})>"
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
T = t.TypeVar("T")
|
|
216
|
+
VT = t.TypeVar("VT")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class KVCache(LoggingMixin, AsyncContextMixin, abc.ABC):
|
|
220
|
+
"""Abstract base class for async key-value cache implementations.
|
|
221
|
+
|
|
222
|
+
Provides an async dictionary-like interface for caching with support for TTL,
|
|
223
|
+
atomic operations (incr/decr), and key validation. Implementations can
|
|
224
|
+
use in-memory storage, Redis, or other backends.
|
|
225
|
+
|
|
226
|
+
The cache supports:
|
|
227
|
+
- Async dict operations (get, set, delete, etc.)
|
|
228
|
+
- Time-to-live (TTL) for automatic expiration
|
|
229
|
+
- Atomic increment/decrement operations
|
|
230
|
+
- Key namespace management via KeyBuilder
|
|
231
|
+
|
|
232
|
+
Example:
|
|
233
|
+
```python
|
|
234
|
+
# Using a cache implementation
|
|
235
|
+
cache = await make_cache(config, logger)
|
|
236
|
+
|
|
237
|
+
# Basic operations
|
|
238
|
+
await cache.set("user:123", {"name": "Alice"})
|
|
239
|
+
user = await cache.get("user:123")
|
|
240
|
+
|
|
241
|
+
# With TTL
|
|
242
|
+
await cache.setx("session:abc", {"data": "..."}, ttl=3600)
|
|
243
|
+
|
|
244
|
+
# Atomic operations
|
|
245
|
+
await cache.incr("counter:visits")
|
|
246
|
+
await cache.decr("counter:remaining", amount=5)
|
|
247
|
+
```
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
@abc.abstractmethod
|
|
252
|
+
def key_builder(self) -> KeyBuilder:
|
|
253
|
+
"""Get the KeyBuilder instance used for constructing cache
|
|
254
|
+
keys."""
|
|
255
|
+
|
|
256
|
+
@abc.abstractmethod
|
|
257
|
+
async def get_item(self, key: str) -> VT | Empty | Negative:
|
|
258
|
+
"""Retrieve an item from the cache by key."""
|
|
259
|
+
|
|
260
|
+
@abc.abstractmethod
|
|
261
|
+
async def set_item(self, key: str, value: VT) -> None:
|
|
262
|
+
"""Set an item in the cache with the specified key and value."""
|
|
263
|
+
|
|
264
|
+
@abc.abstractmethod
|
|
265
|
+
async def del_item(self, key: str) -> None:
|
|
266
|
+
"""Delete an item from the cache by key."""
|
|
267
|
+
|
|
268
|
+
@abc.abstractmethod
|
|
269
|
+
def iter_keys(self) -> t.AsyncIterator[str]:
|
|
270
|
+
"""Return an async iterator over the keys in the cache."""
|
|
271
|
+
|
|
272
|
+
@abc.abstractmethod
|
|
273
|
+
async def len(self) -> int:
|
|
274
|
+
"""Return the number of items in the cache."""
|
|
275
|
+
|
|
276
|
+
@abc.abstractmethod
|
|
277
|
+
async def contains(self, key: str) -> bool:
|
|
278
|
+
"""Check if the cache contains a specific key."""
|
|
279
|
+
|
|
280
|
+
@abc.abstractmethod
|
|
281
|
+
async def get(self, key: str, /, default: VT | T | None = None) -> VT | T | None:
|
|
282
|
+
"""Get an item from the cache, returning default if the key does
|
|
283
|
+
not exist."""
|
|
284
|
+
|
|
285
|
+
@abc.abstractmethod
|
|
286
|
+
async def setdefault(self, key: str, default: VT | None = None, /) -> VT | None:
|
|
287
|
+
"""Set a default value for a key if it does not exist in the
|
|
288
|
+
cache."""
|
|
289
|
+
|
|
290
|
+
@abc.abstractmethod
|
|
291
|
+
async def clear(self) -> None:
|
|
292
|
+
"""Clear all items from the cache."""
|
|
293
|
+
|
|
294
|
+
@abc.abstractmethod
|
|
295
|
+
async def pop(self, key: str, /, default: VT | T | None = None) -> VT | T | None:
|
|
296
|
+
"""Remove and return an item from the cache by key."""
|
|
297
|
+
|
|
298
|
+
@abc.abstractmethod
|
|
299
|
+
async def popitem(self) -> tuple[str, VT]:
|
|
300
|
+
"""Remove and return an arbitrary (key, value) pair from the
|
|
301
|
+
cache."""
|
|
302
|
+
|
|
303
|
+
@abc.abstractmethod
|
|
304
|
+
async def set(self, key: str, value: VT) -> None:
|
|
305
|
+
"""Set an item in the cache with the specified key and value."""
|
|
306
|
+
|
|
307
|
+
@abc.abstractmethod
|
|
308
|
+
async def setx(self, key: str, value: VT, ttl: int | None = None) -> None:
|
|
309
|
+
"""Set an item in the cache with the specified key, value, and
|
|
310
|
+
optional TTL.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
key: Cache key.
|
|
314
|
+
value: Value to store.
|
|
315
|
+
ttl: Time-to-live in seconds. None means use default TTL.
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
@abc.abstractmethod
|
|
319
|
+
async def set_negative(self, key: str, /) -> None:
|
|
320
|
+
"""Store cache miss marker to prevent cache penetration.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
key: Cache key.
|
|
324
|
+
"""
|
|
325
|
+
|
|
326
|
+
@abc.abstractmethod
|
|
327
|
+
async def ttl(self, key: str) -> int | None:
|
|
328
|
+
"""Get the time-to-live (TTL) for a specific key in the cache.
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
key: Cache key.
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Remaining TTL in seconds, or None if no TTL is set.
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
@abc.abstractmethod
|
|
338
|
+
async def expire(self, key: str, ttl: int | None = None) -> None:
|
|
339
|
+
"""Set the time-to-live (TTL) for a specific key in the cache.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
key: Cache key.
|
|
343
|
+
ttl: Time-to-live in seconds. None means use default TTL.
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
@abc.abstractmethod
|
|
347
|
+
async def incr(self, key: str, amount: int = 1) -> int:
|
|
348
|
+
"""Increment the integer value of a key by the given amount.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
key: Cache key.
|
|
352
|
+
amount: Amount to increment by. Defaults to 1.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
The new value after incrementing.
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
@abc.abstractmethod
|
|
359
|
+
async def decr(self, key: str, amount: int = 1) -> int:
|
|
360
|
+
"""Decrement the integer value of a key by the given amount.
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
key: Cache key.
|
|
364
|
+
amount: Amount to decrement by. Defaults to 1.
|
|
365
|
+
|
|
366
|
+
Returns:
|
|
367
|
+
The new value after decrementing.
|
|
368
|
+
"""
|
|
369
|
+
|
|
370
|
+
@abc.abstractmethod
|
|
371
|
+
async def keys(self) -> list[str]:
|
|
372
|
+
"""Return a list of cache keys."""
|
|
373
|
+
|
|
374
|
+
@abc.abstractmethod
|
|
375
|
+
async def values(self) -> list[VT]:
|
|
376
|
+
"""Return all cache values."""
|
|
377
|
+
|
|
378
|
+
@abc.abstractmethod
|
|
379
|
+
async def items(self) -> list[tuple[str, VT]]:
|
|
380
|
+
"""Return all cache items as (key, value) pairs."""
|
|
381
|
+
|
|
382
|
+
def __repr__(self) -> str:
|
|
383
|
+
return f"ASYNC KV CACHE <{self.__class__.__name__}>"
|