omlish 0.0.0.dev484__py3-none-any.whl → 0.0.0.dev493__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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/README.md +199 -0
- omlish/__about__.py +8 -3
- omlish/dataclasses/impl/generation/plans.py +2 -17
- omlish/dataclasses/impl/generation/processor.py +2 -2
- omlish/dataclasses/impl/processing/driving.py +13 -1
- omlish/diag/_pycharm/runhack.py +1 -1
- omlish/inject/__init__.py +19 -11
- omlish/inject/_dataclasses.py +1485 -1323
- omlish/inject/binder.py +7 -4
- omlish/inject/eagers.py +2 -0
- omlish/inject/helpers/late.py +76 -0
- omlish/inject/{managed.py → helpers/managed.py} +10 -10
- omlish/inject/impl/elements.py +7 -4
- omlish/inject/impl/injector.py +10 -7
- omlish/inject/inspect.py +1 -1
- omlish/lang/__init__.py +2 -0
- omlish/lifecycles/README.md +30 -0
- omlish/lifecycles/__init__.py +87 -13
- omlish/lifecycles/_dataclasses.py +1388 -0
- omlish/lifecycles/base.py +178 -64
- omlish/lifecycles/contextmanagers.py +113 -4
- omlish/lifecycles/controller.py +150 -87
- omlish/lifecycles/injection.py +143 -0
- omlish/lifecycles/listeners.py +56 -0
- omlish/lifecycles/managed.py +142 -0
- omlish/lifecycles/manager.py +218 -93
- omlish/lifecycles/states.py +2 -0
- omlish/lifecycles/transitions.py +3 -0
- omlish/lifecycles/unwrap.py +57 -0
- omlish/lite/typing.py +18 -0
- omlish/logs/_amalg.py +1 -1
- omlish/logs/all.py +25 -11
- omlish/logs/asyncs.py +73 -0
- omlish/logs/base.py +101 -12
- omlish/logs/contexts.py +4 -1
- omlish/logs/lists.py +125 -0
- omlish/logs/modules.py +19 -1
- omlish/logs/std/loggers.py +6 -1
- omlish/logs/std/noisy.py +11 -9
- omlish/logs/{standard.py → std/standard.py} +3 -4
- omlish/logs/utils.py +16 -1
- omlish/marshal/_dataclasses.py +781 -781
- omlish/reflect/__init__.py +43 -26
- omlish/reflect/ops.py +10 -1
- omlish/specs/jmespath/_dataclasses.py +559 -559
- omlish/specs/jsonschema/keywords/_dataclasses.py +220 -220
- omlish/sql/__init__.py +24 -5
- omlish/sql/api/dbapi.py +1 -1
- omlish/sql/dbapi/__init__.py +15 -0
- omlish/sql/{dbapi.py → dbapi/drivers.py} +2 -2
- omlish/sql/queries/__init__.py +3 -0
- omlish/testing/pytest/plugins/asyncs/plugin.py +2 -0
- omlish/text/docwrap/cli.py +5 -0
- {omlish-0.0.0.dev484.dist-info → omlish-0.0.0.dev493.dist-info}/METADATA +8 -5
- {omlish-0.0.0.dev484.dist-info → omlish-0.0.0.dev493.dist-info}/RECORD +61 -51
- omlish/lifecycles/abstract.py +0 -86
- /omlish/inject/{impl → helpers}/proxy.py +0 -0
- /omlish/sql/{abc.py → dbapi/abc.py} +0 -0
- {omlish-0.0.0.dev484.dist-info → omlish-0.0.0.dev493.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev484.dist-info → omlish-0.0.0.dev493.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev484.dist-info → omlish-0.0.0.dev493.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev484.dist-info → omlish-0.0.0.dev493.dist-info}/top_level.txt +0 -0
omlish/lifecycles/manager.py
CHANGED
|
@@ -4,160 +4,285 @@ from .. import check
|
|
|
4
4
|
from .. import collections as col
|
|
5
5
|
from .. import dataclasses as dc
|
|
6
6
|
from .. import lang
|
|
7
|
-
from .
|
|
7
|
+
from .base import AnyLifecycle
|
|
8
|
+
from .base import AsyncLifecycle
|
|
8
9
|
from .base import Lifecycle
|
|
10
|
+
from .base import as_async_lifecycle
|
|
11
|
+
from .controller import AnyLifecycleController
|
|
12
|
+
from .controller import AsyncLifecycleController
|
|
9
13
|
from .controller import LifecycleController
|
|
14
|
+
from .managed import AsyncLifecycleManaged
|
|
15
|
+
from .managed import LifecycleManaged
|
|
10
16
|
from .states import LifecycleState
|
|
11
17
|
from .states import LifecycleStateError
|
|
12
18
|
from .states import LifecycleStates
|
|
13
19
|
|
|
14
20
|
|
|
21
|
+
LifecycleControllerT = ta.TypeVar('LifecycleControllerT', bound=AnyLifecycleController)
|
|
22
|
+
|
|
23
|
+
|
|
15
24
|
##
|
|
16
25
|
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
@dc.dataclass(frozen=True, eq=False)
|
|
28
|
+
class LifecycleManagerEntry(lang.Final, ta.Generic[LifecycleControllerT]):
|
|
29
|
+
controller: LifecycleControllerT
|
|
30
|
+
|
|
31
|
+
dependencies: ta.MutableSet['LifecycleManagerEntry'] = dc.field(default_factory=set)
|
|
32
|
+
dependents: ta.MutableSet['LifecycleManagerEntry'] = dc.field(default_factory=set)
|
|
33
|
+
|
|
24
34
|
|
|
35
|
+
#
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@ta.final
|
|
39
|
+
class _InnerLifecycleManager(AsyncLifecycleManaged, lang.Final):
|
|
25
40
|
def __init__(
|
|
26
41
|
self,
|
|
27
|
-
|
|
28
|
-
lock: lang.DefaultLockable = None,
|
|
42
|
+
get_state: ta.Callable[[], LifecycleState],
|
|
29
43
|
) -> None:
|
|
30
44
|
super().__init__()
|
|
31
45
|
|
|
32
|
-
self.
|
|
33
|
-
|
|
34
|
-
self._entries_by_lifecycle: ta.MutableMapping[Lifecycle, LifecycleManager.Entry] = col.IdentityKeyDict()
|
|
35
|
-
|
|
36
|
-
self._controller = LifecycleController(self._lifecycle, lock=self._lock)
|
|
46
|
+
self._get_state = get_state
|
|
37
47
|
|
|
38
|
-
|
|
39
|
-
def controller(self) -> LifecycleController:
|
|
40
|
-
return self._controller
|
|
48
|
+
self._entries_by_lifecycle: ta.MutableMapping[AnyLifecycle, LifecycleManagerEntry] = col.IdentityKeyDict()
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
def state(self) -> LifecycleState:
|
|
44
|
-
return self._controller.state
|
|
50
|
+
#
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if isinstance(lifecycle, LifecycleController):
|
|
52
|
+
def _get_or_make_controller(self, lifecycle: AnyLifecycle) -> AnyLifecycleController:
|
|
53
|
+
if isinstance(lifecycle, (LifecycleController, AsyncLifecycleController)):
|
|
49
54
|
return lifecycle
|
|
50
|
-
|
|
51
|
-
# return lifecycle.lifecycle_controller
|
|
55
|
+
|
|
52
56
|
elif isinstance(lifecycle, Lifecycle):
|
|
53
57
|
return LifecycleController(lifecycle)
|
|
58
|
+
|
|
59
|
+
elif isinstance(lifecycle, AsyncLifecycle):
|
|
60
|
+
return AsyncLifecycleController(lifecycle)
|
|
61
|
+
|
|
54
62
|
else:
|
|
55
63
|
raise TypeError(lifecycle)
|
|
56
64
|
|
|
57
|
-
def _add_internal(self, lifecycle:
|
|
58
|
-
check.state(self.
|
|
65
|
+
def _add_internal(self, lifecycle: AnyLifecycle, dependencies: ta.Iterable[AnyLifecycle]) -> LifecycleManagerEntry:
|
|
66
|
+
check.state(self._get_state() < LifecycleStates.STOPPING and not self._get_state().is_failed)
|
|
59
67
|
|
|
60
|
-
check.isinstance(lifecycle, Lifecycle)
|
|
68
|
+
check.isinstance(lifecycle, (Lifecycle, AsyncLifecycle))
|
|
61
69
|
try:
|
|
62
70
|
entry = self._entries_by_lifecycle[lifecycle]
|
|
63
71
|
except KeyError:
|
|
64
|
-
controller = self.
|
|
65
|
-
entry = self._entries_by_lifecycle[lifecycle] =
|
|
72
|
+
controller = self._get_or_make_controller(lifecycle)
|
|
73
|
+
entry = self._entries_by_lifecycle[lifecycle] = LifecycleManagerEntry(controller)
|
|
66
74
|
|
|
67
75
|
for dep in dependencies:
|
|
68
|
-
check.isinstance(dep, Lifecycle)
|
|
76
|
+
check.isinstance(dep, (Lifecycle, AsyncLifecycle))
|
|
69
77
|
dep_entry = self._add_internal(dep, [])
|
|
70
78
|
entry.dependencies.add(dep_entry)
|
|
71
79
|
dep_entry.dependents.add(entry)
|
|
72
80
|
|
|
73
81
|
return entry
|
|
74
82
|
|
|
75
|
-
def add(
|
|
83
|
+
async def add(
|
|
76
84
|
self,
|
|
77
|
-
lifecycle:
|
|
78
|
-
dependencies: ta.Iterable[
|
|
79
|
-
) ->
|
|
80
|
-
check.state(self.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
85
|
+
lifecycle: AnyLifecycle,
|
|
86
|
+
dependencies: ta.Iterable[AnyLifecycle] = (),
|
|
87
|
+
) -> LifecycleManagerEntry:
|
|
88
|
+
check.state(self._get_state() < LifecycleStates.STOPPING and not self._get_state().is_failed)
|
|
89
|
+
|
|
90
|
+
entry = self._add_internal(lifecycle, dependencies)
|
|
91
|
+
|
|
92
|
+
if self._get_state() >= LifecycleStates.CONSTRUCTING:
|
|
93
|
+
async def rec(e):
|
|
94
|
+
if e.controller.state < LifecycleStates.CONSTRUCTED:
|
|
95
|
+
for dep in e.dependencies:
|
|
96
|
+
await rec(dep)
|
|
97
|
+
|
|
98
|
+
await as_async_lifecycle(e.controller).lifecycle_construct()
|
|
99
|
+
|
|
100
|
+
await rec(entry)
|
|
101
|
+
|
|
102
|
+
if self._get_state() >= LifecycleStates.STARTING:
|
|
103
|
+
async def rec(e):
|
|
104
|
+
if e.controller.state < LifecycleStates.STARTED:
|
|
105
|
+
for dep in e.dependencies:
|
|
106
|
+
await rec(dep)
|
|
107
|
+
|
|
108
|
+
await as_async_lifecycle(e.controller).lifecycle_start()
|
|
109
|
+
|
|
110
|
+
await rec(entry)
|
|
111
|
+
|
|
112
|
+
return entry
|
|
102
113
|
|
|
103
114
|
##
|
|
104
115
|
|
|
105
116
|
@ta.override
|
|
106
|
-
def _lifecycle_construct(self) -> None:
|
|
107
|
-
def rec(
|
|
108
|
-
for dep in
|
|
109
|
-
rec(dep)
|
|
117
|
+
async def _lifecycle_construct(self) -> None:
|
|
118
|
+
async def rec(e: LifecycleManagerEntry) -> None:
|
|
119
|
+
for dep in e.dependencies:
|
|
120
|
+
await rec(dep)
|
|
110
121
|
|
|
111
|
-
if
|
|
112
|
-
raise LifecycleStateError(
|
|
122
|
+
if e.controller.state.is_failed:
|
|
123
|
+
raise LifecycleStateError(e.controller)
|
|
113
124
|
|
|
114
|
-
if
|
|
115
|
-
|
|
125
|
+
if e.controller.state < LifecycleStates.CONSTRUCTED:
|
|
126
|
+
await as_async_lifecycle(e.controller).lifecycle_construct()
|
|
116
127
|
|
|
117
128
|
for entry in self._entries_by_lifecycle.values():
|
|
118
|
-
rec(entry)
|
|
129
|
+
await rec(entry)
|
|
119
130
|
|
|
120
131
|
@ta.override
|
|
121
|
-
def _lifecycle_start(self) -> None:
|
|
122
|
-
def rec(
|
|
123
|
-
for dep in
|
|
124
|
-
rec(dep)
|
|
132
|
+
async def _lifecycle_start(self) -> None:
|
|
133
|
+
async def rec(e: LifecycleManagerEntry) -> None:
|
|
134
|
+
for dep in e.dependencies:
|
|
135
|
+
await rec(dep)
|
|
125
136
|
|
|
126
|
-
if
|
|
127
|
-
raise LifecycleStateError(
|
|
137
|
+
if e.controller.state.is_failed:
|
|
138
|
+
raise LifecycleStateError(e.controller)
|
|
128
139
|
|
|
129
|
-
if
|
|
130
|
-
|
|
140
|
+
if e.controller.state < LifecycleStates.CONSTRUCTED:
|
|
141
|
+
await as_async_lifecycle(e.controller).lifecycle_construct()
|
|
131
142
|
|
|
132
|
-
if
|
|
133
|
-
|
|
143
|
+
if e.controller.state < LifecycleStates.STARTED:
|
|
144
|
+
await as_async_lifecycle(e.controller).lifecycle_start()
|
|
134
145
|
|
|
135
146
|
for entry in self._entries_by_lifecycle.values():
|
|
136
|
-
rec(entry)
|
|
147
|
+
await rec(entry)
|
|
137
148
|
|
|
138
149
|
@ta.override
|
|
139
|
-
def _lifecycle_stop(self) -> None:
|
|
140
|
-
def rec(
|
|
141
|
-
for dep in
|
|
142
|
-
rec(dep)
|
|
150
|
+
async def _lifecycle_stop(self) -> None:
|
|
151
|
+
async def rec(e: LifecycleManagerEntry) -> None:
|
|
152
|
+
for dep in e.dependents:
|
|
153
|
+
await rec(dep)
|
|
143
154
|
|
|
144
|
-
if
|
|
145
|
-
raise LifecycleStateError(
|
|
155
|
+
if e.controller.state.is_failed:
|
|
156
|
+
raise LifecycleStateError(e.controller)
|
|
146
157
|
|
|
147
|
-
if
|
|
148
|
-
|
|
158
|
+
if e.controller.state is LifecycleStates.STARTED:
|
|
159
|
+
await as_async_lifecycle(e.controller).lifecycle_stop()
|
|
149
160
|
|
|
150
161
|
for entry in self._entries_by_lifecycle.values():
|
|
151
|
-
rec(entry)
|
|
162
|
+
await rec(entry)
|
|
152
163
|
|
|
153
164
|
@ta.override
|
|
154
|
-
def _lifecycle_destroy(self) -> None:
|
|
155
|
-
def rec(
|
|
156
|
-
for dep in
|
|
157
|
-
rec(dep)
|
|
165
|
+
async def _lifecycle_destroy(self) -> None:
|
|
166
|
+
async def rec(e: LifecycleManagerEntry) -> None:
|
|
167
|
+
for dep in e.dependents:
|
|
168
|
+
await rec(dep)
|
|
158
169
|
|
|
159
|
-
if
|
|
160
|
-
|
|
170
|
+
if e.controller.state < LifecycleStates.DESTROYED:
|
|
171
|
+
await as_async_lifecycle(e.controller).lifecycle_destroy()
|
|
161
172
|
|
|
162
173
|
for entry in self._entries_by_lifecycle.values():
|
|
163
|
-
rec(entry)
|
|
174
|
+
await rec(entry)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class LifecycleManager(LifecycleManaged, lang.Final):
|
|
181
|
+
def __init__(
|
|
182
|
+
self,
|
|
183
|
+
*,
|
|
184
|
+
lock: lang.DefaultLockable = None,
|
|
185
|
+
) -> None:
|
|
186
|
+
super().__init__()
|
|
187
|
+
|
|
188
|
+
self._lock = lang.default_lock(lock, None)
|
|
189
|
+
|
|
190
|
+
self._inner = _InnerLifecycleManager(lambda: self._inner_controller.state)
|
|
191
|
+
|
|
192
|
+
self._inner_controller = AsyncLifecycleController(
|
|
193
|
+
self._inner._lifecycle, # noqa
|
|
194
|
+
lock=lambda: lang.SyncToAsyncContextManager(self._lock()),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
#
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def state(self) -> LifecycleState:
|
|
201
|
+
return self._inner_controller.state
|
|
202
|
+
|
|
203
|
+
#
|
|
204
|
+
|
|
205
|
+
def add(
|
|
206
|
+
self,
|
|
207
|
+
lifecycle: Lifecycle,
|
|
208
|
+
dependencies: ta.Iterable[Lifecycle] = (),
|
|
209
|
+
) -> LifecycleManagerEntry[LifecycleController]:
|
|
210
|
+
return lang.sync_await(self._inner.add(
|
|
211
|
+
check.isinstance(lifecycle, Lifecycle),
|
|
212
|
+
[check.isinstance(d, Lifecycle) for d in dependencies],
|
|
213
|
+
))
|
|
214
|
+
|
|
215
|
+
#
|
|
216
|
+
|
|
217
|
+
@ta.override
|
|
218
|
+
def _lifecycle_construct(self) -> None:
|
|
219
|
+
return lang.sync_await(self._inner_controller.lifecycle_construct())
|
|
220
|
+
|
|
221
|
+
@ta.override
|
|
222
|
+
def _lifecycle_start(self) -> None:
|
|
223
|
+
return lang.sync_await(self._inner_controller.lifecycle_start())
|
|
224
|
+
|
|
225
|
+
@ta.override
|
|
226
|
+
def _lifecycle_stop(self) -> None:
|
|
227
|
+
return lang.sync_await(self._inner_controller.lifecycle_stop())
|
|
228
|
+
|
|
229
|
+
@ta.override
|
|
230
|
+
def _lifecycle_destroy(self) -> None:
|
|
231
|
+
return lang.sync_await(self._inner_controller.lifecycle_destroy())
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
#
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class AsyncLifecycleManager(AsyncLifecycleManaged, lang.Final):
|
|
238
|
+
def __init__(
|
|
239
|
+
self,
|
|
240
|
+
*,
|
|
241
|
+
lock: lang.DefaultAsyncLockable = None,
|
|
242
|
+
) -> None:
|
|
243
|
+
super().__init__()
|
|
244
|
+
|
|
245
|
+
self._lock = lang.default_async_lock(lock, None)
|
|
246
|
+
|
|
247
|
+
self._inner = _InnerLifecycleManager(lambda: self._inner_controller.state)
|
|
248
|
+
|
|
249
|
+
self._inner_controller = AsyncLifecycleController(
|
|
250
|
+
self._inner._lifecycle, # noqa
|
|
251
|
+
lock=self._lock,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
#
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def state(self) -> LifecycleState:
|
|
258
|
+
return self._inner_controller.state
|
|
259
|
+
|
|
260
|
+
#
|
|
261
|
+
|
|
262
|
+
async def add(
|
|
263
|
+
self,
|
|
264
|
+
lifecycle: AnyLifecycle,
|
|
265
|
+
dependencies: ta.Iterable[AnyLifecycle] = (),
|
|
266
|
+
) -> LifecycleManagerEntry[AnyLifecycleController]:
|
|
267
|
+
return await self._inner.add(
|
|
268
|
+
lifecycle,
|
|
269
|
+
dependencies,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
#
|
|
273
|
+
|
|
274
|
+
@ta.override
|
|
275
|
+
async def _lifecycle_construct(self) -> None:
|
|
276
|
+
return await self._inner_controller.lifecycle_construct()
|
|
277
|
+
|
|
278
|
+
@ta.override
|
|
279
|
+
async def _lifecycle_start(self) -> None:
|
|
280
|
+
return await self._inner_controller.lifecycle_start()
|
|
281
|
+
|
|
282
|
+
@ta.override
|
|
283
|
+
async def _lifecycle_stop(self) -> None:
|
|
284
|
+
return await self._inner_controller.lifecycle_stop()
|
|
285
|
+
|
|
286
|
+
@ta.override
|
|
287
|
+
async def _lifecycle_destroy(self) -> None:
|
|
288
|
+
return await self._inner_controller.lifecycle_destroy()
|
omlish/lifecycles/states.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import functools
|
|
2
|
+
import typing as ta
|
|
2
3
|
|
|
3
4
|
from .. import check
|
|
4
5
|
from .. import dataclasses as dc
|
|
@@ -12,6 +13,7 @@ class LifecycleStateError(Exception):
|
|
|
12
13
|
pass
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
@ta.final
|
|
15
17
|
@dc.dataclass(frozen=True, eq=False)
|
|
16
18
|
@functools.total_ordering
|
|
17
19
|
class LifecycleState(lang.Final):
|
omlish/lifecycles/transitions.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
1
3
|
from .. import check
|
|
2
4
|
from .. import dataclasses as dc
|
|
3
5
|
from .. import lang
|
|
@@ -8,6 +10,7 @@ from .states import LifecycleStates
|
|
|
8
10
|
##
|
|
9
11
|
|
|
10
12
|
|
|
13
|
+
@ta.final
|
|
11
14
|
@dc.dataclass(frozen=True)
|
|
12
15
|
class LifecycleTransition(lang.Final):
|
|
13
16
|
old: frozenset[LifecycleState]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from .base import AsyncLifecycle
|
|
5
|
+
from .base import Lifecycle
|
|
6
|
+
from .managed import AsyncLifecycleManaged
|
|
7
|
+
from .managed import LifecycleManaged
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@functools.singledispatch
|
|
14
|
+
def unwrap_lifecycle(obj: ta.Any) -> Lifecycle | None:
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@unwrap_lifecycle.register
|
|
19
|
+
def _(obj: Lifecycle) -> Lifecycle:
|
|
20
|
+
return obj
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@unwrap_lifecycle.register
|
|
24
|
+
def _(obj: LifecycleManaged) -> Lifecycle:
|
|
25
|
+
return obj._lifecycle # noqa
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@functools.singledispatch
|
|
32
|
+
def unwrap_async_lifecycle(obj: ta.Any) -> AsyncLifecycle | None:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@unwrap_async_lifecycle.register
|
|
37
|
+
def _(obj: AsyncLifecycle) -> AsyncLifecycle:
|
|
38
|
+
return obj
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@unwrap_async_lifecycle.register
|
|
42
|
+
def _(obj: AsyncLifecycleManaged) -> AsyncLifecycle:
|
|
43
|
+
return obj._lifecycle # noqa
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def unwrap_any_lifecycle(obj: ta.Any) -> Lifecycle | AsyncLifecycle | None:
|
|
50
|
+
if (lc := unwrap_lifecycle(obj)) is not None:
|
|
51
|
+
return lc
|
|
52
|
+
|
|
53
|
+
elif (alc := unwrap_async_lifecycle(obj)) is not None:
|
|
54
|
+
return alc
|
|
55
|
+
|
|
56
|
+
else:
|
|
57
|
+
return None
|
omlish/lite/typing.py
CHANGED
|
@@ -63,6 +63,24 @@ class Func3(ta.Generic[A0, A1, A2, T]):
|
|
|
63
63
|
##
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
@dc.dataclass(frozen=True)
|
|
67
|
+
class CachedFunc0(ta.Generic[T]):
|
|
68
|
+
fn: ta.Callable[[], T]
|
|
69
|
+
|
|
70
|
+
def __call__(self) -> T:
|
|
71
|
+
try:
|
|
72
|
+
return object.__getattribute__(self, '_value')
|
|
73
|
+
except AttributeError:
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
value = self.fn()
|
|
77
|
+
object.__setattr__(self, '_value', value)
|
|
78
|
+
return value
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
|
|
83
|
+
|
|
66
84
|
_TYPING_ANNOTATIONS_ATTR = '__annotate__' if sys.version_info >= (3, 14) else '__annotations__'
|
|
67
85
|
|
|
68
86
|
|
omlish/logs/_amalg.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @omlish-lite
|
|
2
2
|
# @omlish-amalg ../../omdev/scripts/lib/logs.py
|
|
3
3
|
from .base import AnyLogger # noqa
|
|
4
|
-
from .standard import configure_standard_logging # noqa
|
|
5
4
|
from .std.loggers import StdLogger # noqa
|
|
5
|
+
from .std.standard import configure_standard_logging # noqa
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
##
|
omlish/logs/all.py
CHANGED
|
@@ -38,6 +38,20 @@ with _lang.auto_proxy_init(globals()):
|
|
|
38
38
|
LoggingContextLogRecord,
|
|
39
39
|
)
|
|
40
40
|
|
|
41
|
+
from .std.standard import ( # noqa
|
|
42
|
+
STANDARD_LOG_FORMAT_PARTS,
|
|
43
|
+
StandardLoggingFormatter,
|
|
44
|
+
|
|
45
|
+
StandardConfiguredLoggingHandler,
|
|
46
|
+
|
|
47
|
+
configure_standard_logging,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
from .asyncs import ( # noqa
|
|
51
|
+
AsyncLoggerToLogger,
|
|
52
|
+
LoggerToAsyncLogger,
|
|
53
|
+
)
|
|
54
|
+
|
|
41
55
|
from .base import ( # noqa
|
|
42
56
|
AnyLogger,
|
|
43
57
|
Logger,
|
|
@@ -67,28 +81,28 @@ with _lang.auto_proxy_init(globals()):
|
|
|
67
81
|
NamedLogLevel,
|
|
68
82
|
)
|
|
69
83
|
|
|
84
|
+
from .lists import ( # noqa
|
|
85
|
+
AnyListLogger,
|
|
86
|
+
ListLogger,
|
|
87
|
+
AsyncLogger,
|
|
88
|
+
)
|
|
89
|
+
|
|
70
90
|
from .modules import ( # noqa
|
|
71
91
|
get_module_logger,
|
|
92
|
+
get_module_async_logger,
|
|
93
|
+
get_module_loggers,
|
|
72
94
|
)
|
|
73
95
|
|
|
74
96
|
from .protocols import ( # noqa
|
|
75
97
|
LoggerLike,
|
|
76
98
|
)
|
|
77
99
|
|
|
78
|
-
from .standard import ( # noqa
|
|
79
|
-
STANDARD_LOG_FORMAT_PARTS,
|
|
80
|
-
StandardLoggingFormatter,
|
|
81
|
-
|
|
82
|
-
StandardConfiguredLoggingHandler,
|
|
83
|
-
|
|
84
|
-
configure_standard_logging,
|
|
85
|
-
)
|
|
86
|
-
|
|
87
100
|
from .utils import ( # noqa
|
|
101
|
+
exception_logging,
|
|
102
|
+
async_exception_logging,
|
|
103
|
+
|
|
88
104
|
LogTimingContext,
|
|
89
105
|
log_timing_context,
|
|
90
|
-
|
|
91
|
-
exception_logging,
|
|
92
106
|
)
|
|
93
107
|
|
|
94
108
|
from .warnings import ( # noqa
|
omlish/logs/asyncs.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007 UP045 UP046
|
|
2
|
+
# @omlish-lite
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
from ..lite.asyncs import sync_await
|
|
6
|
+
from ..lite.check import check
|
|
7
|
+
from .base import AsyncLogger
|
|
8
|
+
from .base import CaptureLoggingContext
|
|
9
|
+
from .base import Logger
|
|
10
|
+
from .base import LoggingMsgFn
|
|
11
|
+
from .contexts import CaptureLoggingContextImpl
|
|
12
|
+
from .infos import LoggingContextInfos
|
|
13
|
+
from .levels import LogLevel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AsyncLoggerToLogger(Logger):
|
|
20
|
+
def __init__(self, u: AsyncLogger) -> None:
|
|
21
|
+
super().__init__()
|
|
22
|
+
|
|
23
|
+
self._u = u
|
|
24
|
+
|
|
25
|
+
def get_effective_level(self) -> LogLevel:
|
|
26
|
+
return self._u.get_effective_level()
|
|
27
|
+
|
|
28
|
+
def _log(
|
|
29
|
+
self,
|
|
30
|
+
ctx: CaptureLoggingContext,
|
|
31
|
+
msg: ta.Union[str, tuple, LoggingMsgFn],
|
|
32
|
+
*args: ta.Any,
|
|
33
|
+
**kwargs: ta.Any,
|
|
34
|
+
) -> None:
|
|
35
|
+
# Nope out early to avoid sync_await if possible - don't bother in the LoggerToAsyncLogger.
|
|
36
|
+
if not self.is_enabled_for(ctx.must_get_info(LoggingContextInfos.Level).level):
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
# Note: we hardcode the stack offset of sync_await (which is 2 - sync_await + sync_await.thunk). In non-lite
|
|
40
|
+
# code, lang.sync_await uses a cext if present to avoid being on the py stack, which would obviously complicate
|
|
41
|
+
# this, but this is lite code so we will always have the non-c version.
|
|
42
|
+
sync_await(
|
|
43
|
+
self._u._log( # noqa
|
|
44
|
+
check.isinstance(ctx, CaptureLoggingContextImpl).inc_stack_offset(3),
|
|
45
|
+
msg,
|
|
46
|
+
*args,
|
|
47
|
+
**kwargs,
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class LoggerToAsyncLogger(AsyncLogger):
|
|
53
|
+
def __init__(self, u: Logger) -> None:
|
|
54
|
+
super().__init__()
|
|
55
|
+
|
|
56
|
+
self._u = u
|
|
57
|
+
|
|
58
|
+
def get_effective_level(self) -> LogLevel:
|
|
59
|
+
return self._u.get_effective_level()
|
|
60
|
+
|
|
61
|
+
async def _log(
|
|
62
|
+
self,
|
|
63
|
+
ctx: CaptureLoggingContext,
|
|
64
|
+
msg: ta.Union[str, tuple, LoggingMsgFn],
|
|
65
|
+
*args: ta.Any,
|
|
66
|
+
**kwargs: ta.Any,
|
|
67
|
+
) -> None:
|
|
68
|
+
return self._u._log( # noqa
|
|
69
|
+
check.isinstance(ctx, CaptureLoggingContextImpl).inc_stack_offset(),
|
|
70
|
+
msg,
|
|
71
|
+
*args,
|
|
72
|
+
**kwargs,
|
|
73
|
+
)
|