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.
Files changed (192) hide show
  1. audex/__init__.py +9 -0
  2. audex/__main__.py +7 -0
  3. audex/cli/__init__.py +189 -0
  4. audex/cli/apis/__init__.py +12 -0
  5. audex/cli/apis/init/__init__.py +34 -0
  6. audex/cli/apis/init/gencfg.py +130 -0
  7. audex/cli/apis/init/setup.py +330 -0
  8. audex/cli/apis/init/vprgroup.py +125 -0
  9. audex/cli/apis/serve.py +141 -0
  10. audex/cli/args.py +356 -0
  11. audex/cli/exceptions.py +44 -0
  12. audex/cli/helper/__init__.py +0 -0
  13. audex/cli/helper/ansi.py +193 -0
  14. audex/cli/helper/display.py +288 -0
  15. audex/config/__init__.py +64 -0
  16. audex/config/core/__init__.py +30 -0
  17. audex/config/core/app.py +29 -0
  18. audex/config/core/audio.py +45 -0
  19. audex/config/core/logging.py +163 -0
  20. audex/config/core/session.py +11 -0
  21. audex/config/helper/__init__.py +1 -0
  22. audex/config/helper/client/__init__.py +1 -0
  23. audex/config/helper/client/http.py +28 -0
  24. audex/config/helper/client/websocket.py +21 -0
  25. audex/config/helper/provider/__init__.py +1 -0
  26. audex/config/helper/provider/dashscope.py +13 -0
  27. audex/config/helper/provider/unisound.py +18 -0
  28. audex/config/helper/provider/xfyun.py +23 -0
  29. audex/config/infrastructure/__init__.py +31 -0
  30. audex/config/infrastructure/cache.py +51 -0
  31. audex/config/infrastructure/database.py +48 -0
  32. audex/config/infrastructure/recorder.py +32 -0
  33. audex/config/infrastructure/store.py +19 -0
  34. audex/config/provider/__init__.py +18 -0
  35. audex/config/provider/transcription.py +109 -0
  36. audex/config/provider/vpr.py +99 -0
  37. audex/container.py +40 -0
  38. audex/entity/__init__.py +468 -0
  39. audex/entity/doctor.py +109 -0
  40. audex/entity/doctor.pyi +51 -0
  41. audex/entity/fields.py +401 -0
  42. audex/entity/segment.py +115 -0
  43. audex/entity/segment.pyi +38 -0
  44. audex/entity/session.py +133 -0
  45. audex/entity/session.pyi +47 -0
  46. audex/entity/utterance.py +142 -0
  47. audex/entity/utterance.pyi +48 -0
  48. audex/entity/vp.py +68 -0
  49. audex/entity/vp.pyi +35 -0
  50. audex/exceptions.py +157 -0
  51. audex/filters/__init__.py +692 -0
  52. audex/filters/generated/__init__.py +21 -0
  53. audex/filters/generated/doctor.py +987 -0
  54. audex/filters/generated/segment.py +723 -0
  55. audex/filters/generated/session.py +978 -0
  56. audex/filters/generated/utterance.py +939 -0
  57. audex/filters/generated/vp.py +815 -0
  58. audex/helper/__init__.py +1 -0
  59. audex/helper/hash.py +33 -0
  60. audex/helper/mixin.py +65 -0
  61. audex/helper/net.py +19 -0
  62. audex/helper/settings/__init__.py +830 -0
  63. audex/helper/settings/fields.py +317 -0
  64. audex/helper/stream.py +153 -0
  65. audex/injectors/__init__.py +1 -0
  66. audex/injectors/config.py +12 -0
  67. audex/injectors/lifespan.py +7 -0
  68. audex/lib/__init__.py +1 -0
  69. audex/lib/cache/__init__.py +383 -0
  70. audex/lib/cache/inmemory.py +513 -0
  71. audex/lib/database/__init__.py +83 -0
  72. audex/lib/database/sqlite.py +406 -0
  73. audex/lib/exporter.py +189 -0
  74. audex/lib/injectors/__init__.py +1 -0
  75. audex/lib/injectors/cache.py +25 -0
  76. audex/lib/injectors/container.py +47 -0
  77. audex/lib/injectors/exporter.py +26 -0
  78. audex/lib/injectors/recorder.py +33 -0
  79. audex/lib/injectors/server.py +17 -0
  80. audex/lib/injectors/session.py +18 -0
  81. audex/lib/injectors/sqlite.py +24 -0
  82. audex/lib/injectors/store.py +13 -0
  83. audex/lib/injectors/transcription.py +42 -0
  84. audex/lib/injectors/usb.py +12 -0
  85. audex/lib/injectors/vpr.py +65 -0
  86. audex/lib/injectors/wifi.py +7 -0
  87. audex/lib/recorder.py +844 -0
  88. audex/lib/repos/__init__.py +149 -0
  89. audex/lib/repos/container.py +23 -0
  90. audex/lib/repos/database/__init__.py +1 -0
  91. audex/lib/repos/database/sqlite.py +672 -0
  92. audex/lib/repos/decorators.py +74 -0
  93. audex/lib/repos/doctor.py +286 -0
  94. audex/lib/repos/segment.py +302 -0
  95. audex/lib/repos/session.py +285 -0
  96. audex/lib/repos/tables/__init__.py +70 -0
  97. audex/lib/repos/tables/doctor.py +137 -0
  98. audex/lib/repos/tables/segment.py +113 -0
  99. audex/lib/repos/tables/session.py +140 -0
  100. audex/lib/repos/tables/utterance.py +131 -0
  101. audex/lib/repos/tables/vp.py +102 -0
  102. audex/lib/repos/utterance.py +288 -0
  103. audex/lib/repos/vp.py +286 -0
  104. audex/lib/restful.py +251 -0
  105. audex/lib/server/__init__.py +97 -0
  106. audex/lib/server/auth.py +98 -0
  107. audex/lib/server/handlers.py +248 -0
  108. audex/lib/server/templates/index.html.j2 +226 -0
  109. audex/lib/server/templates/login.html.j2 +111 -0
  110. audex/lib/server/templates/static/script.js +68 -0
  111. audex/lib/server/templates/static/style.css +579 -0
  112. audex/lib/server/types.py +123 -0
  113. audex/lib/session.py +503 -0
  114. audex/lib/store/__init__.py +238 -0
  115. audex/lib/store/localfile.py +411 -0
  116. audex/lib/transcription/__init__.py +33 -0
  117. audex/lib/transcription/dashscope.py +525 -0
  118. audex/lib/transcription/events.py +62 -0
  119. audex/lib/usb.py +554 -0
  120. audex/lib/vpr/__init__.py +38 -0
  121. audex/lib/vpr/unisound/__init__.py +185 -0
  122. audex/lib/vpr/unisound/types.py +469 -0
  123. audex/lib/vpr/xfyun/__init__.py +483 -0
  124. audex/lib/vpr/xfyun/types.py +679 -0
  125. audex/lib/websocket/__init__.py +8 -0
  126. audex/lib/websocket/connection.py +485 -0
  127. audex/lib/websocket/pool.py +991 -0
  128. audex/lib/wifi.py +1146 -0
  129. audex/lifespan.py +75 -0
  130. audex/service/__init__.py +27 -0
  131. audex/service/decorators.py +73 -0
  132. audex/service/doctor/__init__.py +652 -0
  133. audex/service/doctor/const.py +36 -0
  134. audex/service/doctor/exceptions.py +96 -0
  135. audex/service/doctor/types.py +54 -0
  136. audex/service/export/__init__.py +236 -0
  137. audex/service/export/const.py +17 -0
  138. audex/service/export/exceptions.py +34 -0
  139. audex/service/export/types.py +21 -0
  140. audex/service/injectors/__init__.py +1 -0
  141. audex/service/injectors/container.py +53 -0
  142. audex/service/injectors/doctor.py +34 -0
  143. audex/service/injectors/export.py +27 -0
  144. audex/service/injectors/session.py +49 -0
  145. audex/service/session/__init__.py +754 -0
  146. audex/service/session/const.py +34 -0
  147. audex/service/session/exceptions.py +67 -0
  148. audex/service/session/types.py +91 -0
  149. audex/types.py +39 -0
  150. audex/utils.py +287 -0
  151. audex/valueobj/__init__.py +81 -0
  152. audex/valueobj/common/__init__.py +1 -0
  153. audex/valueobj/common/auth.py +84 -0
  154. audex/valueobj/common/email.py +16 -0
  155. audex/valueobj/common/ops.py +22 -0
  156. audex/valueobj/common/phone.py +84 -0
  157. audex/valueobj/common/version.py +72 -0
  158. audex/valueobj/session.py +19 -0
  159. audex/valueobj/utterance.py +15 -0
  160. audex/view/__init__.py +51 -0
  161. audex/view/container.py +17 -0
  162. audex/view/decorators.py +303 -0
  163. audex/view/pages/__init__.py +1 -0
  164. audex/view/pages/dashboard/__init__.py +286 -0
  165. audex/view/pages/dashboard/wifi.py +407 -0
  166. audex/view/pages/login.py +110 -0
  167. audex/view/pages/recording.py +348 -0
  168. audex/view/pages/register.py +202 -0
  169. audex/view/pages/sessions/__init__.py +196 -0
  170. audex/view/pages/sessions/details.py +224 -0
  171. audex/view/pages/sessions/export.py +443 -0
  172. audex/view/pages/settings.py +374 -0
  173. audex/view/pages/voiceprint/__init__.py +1 -0
  174. audex/view/pages/voiceprint/enroll.py +195 -0
  175. audex/view/pages/voiceprint/update.py +195 -0
  176. audex/view/static/css/dashboard.css +452 -0
  177. audex/view/static/css/glass.css +22 -0
  178. audex/view/static/css/global.css +541 -0
  179. audex/view/static/css/login.css +386 -0
  180. audex/view/static/css/recording.css +439 -0
  181. audex/view/static/css/register.css +293 -0
  182. audex/view/static/css/sessions/styles.css +501 -0
  183. audex/view/static/css/settings.css +186 -0
  184. audex/view/static/css/voiceprint/enroll.css +43 -0
  185. audex/view/static/css/voiceprint/styles.css +209 -0
  186. audex/view/static/css/voiceprint/update.css +44 -0
  187. audex/view/static/images/logo.svg +95 -0
  188. audex/view/static/js/recording.js +42 -0
  189. audex-1.0.7a3.dist-info/METADATA +361 -0
  190. audex-1.0.7a3.dist-info/RECORD +192 -0
  191. audex-1.0.7a3.dist-info/WHEEL +4 -0
  192. audex-1.0.7a3.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,317 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from pydantic.fields import FieldInfo
6
+ from pydantic.fields import _FieldInfoInputs
7
+ from pydantic_core import PydanticUndefined
8
+
9
+ from audex import __prog__
10
+ from audex.utils import Unset
11
+
12
+ P = t.ParamSpec("P")
13
+ T = t.TypeVar("T")
14
+
15
+
16
+ class AudexFieldInfo(FieldInfo): # type: ignore[misc]
17
+ """Extended FieldInfo with platform-specific default values.
18
+
19
+ This class extends Pydantic's FieldInfo to support platform-specific
20
+ default values and factories, enabling generation of OS-specific
21
+ configuration files.
22
+
23
+ Attributes:
24
+ linux_default: Default value for Linux systems
25
+ linux_default_factory: Factory function for Linux default values
26
+ windows_default: Default value for Windows systems
27
+ windows_default_factory: Factory function for Windows default values
28
+ system_default: Default value for system configuration
29
+ system_default_factory: Factory function for system default
30
+ system_path_type: Type of system path prefix (log, data, config, etc.)
31
+ """
32
+
33
+ __slots__ = (
34
+ *FieldInfo.__slots__,
35
+ "linux_default",
36
+ "linux_default_factory",
37
+ "windows_default",
38
+ "windows_default_factory",
39
+ "system_default",
40
+ "system_default_factory",
41
+ "system_path_type",
42
+ )
43
+
44
+ def __init__(
45
+ self,
46
+ linux_default: t.Any = PydanticUndefined,
47
+ linux_default_factory: t.Callable[[], t.Any] | None = None,
48
+ windows_default: t.Any = PydanticUndefined,
49
+ windows_default_factory: t.Callable[[], t.Any] | None = None,
50
+ system_default: t.Any = PydanticUndefined,
51
+ system_default_factory: t.Callable[[], t.Any] | None = None,
52
+ system_path_type: t.Literal["log", "data", "config", "cache", "runtime"] | None = None,
53
+ **kwargs: t.Unpack[_FieldInfoInputs],
54
+ ) -> None:
55
+ """Initialize AudexFieldInfo with platform-specific defaults.
56
+
57
+ Args:
58
+ linux_default: Default value for Linux systems
59
+ linux_default_factory: Factory function for Linux defaults
60
+ windows_default: Default value for Windows systems
61
+ windows_default_factory: Factory function for Windows defaults
62
+ system_default: Default value for system configuration
63
+ system_default_factory: Factory function for system default
64
+ system_path_type: Type of system path prefix
65
+ **kwargs: Keyword arguments passed to FieldInfo
66
+ """
67
+ super().__init__(**kwargs)
68
+
69
+ self.linux_default = linux_default
70
+ self.linux_default_factory = linux_default_factory
71
+ self.windows_default = windows_default
72
+ self.windows_default_factory = windows_default_factory
73
+ self.system_default = system_default
74
+ self.system_default_factory = system_default_factory
75
+ self.system_path_type = system_path_type
76
+
77
+ def get_platform_default(self, platform: str) -> t.Any:
78
+ """Get the default value for the specified platform.
79
+
80
+ Priority:
81
+ 1. Platform-specific factory (linux_default_factory/windows_default_factory)
82
+ 2. System path prefix + system_default (if system_path_type is set)
83
+ 3. Standard default
84
+
85
+ Args:
86
+ platform: Target platform ("linux" or "windows").
87
+
88
+ Returns:
89
+ Platform-specific default value, or PydanticUndefined if not set.
90
+ """
91
+ # Step 1: Try platform-specific factory/value
92
+ platform_value = self._get_platform_specific_value(platform)
93
+
94
+ # If found, join with system path if needed and return
95
+ if platform_value is not PydanticUndefined and not isinstance(platform_value, Unset):
96
+ return self._join_with_system_path(platform_value, platform)
97
+ if isinstance(platform_value, Unset):
98
+ return platform_value
99
+
100
+ # Step 2: Try system_default with system_path_type
101
+ if self.system_path_type is not None:
102
+ system_value = self._get_system_default()
103
+ if system_value is not PydanticUndefined:
104
+ return self._join_with_system_path(system_value, platform)
105
+
106
+ # Step 3: Fallback to standard default
107
+ if self.default_factory is not None:
108
+ return self.default_factory()
109
+ if self.default is not PydanticUndefined:
110
+ return self.default
111
+
112
+ return PydanticUndefined
113
+
114
+ def _get_platform_specific_value(self, platform: str) -> t.Any:
115
+ """Get platform-specific value (factory or direct).
116
+
117
+ Args:
118
+ platform: Target platform.
119
+
120
+ Returns:
121
+ Platform-specific value or PydanticUndefined.
122
+ """
123
+ if platform == "linux":
124
+ if self.linux_default_factory is not None:
125
+ return self.linux_default_factory()
126
+ if self.linux_default is not PydanticUndefined:
127
+ return self.linux_default
128
+ elif platform == "windows":
129
+ if self.windows_default_factory is not None:
130
+ return self.windows_default_factory()
131
+ if self.windows_default is not PydanticUndefined:
132
+ return self.windows_default
133
+
134
+ return PydanticUndefined
135
+
136
+ def _get_system_default(self) -> t.Any:
137
+ """Get system default value (factory or direct).
138
+
139
+ Returns:
140
+ System default value or PydanticUndefined.
141
+ """
142
+ if self.system_default_factory is not None:
143
+ return self.system_default_factory()
144
+ if self.system_default is not PydanticUndefined:
145
+ return self.system_default
146
+
147
+ return PydanticUndefined
148
+
149
+ def _get_system_path_prefix(self, platform: str) -> str | None:
150
+ """Get the system path prefix for the specified platform.
151
+
152
+ Args:
153
+ platform: Target platform.
154
+
155
+ Returns:
156
+ System path prefix string, or None if system_path_type not set.
157
+ """
158
+ if self.system_path_type is None:
159
+ return None
160
+
161
+ app_name = __prog__
162
+
163
+ # Linux FHS (Filesystem Hierarchy Standard) paths
164
+ if platform == "linux":
165
+ if self.system_path_type == "log":
166
+ return f"${{HOME}}/.local/share/{app_name}/logs"
167
+ if self.system_path_type == "data":
168
+ return f"${{HOME}}/.local/share/{app_name}"
169
+ if self.system_path_type == "config":
170
+ return f"${{HOME}}/.config/{app_name}"
171
+ if self.system_path_type == "cache":
172
+ return f"${{HOME}}/.cache/{app_name}"
173
+ if self.system_path_type == "runtime":
174
+ return f"${{HOME}}/.cache/{app_name}/runtime"
175
+
176
+ # Windows standard paths
177
+ elif platform == "windows":
178
+ if self.system_path_type == "log":
179
+ return f"%PROGRAMDATA%\\{app_name}\\logs"
180
+ if self.system_path_type == "data":
181
+ return f"%PROGRAMDATA%\\{app_name}\\data"
182
+ if self.system_path_type == "config":
183
+ return f"%PROGRAMDATA%\\{app_name}\\config"
184
+ if self.system_path_type == "cache":
185
+ return f"%LOCALAPPDATA%\\{app_name}\\cache"
186
+ if self.system_path_type == "runtime":
187
+ return f"%TEMP%\\{app_name}"
188
+
189
+ return None
190
+
191
+ def _join_with_system_path(self, value: t.Any, platform: str) -> t.Any:
192
+ """Join value with system path prefix if applicable.
193
+
194
+ Args:
195
+ value: Value to join.
196
+ platform: Target platform.
197
+
198
+ Returns:
199
+ Joined path or original value.
200
+ """
201
+ if self.system_path_type is None or value is PydanticUndefined:
202
+ return value
203
+
204
+ prefix = self._get_system_path_prefix(platform)
205
+ if prefix is None:
206
+ return value
207
+
208
+ # Only join string values
209
+ if isinstance(value, str):
210
+ separator = "/" if platform == "linux" else "\\"
211
+ # Avoid double separators
212
+ if not prefix.endswith(("/", "\\")):
213
+ prefix += separator
214
+ return prefix + value
215
+
216
+ return value
217
+
218
+
219
+ def Field( # noqa
220
+ default: t.Any = PydanticUndefined,
221
+ *,
222
+ default_factory: t.Callable[[], t.Any] | None = None,
223
+ linux_default: t.Any = PydanticUndefined,
224
+ linux_default_factory: t.Callable[[], t.Any] | None = None,
225
+ windows_default: t.Any = PydanticUndefined,
226
+ windows_default_factory: t.Callable[[], t.Any] | None = None,
227
+ system_default: t.Any = PydanticUndefined,
228
+ system_default_factory: t.Callable[[], t.Any] | None = None,
229
+ system_path_type: t.Literal["log", "data", "config", "cache", "runtime"] | None = None,
230
+ alias: str | None = None,
231
+ title: str | None = None,
232
+ description: str | None = None,
233
+ **kwargs: t.Any,
234
+ ) -> t.Any:
235
+ """Create a system-aware configuration field descriptor.
236
+
237
+ This function creates a field descriptor that supports platform-specific
238
+ default values and automatic system path prefix joining.
239
+
240
+ Value resolution priority for system configuration:
241
+ 1. Platform-specific factory/value (linux_default_factory/windows_default_factory)
242
+ 2. System default + system path prefix (system_default + system_path_type)
243
+ 3. Standard default (default/default_factory)
244
+
245
+ Args:
246
+ default: Default value for all platforms
247
+ default_factory: Factory function for default value
248
+ linux_default: Default value specific to Linux
249
+ linux_default_factory: Factory function for Linux default
250
+ windows_default: Default value specific to Windows
251
+ windows_default_factory: Factory function for Windows default
252
+ system_default: Default value for system configuration
253
+ system_default_factory: Factory function for system default
254
+ system_path_type: Type of system path prefix (log, data, config, cache, runtime)
255
+ alias: Field alias
256
+ title: Field title
257
+ description: Field description
258
+ **kwargs: Additional arguments passed to FieldInfo
259
+
260
+ Returns:
261
+ AudexFieldInfo instance
262
+
263
+ Examples:
264
+ ```python
265
+ from audex.helper.settings.fields import Field
266
+
267
+
268
+ class LoggingConfig(BaseModel):
269
+ # Platform-specific with system path
270
+ # Linux: /var/log/audex/app. log
271
+ # Windows: %PROGRAMDATA%\\audex\\logs\\app.log
272
+ log_file: str = Field(
273
+ linux_default="app.log",
274
+ windows_default="app.log",
275
+ system_path_type="log",
276
+ description="Log file path",
277
+ )
278
+
279
+ # System default with path prefix
280
+ # Linux: /var/lib/audex/audex.db
281
+ # Windows: %PROGRAMDATA%\\audex\\data\\audex.db
282
+ db_path: str = Field(
283
+ system_default="audex.db",
284
+ system_path_type="data",
285
+ description="Database file path",
286
+ )
287
+
288
+ # Platform-specific without system path
289
+ native: bool = Field(
290
+ linux_default=True,
291
+ windows_default=False,
292
+ description="Use native mode",
293
+ )
294
+
295
+ # Full control without system path
296
+ custom_path: str = Field(
297
+ linux_default="/custom/path/file.txt",
298
+ windows_default="C:\\custom\\path\\file.txt",
299
+ description="Custom path",
300
+ )
301
+ ```
302
+ """
303
+ return AudexFieldInfo(
304
+ default=default,
305
+ default_factory=default_factory,
306
+ linux_default=linux_default,
307
+ linux_default_factory=linux_default_factory,
308
+ windows_default=windows_default,
309
+ windows_default_factory=windows_default_factory,
310
+ system_default=system_default,
311
+ system_default_factory=system_default_factory,
312
+ system_path_type=system_path_type,
313
+ alias=alias,
314
+ title=title,
315
+ description=description,
316
+ **kwargs,
317
+ )
audex/helper/stream.py ADDED
@@ -0,0 +1,153 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ _T = t.TypeVar("_T")
6
+ _U = t.TypeVar("_U")
7
+ _V = t.TypeVar("_V")
8
+
9
+
10
+ class AsyncStream(t.AsyncIterable[_T], t.Generic[_T]):
11
+ def __init__(self, source: t.AsyncIterable[_V], mapper: t.Callable[[_V], _T] | None = None):
12
+ self._source = source
13
+ self._mapper = mapper
14
+ self._is_consumed = False
15
+ self._items = [] # type: t.List[_T]
16
+ self._error = None # type: t.Optional[Exception]
17
+ self._completed = False
18
+ self._iterator = None # type: t.Optional[t.AsyncIterator[_T]]
19
+
20
+ async def __aiter__(self) -> t.AsyncIterator[_T]: # pylint: disable=invalid-overridden-method
21
+ if self._is_consumed:
22
+ # If the stream has already been consumed, return the cached items
23
+ for item in self._items:
24
+ yield item
25
+ return
26
+
27
+ self._is_consumed = True
28
+ try:
29
+ async for raw_item in self._source:
30
+ item = self._mapper(raw_item) if self._mapper else t.cast(_T, raw_item)
31
+
32
+ self._items.append(item)
33
+ yield item
34
+
35
+ except Exception as e:
36
+ self._error = e
37
+ raise
38
+ finally:
39
+ self._completed = True
40
+
41
+ async def __anext__(self) -> _T:
42
+ if not hasattr(self, "_iterator") or self._iterator is None:
43
+ self._iterator = self.__aiter__()
44
+ return await self._iterator.__anext__()
45
+
46
+ def filter(self, predicate: t.Callable[[_T], bool]) -> AsyncStream[_T]:
47
+ async def filtered_source() -> t.AsyncIterator[_T]:
48
+ async for item in self:
49
+ if predicate(item):
50
+ yield item
51
+
52
+ return AsyncStream(filtered_source())
53
+
54
+ def tap(self, action: t.Callable[[_T], None]) -> AsyncStream[_T]:
55
+ async def tap_source() -> t.AsyncIterator[_T]:
56
+ async for item in self:
57
+ action(item)
58
+ yield item
59
+
60
+ return AsyncStream(tap_source())
61
+
62
+ def map(self, mapper: t.Callable[[_T], _U]) -> AsyncStream[_U]:
63
+ async def mapped_source() -> t.AsyncIterator[_U]:
64
+ async for item in self:
65
+ yield mapper(item)
66
+
67
+ return AsyncStream(mapped_source())
68
+
69
+ def take(self, n: int, /) -> AsyncStream[_T]:
70
+ async def take_source() -> t.AsyncIterator[_T]:
71
+ count = 0
72
+ async for item in self:
73
+ if count >= n:
74
+ break
75
+ yield item
76
+ count += 1
77
+
78
+ return AsyncStream(take_source())
79
+
80
+ def skip(self, n: int, /) -> AsyncStream[_T]:
81
+ async def skip_source() -> t.AsyncIterator[_T]:
82
+ count = 0
83
+ async for item in self:
84
+ if count < n:
85
+ count += 1
86
+ continue
87
+ yield item
88
+
89
+ return AsyncStream(skip_source())
90
+
91
+ def chunk(self, size: int) -> AsyncStream[list[_T]]:
92
+ async def chunk_source() -> t.AsyncIterator[list[_T]]:
93
+ batch = []
94
+ async for item in self:
95
+ batch.append(item)
96
+ if len(batch) >= size:
97
+ yield batch
98
+ batch = []
99
+ if batch:
100
+ yield batch
101
+
102
+ return AsyncStream(chunk_source())
103
+
104
+ def take_while(self, predicate: t.Callable[[_T], bool]) -> AsyncStream[_T]:
105
+ async def take_while_source() -> t.AsyncIterator[_T]:
106
+ async for item in self:
107
+ if not predicate(item):
108
+ break
109
+ yield item
110
+
111
+ return AsyncStream(take_while_source())
112
+
113
+ def enumerate(self, start: int = 0) -> AsyncStream[tuple[int, _T]]:
114
+ async def enumerate_source() -> t.AsyncIterator[tuple[int, _T]]:
115
+ index = start
116
+ async for item in self:
117
+ yield index, item
118
+ index += 1
119
+
120
+ return AsyncStream(enumerate_source())
121
+
122
+ async def foreach(self, action: t.Callable[[_T], t.Awaitable[None]], /) -> None:
123
+ async for item in self:
124
+ await action(item)
125
+
126
+ async def reduce(self, func: t.Callable[[_U, _T], _U], initial: _U) -> _U:
127
+ result = initial
128
+ async for item in self:
129
+ result = func(result, item)
130
+ return result
131
+
132
+ async def all(self, predicate: t.Callable[[_T], bool] | None = None, /) -> bool:
133
+ if predicate is None:
134
+
135
+ def predicate(v: _T) -> bool:
136
+ return bool(v)
137
+
138
+ async for item in self:
139
+ if not predicate(item):
140
+ return False
141
+ return True
142
+
143
+ @property
144
+ def is_completed(self) -> bool:
145
+ return self._completed
146
+
147
+ @property
148
+ def error(self) -> Exception | None:
149
+ return self._error
150
+
151
+ @property
152
+ def items_count(self) -> int:
153
+ return len(self._items)
@@ -0,0 +1 @@
1
+ from __future__ import annotations
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.config import Config
4
+ from audex.config import build_config
5
+ from audex.config import getconfig
6
+
7
+
8
+ def config() -> Config:
9
+ try:
10
+ return getconfig()
11
+ except RuntimeError:
12
+ return build_config()
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from audex.lifespan import LifeSpan
4
+
5
+
6
+ def lifespan(*args: object) -> LifeSpan:
7
+ return LifeSpan(*args)
audex/lib/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from __future__ import annotations