omlish 0.0.0.dev418__py3-none-any.whl → 0.0.0.dev420__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev418'
2
- __revision__ = '768aa72e47d914554932c2598e2f832465969997'
1
+ __version__ = '0.0.0.dev420'
2
+ __revision__ = '513bbdf392274f50320eb9577bd88bc0a683e1a5'
3
3
 
4
4
 
5
5
  #
omlish/configs/all.py CHANGED
@@ -1,47 +1,54 @@
1
- # ruff: noqa: I001
2
- from .classes import ( # noqa
3
- Configurable,
4
- )
1
+ # rufF: noqa: I001
2
+ from .. import lang as _lang
5
3
 
6
- from .formats import ( # noqa
7
- ConfigData as Data,
8
4
 
9
- ConfigLoader as Loader,
5
+ with _lang.auto_proxy_init(globals()):
6
+ ##
10
7
 
11
- ConfigRenderer as Renderer,
8
+ from .classes import ( # noqa
9
+ Configurable,
10
+ )
12
11
 
13
- ObjConfigData as ObjData,
12
+ from .formats import ( # noqa
13
+ ConfigData as Data,
14
14
 
15
- JsonConfigData as JsonData,
16
- JsonConfigLoader as JsonLoader,
17
- JsonConfigRenderer as JsonRenderer,
15
+ ConfigLoader as Loader,
18
16
 
19
- TomlConfigData as TomlData,
20
- TomlConfigLoader as TomlLoader,
21
- TomlConfigRenderer as TomlRenderer,
17
+ ConfigRenderer as Renderer,
22
18
 
23
- YamlConfigData as YamlData,
24
- YamlConfigLoader as YamlLoader,
25
- YamlConfigRenderer as YamlRenderer,
19
+ ObjConfigData as ObjData,
26
20
 
27
- IniConfigData as IniData,
28
- IniConfigLoader as IniLoader,
29
- IniConfigRenderer as IniRenderer,
21
+ JsonConfigData as JsonData,
22
+ JsonConfigLoader as JsonLoader,
23
+ JsonConfigRenderer as JsonRenderer,
30
24
 
31
- SwitchedConfigFileLoader as SwitchedFileLoader,
25
+ TomlConfigData as TomlData,
26
+ TomlConfigLoader as TomlLoader,
27
+ TomlConfigRenderer as TomlRenderer,
32
28
 
33
- DEFAULT_CONFIG_LOADERS as DEFAULT_LOADERS,
34
- DEFAULT_CONFIG_LOADER as DEFAULT_LOADER,
35
- DEFAULT_CONFIG_FILE_LOADER as DEFAULT_FILE_LOADER,
29
+ YamlConfigData as YamlData,
30
+ YamlConfigLoader as YamlLoader,
31
+ YamlConfigRenderer as YamlRenderer,
36
32
 
37
- SwitchedConfigRenderer as SwitchedRenderer,
33
+ IniConfigData as IniData,
34
+ IniConfigLoader as IniLoader,
35
+ IniConfigRenderer as IniRenderer,
38
36
 
39
- DEFAULT_CONFIG_RENDERERS as DEFAULT_RENDERERS,
40
- DEFAULT_CONFIG_RENDERER as DEFAULT_RENDERER,
41
- )
37
+ SwitchedConfigFileLoader as SwitchedFileLoader,
38
+
39
+ DEFAULT_CONFIG_LOADERS as DEFAULT_LOADERS,
40
+ DEFAULT_CONFIG_LOADER as DEFAULT_LOADER,
41
+ DEFAULT_CONFIG_FILE_LOADER as DEFAULT_FILE_LOADER,
42
+
43
+ SwitchedConfigRenderer as SwitchedRenderer,
44
+
45
+ DEFAULT_CONFIG_RENDERERS as DEFAULT_RENDERERS,
46
+ DEFAULT_CONFIG_RENDERER as DEFAULT_RENDERER,
47
+ )
48
+
49
+ from .types import ( # noqa
50
+ ConfigMap as Map,
51
+ )
42
52
 
43
- from .types import ( # noqa
44
- ConfigMap as Map,
45
- )
46
53
 
47
54
  from .processing import all as processing # noqa
@@ -1,37 +1,43 @@
1
1
  # ruff: noqa: I001
2
- from .flattening import ( # noqa
3
- ConfigFlattening as Flattening,
4
- )
2
+ from ... import lang as _lang
5
3
 
6
- from .inheritance import ( # noqa
7
- build_config_inherited_values as build_inherited_values,
8
- )
9
4
 
10
- from .matching import ( # noqa
11
- MatchingConfigRewriter as MatchingRewriter,
5
+ with _lang.auto_proxy_init(globals()):
6
+ ##
12
7
 
13
- matched_config_rewrite as matched_rewrite,
14
- )
8
+ from .flattening import ( # noqa
9
+ ConfigFlattening as Flattening,
10
+ )
15
11
 
16
- from .merging import ( # noqa
17
- merge_configs as merge,
18
- )
12
+ from .inheritance import ( # noqa
13
+ build_config_inherited_values as build_inherited_values,
14
+ )
19
15
 
20
- from .names import ( # noqa
21
- build_config_named_children as build_named_children,
22
- )
16
+ from .matching import ( # noqa
17
+ MatchingConfigRewriter as MatchingRewriter,
23
18
 
24
- from .rewriting import ( # noqa
25
- ConfigRewriterItem as RewriterItem,
26
- ConfigRewriterPath as RewriterPath,
19
+ matched_config_rewrite as matched_rewrite,
20
+ )
27
21
 
28
- RawConfigMetadata as RawMetadata,
22
+ from .merging import ( # noqa
23
+ merge_configs as merge,
24
+ )
29
25
 
30
- ConfigRewriter as Rewriter,
31
- )
26
+ from .names import ( # noqa
27
+ build_config_named_children as build_named_children,
28
+ )
32
29
 
33
- from .strings import ( # noqa
34
- StringConfigRewriter as StringRewriter,
30
+ from .rewriting import ( # noqa
31
+ ConfigRewriterItem as RewriterItem,
32
+ ConfigRewriterPath as RewriterPath,
35
33
 
36
- format_config_strings as format_strings,
37
- )
34
+ RawConfigMetadata as RawMetadata,
35
+
36
+ ConfigRewriter as Rewriter,
37
+ )
38
+
39
+ from .strings import ( # noqa
40
+ StringConfigRewriter as StringRewriter,
41
+
42
+ format_config_strings as format_strings,
43
+ )
@@ -94,7 +94,7 @@ class Launcher:
94
94
  if (pid_file := self._pid_file) is not None:
95
95
  if not isinstance(spawner, InProcessSpawner):
96
96
  pidfile = es.enter_context(open_inheritable_pidfile(pid_file))
97
- pidfile_manager = lang.NopContextManager(pidfile)
97
+ pidfile_manager = lang.ValueContextManager(pidfile)
98
98
 
99
99
  else:
100
100
  check.state(not self._reparent_process)
@@ -2,9 +2,15 @@ import typing as ta
2
2
 
3
3
  from .... import lang
4
4
  from .base import Backend
5
- from .orjson import orjson_backend
6
5
  from .std import std_backend
7
- from .ujson import ujson_backend
6
+
7
+
8
+ if ta.TYPE_CHECKING:
9
+ from . import orjson as oj
10
+ from . import ujson as uj
11
+ else:
12
+ oj = lang.proxy_import('.orjson', __package__)
13
+ uj = lang.proxy_import('.ujson', __package__)
8
14
 
9
15
 
10
16
  ##
@@ -12,12 +18,13 @@ from .ujson import ujson_backend
12
18
 
13
19
  @lang.cached_function
14
20
  def default_backend() -> Backend:
15
- for fn in [
16
- orjson_backend,
17
- ujson_backend,
21
+ for (im, bm, fn) in [
22
+ ('orjson', oj, 'orjson_backend'),
23
+ ('ujson', uj, 'ujson_backend'),
18
24
  ]:
19
- if (be := fn()) is not None:
20
- return be
25
+ if lang.can_import(im):
26
+ if (be := getattr(bm, fn)()) is not None:
27
+ return be
21
28
 
22
29
  return std_backend()
23
30
 
@@ -48,6 +48,7 @@ class Options:
48
48
 
49
49
  ##
50
50
 
51
+ @lang.cached_function
51
52
  def __int__(self) -> int:
52
53
  return (
53
54
  (oj.OPT_APPEND_NEWLINE if self.append_newline else 0) |
@@ -49,8 +49,8 @@ import types
49
49
  import typing as ta
50
50
 
51
51
 
52
- TomlParseFloat = ta.Callable[[str], ta.Any]
53
- TomlKey = ta.Tuple[str, ...]
52
+ TomlParseFloat = ta.Callable[[str], ta.Any] # ta.TypeAlias
53
+ TomlKey = ta.Tuple[str, ...] # ta.TypeAlias
54
54
  TomlPos = int # ta.TypeAlias
55
55
 
56
56
 
omlish/lang/__init__.py CHANGED
@@ -145,22 +145,42 @@ with _auto_proxy_init(
145
145
  )
146
146
 
147
147
  from .contextmanagers import ( # noqa
148
- AsyncContextManager,
149
148
  ContextManaged,
150
- ContextManager,
151
- ContextWrapped,
152
- DefaultLockable,
153
- Lockable,
149
+ SelfContextManaged,
150
+ ValueContextManager,
154
151
  NOP_CONTEXT_MANAGER,
155
- NopContextManager,
156
- Timer,
152
+
153
+ AsyncContextManaged,
154
+ SelfAsyncContextManaged,
155
+ ValueAsyncContextManager,
156
+ NOP_ASYNC_CONTEXT_MANAGER,
157
+
158
+ AsyncContextManager,
159
+
160
+ ContextManager,
161
+
162
+ maybe_managing,
163
+ disposing,
157
164
  breakpoint_on_exception,
158
165
  context_var_setting,
166
+
167
+ as_async_context_manager,
168
+
169
+ ContextWrappable,
170
+ ContextWrapped,
159
171
  context_wrapped,
172
+
173
+ Lockable,
174
+ DefaultLockable,
160
175
  default_lock,
161
- disposing,
176
+
177
+ AsyncLockable,
178
+ DefaultAsyncLockable,
179
+ default_async_lock,
180
+
181
+ Timer,
182
+
162
183
  double_check_setdefault,
163
- maybe_managing,
164
184
  )
165
185
 
166
186
  from .datetimes import ( # noqa
@@ -297,7 +317,7 @@ with _auto_proxy_init(
297
317
  just,
298
318
  )
299
319
 
300
- from .maysyncs import ( # noqa
320
+ from .maysync import ( # noqa
301
321
  make_maysync_fn,
302
322
  make_maysync_generator_fn,
303
323
  make_maysync,
@@ -439,7 +459,7 @@ with _auto_proxy_init(
439
459
  Maybe,
440
460
  )
441
461
 
442
- from ..lite.maysyncs import ( # noqa
462
+ from ..lite.maysync import ( # noqa
443
463
  mark_maysync,
444
464
  is_maysync,
445
465
 
@@ -2,6 +2,7 @@
2
2
  TODO:
3
3
  - AsyncExitStacked
4
4
  - lol does double_check_setdefault need a CowDict in FT?
5
+ - AsyncLockable, DefaultAsyncLockable
5
6
  """
6
7
  import abc
7
8
  import contextlib
@@ -21,16 +22,45 @@ V = ta.TypeVar('V')
21
22
  ##
22
23
 
23
24
 
24
- class _NOT_SET: # noqa
25
- def __new__(cls, *args, **kwargs): # noqa
26
- raise TypeError
25
+ class ContextManaged(abc.ABC): # noqa
26
+ def __enter__(self):
27
+ return None
28
+
29
+ def __exit__(
30
+ self,
31
+ exc_type: type[BaseException] | None,
32
+ exc_val: BaseException | None,
33
+ exc_tb: types.TracebackType | None,
34
+ ) -> bool | None:
35
+ return None
27
36
 
28
37
 
29
- class ContextManaged:
38
+ class SelfContextManaged(ContextManaged):
30
39
  def __enter__(self) -> ta.Self:
31
40
  return self
32
41
 
33
- def __exit__(
42
+
43
+ class ValueContextManager(ContextManaged, ta.Generic[T]):
44
+ def __init__(self, value: T) -> None:
45
+ super().__init__()
46
+
47
+ self._value = value
48
+
49
+ def __enter__(self) -> T:
50
+ return self._value
51
+
52
+
53
+ NOP_CONTEXT_MANAGER = ValueContextManager(None)
54
+
55
+
56
+ #
57
+
58
+
59
+ class AsyncContextManaged(abc.ABC): # noqa
60
+ async def __aenter__(self):
61
+ return None
62
+
63
+ async def __aexit__(
34
64
  self,
35
65
  exc_type: type[BaseException] | None,
36
66
  exc_val: BaseException | None,
@@ -39,23 +69,22 @@ class ContextManaged:
39
69
  return None
40
70
 
41
71
 
42
- class NopContextManager(ContextManaged):
43
- def __init__(self, /, value: ta.Any = _NOT_SET) -> None:
72
+ class SelfAsyncContextManaged(AsyncContextManaged):
73
+ async def __aenter__(self) -> ta.Self:
74
+ return self
75
+
76
+
77
+ class ValueAsyncContextManager(AsyncContextManaged, ta.Generic[T]):
78
+ def __init__(self, value: T) -> None:
44
79
  super().__init__()
45
80
 
46
81
  self._value = value
47
82
 
48
- def __enter__(self):
49
- if (value := self._value) is _NOT_SET:
50
- return self
51
- else:
52
- return value
53
-
54
- def __init_subclass__(cls, **kwargs: ta.Any) -> None:
55
- raise TypeError
83
+ async def __aenter__(self) -> T:
84
+ return self._value
56
85
 
57
86
 
58
- NOP_CONTEXT_MANAGER = NopContextManager()
87
+ NOP_ASYNC_CONTEXT_MANAGER = ValueAsyncContextManager(None)
59
88
 
60
89
 
61
90
  ##
@@ -90,6 +119,9 @@ class ContextManager(abc.ABC, ta.Generic[T]):
90
119
  return self._contextmanager.__exit__(exc_type, exc_val, exc_tb)
91
120
 
92
121
 
122
+ #
123
+
124
+
93
125
  class AsyncContextManager(abc.ABC, ta.Generic[T]):
94
126
  def __init_subclass__(cls, **kwargs: ta.Any) -> None:
95
127
  super().__init_subclass__(**kwargs)
@@ -160,6 +192,15 @@ def context_var_setting(var: contextvars.ContextVar[T], val: T) -> ta.Iterator[T
160
192
  ##
161
193
 
162
194
 
195
+ @contextlib.asynccontextmanager
196
+ async def as_async_context_manager(cm: ta.ContextManager[T]) -> ta.AsyncIterator[T]:
197
+ with cm as v:
198
+ yield v
199
+
200
+
201
+ ##
202
+
203
+
163
204
  ContextWrappable: ta.TypeAlias = ta.ContextManager | str | ta.Callable[..., ta.ContextManager]
164
205
 
165
206
 
@@ -257,6 +298,30 @@ def default_lock(value: DefaultLockable, default: DefaultLockable = None) -> Loc
257
298
  raise TypeError(value)
258
299
 
259
300
 
301
+ #
302
+
303
+
304
+ AsyncLockable = ta.Callable[[], ta.AsyncContextManager]
305
+ DefaultAsyncLockable = AsyncLockable | ta.AsyncContextManager | None
306
+
307
+
308
+ def default_async_lock(value: DefaultAsyncLockable, default: DefaultAsyncLockable = None) -> AsyncLockable:
309
+ if value is None:
310
+ value = default
311
+
312
+ if value is None:
313
+ return lambda: NOP_ASYNC_CONTEXT_MANAGER
314
+
315
+ elif callable(value):
316
+ return value
317
+
318
+ elif isinstance(value, ta.AsyncContextManager):
319
+ return lambda: value
320
+
321
+ else:
322
+ raise TypeError(value)
323
+
324
+
260
325
  ##
261
326
 
262
327
 
@@ -512,8 +512,8 @@ class AutoProxyInit:
512
512
  self,
513
513
  init_globals: ta.MutableMapping[str, ta.Any],
514
514
  *,
515
- disable: bool,
516
- eager: bool,
515
+ disable: bool = False,
516
+ eager: bool = False,
517
517
  ) -> None:
518
518
  super().__init__()
519
519
 
@@ -1,8 +1,8 @@
1
1
  import typing as ta
2
2
 
3
- from ..lite.maysyncs import MaysyncFn
4
- from ..lite.maysyncs import MaysyncGeneratorFn
5
- from ..lite.maysyncs import make_maysync as _make_maysync
3
+ from ..lite.maysync import MaysyncFn
4
+ from ..lite.maysync import MaysyncGeneratorFn
5
+ from ..lite.maysync import make_maysync as _make_maysync
6
6
  from .functions import as_async
7
7
 
8
8
 
@@ -1,11 +1,21 @@
1
1
  from .abstract import ( # noqa
2
2
  AbstractLifecycle,
3
+
4
+ AbstractAsyncLifecycle,
3
5
  )
4
6
 
5
7
  from .base import ( # noqa
8
+ AnyLifecycleCallback,
9
+ AnyLifecycle,
10
+ AnyCallbackLifecycle,
11
+
12
+ LifecycleCallback,
6
13
  CallbackLifecycle,
7
14
  Lifecycle,
8
- LifecycleCallback,
15
+
16
+ AsyncLifecycleCallback,
17
+ CallbackAsyncLifecycle,
18
+ AsyncLifecycle,
9
19
  )
10
20
 
11
21
  from .contextmanagers import ( # noqa
@@ -14,6 +24,9 @@ from .contextmanagers import ( # noqa
14
24
  )
15
25
 
16
26
  from .controller import ( # noqa
27
+ AnyLifecycleListener,
28
+ AnyLifecycleController,
29
+
17
30
  LifecycleController,
18
31
  LifecycleListener,
19
32
  )
@@ -3,11 +3,14 @@ import typing as ta
3
3
  from .. import cached
4
4
  from .. import dataclasses as dc
5
5
  from .. import lang
6
+ from .base import AsyncLifecycle
6
7
  from .base import Lifecycle
7
8
 
8
9
 
9
10
  AbstractLifecycleT = ta.TypeVar('AbstractLifecycleT', bound='AbstractLifecycle')
10
11
 
12
+ AbstractAsyncLifecycleT = ta.TypeVar('AbstractAsyncLifecycleT', bound='AbstractAsyncLifecycle')
13
+
11
14
 
12
15
  ##
13
16
 
@@ -44,3 +47,40 @@ class AbstractLifecycle(lang.Abstract):
44
47
 
45
48
  def _lifecycle_destroy(self) -> None:
46
49
  pass
50
+
51
+
52
+ ##
53
+
54
+
55
+ class AbstractAsyncLifecycle(lang.Abstract):
56
+ @dc.dataclass(frozen=True)
57
+ class _Lifecycle(AsyncLifecycle, lang.Final, ta.Generic[AbstractAsyncLifecycleT]):
58
+ obj: AbstractAsyncLifecycleT
59
+
60
+ async def lifecycle_construct(self) -> None:
61
+ await self.obj._lifecycle_construct() # noqa
62
+
63
+ async def lifecycle_start(self) -> None:
64
+ await self.obj._lifecycle_start() # noqa
65
+
66
+ async def lifecycle_stop(self) -> None:
67
+ await self.obj._lifecycle_stop() # noqa
68
+
69
+ async def lifecycle_destroy(self) -> None:
70
+ await self.obj._lifecycle_destroy() # noqa
71
+
72
+ @cached.property
73
+ def _lifecycle(self) -> _Lifecycle[ta.Self]:
74
+ return AbstractAsyncLifecycle._Lifecycle(self)
75
+
76
+ async def _lifecycle_construct(self) -> None:
77
+ pass
78
+
79
+ async def _lifecycle_start(self) -> None:
80
+ pass
81
+
82
+ async def _lifecycle_stop(self) -> None:
83
+ pass
84
+
85
+ async def _lifecycle_destroy(self) -> None:
86
+ pass
omlish/lifecycles/base.py CHANGED
@@ -4,50 +4,100 @@ from .. import dataclasses as dc
4
4
  from .. import lang
5
5
 
6
6
 
7
+ R = ta.TypeVar('R')
8
+
9
+ AnyLifecycleT = ta.TypeVar('AnyLifecycleT', bound='AnyLifecycle')
10
+ AnyLifecycleCallback: ta.TypeAlias = ta.Callable[[AnyLifecycleT], R]
11
+
7
12
  LifecycleT = ta.TypeVar('LifecycleT', bound='Lifecycle')
8
- LifecycleCallback: ta.TypeAlias = ta.Callable[[LifecycleT], None]
13
+ LifecycleCallback: ta.TypeAlias = ta.Callable[[LifecycleT], R]
14
+
15
+ AsyncLifecycleT = ta.TypeVar('AsyncLifecycleT', bound='AsyncLifecycle')
16
+ AsyncLifecycleCallback: ta.TypeAlias = ta.Callable[[AsyncLifecycleT], R]
9
17
 
10
18
 
11
19
  ##
12
20
 
13
21
 
14
- class Lifecycle:
15
- def lifecycle_construct(self) -> None:
16
- pass
22
+ class AnyLifecycle(lang.Abstract, ta.Generic[R]):
23
+ def lifecycle_construct(self) -> R | None:
24
+ return None
17
25
 
18
- def lifecycle_start(self) -> None:
19
- pass
26
+ def lifecycle_start(self) -> R | None:
27
+ return None
20
28
 
21
- def lifecycle_stop(self) -> None:
22
- pass
29
+ def lifecycle_stop(self) -> R | None:
30
+ return None
23
31
 
24
- def lifecycle_destroy(self) -> None:
25
- pass
32
+ def lifecycle_destroy(self) -> R | None:
33
+ return None
26
34
 
27
35
 
28
36
  @dc.dataclass(frozen=True, kw_only=True)
29
- class CallbackLifecycle(Lifecycle, lang.Final, ta.Generic[LifecycleT]):
30
- on_construct: LifecycleCallback['CallbackLifecycle[LifecycleT]'] | None = None
31
- on_start: LifecycleCallback['CallbackLifecycle[LifecycleT]'] | None = None
32
- on_stop: LifecycleCallback['CallbackLifecycle[LifecycleT]'] | None = None
33
- on_destroy: LifecycleCallback['CallbackLifecycle[LifecycleT]'] | None = None
37
+ class AnyCallbackLifecycle(
38
+ AnyLifecycle[R],
39
+ lang.Abstract,
40
+ ta.Generic[AnyLifecycleT, R],
41
+ ):
42
+ on_construct: AnyLifecycleCallback['AnyCallbackLifecycle[AnyLifecycleT, R]', R] | None = None
43
+ on_start: AnyLifecycleCallback['AnyCallbackLifecycle[AnyLifecycleT, R]', R] | None = None
44
+ on_stop: AnyLifecycleCallback['AnyCallbackLifecycle[AnyLifecycleT, R]', R] | None = None
45
+ on_destroy: AnyLifecycleCallback['AnyCallbackLifecycle[AnyLifecycleT, R]', R] | None = None
34
46
 
35
47
  @ta.override
36
- def lifecycle_construct(self) -> None:
48
+ def lifecycle_construct(self) -> R | None:
37
49
  if self.on_construct is not None:
38
- self.on_construct(self)
50
+ return self.on_construct(self)
51
+ else:
52
+ return None
39
53
 
40
54
  @ta.override
41
- def lifecycle_start(self) -> None:
55
+ def lifecycle_start(self) -> R | None:
42
56
  if self.on_start is not None:
43
- self.on_start(self)
57
+ return self.on_start(self)
58
+ else:
59
+ return None
44
60
 
45
61
  @ta.override
46
- def lifecycle_stop(self) -> None:
62
+ def lifecycle_stop(self) -> R | None:
47
63
  if self.on_stop is not None:
48
- self.on_stop(self)
64
+ return self.on_stop(self)
65
+ else:
66
+ return None
49
67
 
50
68
  @ta.override
51
- def lifecycle_destroy(self) -> None:
69
+ def lifecycle_destroy(self) -> R | None:
52
70
  if self.on_destroy is not None:
53
- self.on_destroy(self)
71
+ return self.on_destroy(self)
72
+ else:
73
+ return None
74
+
75
+
76
+ ##
77
+
78
+
79
+ class Lifecycle(AnyLifecycle[None]):
80
+ pass
81
+
82
+
83
+ class CallbackLifecycle(
84
+ AnyCallbackLifecycle[LifecycleT, None],
85
+ lang.Final,
86
+ ta.Generic[LifecycleT],
87
+ ):
88
+ pass
89
+
90
+
91
+ ##
92
+
93
+
94
+ class AsyncLifecycle(AnyLifecycle[ta.Awaitable[None]]):
95
+ pass
96
+
97
+
98
+ class CallbackAsyncLifecycle(
99
+ AnyCallbackLifecycle[LifecycleT, ta.Awaitable[None]],
100
+ lang.Final,
101
+ ta.Generic[LifecycleT],
102
+ ):
103
+ pass