omlish 0.0.0.dev420__py3-none-any.whl → 0.0.0.dev421__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 +2 -2
- omlish/asyncs/bluelet/core.py +2 -2
- omlish/asyncs/bluelet/events.py +4 -3
- omlish/asyncs/bluelet/files.py +2 -2
- omlish/asyncs/bluelet/sockets.py +2 -2
- omlish/collections/frozen.py +1 -1
- omlish/collections/kv/base.py +1 -1
- omlish/collections/multimaps.py +1 -1
- omlish/collections/persistent/treapmap.py +2 -1
- omlish/concurrent/threadlets.py +2 -2
- omlish/configs/formats.py +5 -4
- omlish/configs/processing/flattening.py +2 -1
- omlish/configs/processing/rewriting.py +2 -2
- omlish/configs/shadow.py +3 -2
- omlish/daemons/spawning.py +2 -2
- omlish/daemons/targets.py +1 -1
- omlish/daemons/waiting.py +2 -1
- omlish/dataclasses/impl/generation/base.py +3 -2
- omlish/dataclasses/impl/generation/compilation.py +2 -1
- omlish/dataclasses/impl/generation/ops.py +2 -2
- omlish/dataclasses/impl/generation/processor.py +1 -1
- omlish/dataclasses/metaclass/meta.py +1 -0
- omlish/dataclasses/tools/static.py +5 -1
- omlish/formats/dotenv.py +3 -1
- omlish/formats/logfmt.py +111 -0
- omlish/formats/yaml.py +1 -1
- omlish/funcs/builders.py +2 -1
- omlish/funcs/match.py +1 -1
- omlish/funcs/pairs.py +41 -23
- omlish/funcs/pipes.py +3 -1
- omlish/http/asgi.py +2 -1
- omlish/http/coro/client/io.py +3 -2
- omlish/http/coro/server/server.py +2 -2
- omlish/http/handlers.py +2 -1
- omlish/http/jwt.py +1 -1
- omlish/http/parsing.py +2 -2
- omlish/io/compress/base.py +3 -2
- omlish/io/coro/readers.py +4 -3
- omlish/io/fdio/handlers.py +3 -2
- omlish/io/fdio/pollers.py +3 -1
- omlish/lang/__init__.py +20 -8
- omlish/lang/attrs.py +3 -1
- omlish/lang/casing.py +3 -1
- omlish/lang/classes/abstract.py +35 -96
- omlish/lang/classes/virtual.py +2 -2
- omlish/lang/contextmanagers.py +6 -4
- omlish/lang/generators.py +2 -2
- omlish/lang/iterables.py +6 -6
- omlish/lang/objects.py +0 -58
- omlish/lang/outcomes.py +3 -1
- omlish/lang/typing.py +5 -24
- omlish/lite/abstract.py +119 -0
- omlish/lite/contextmanagers.py +4 -1
- omlish/lite/inject.py +9 -9
- omlish/lite/marshal.py +230 -114
- omlish/lite/maybes.py +3 -1
- omlish/lite/maysync.py +4 -2
- omlish/lite/objects.py +81 -0
- omlish/lite/reflect.py +0 -15
- omlish/lite/timeouts.py +3 -1
- omlish/lite/wrappers.py +23 -0
- omlish/logs/abc.py +21 -5
- omlish/logs/all.py +14 -3
- omlish/logs/configs.py +13 -10
- omlish/logs/levels.py +4 -0
- omlish/logs/protocol.py +77 -39
- omlish/marshal/__init__.py +1 -0
- omlish/os/atomics.py +3 -2
- omlish/os/deathpacts/base.py +4 -2
- omlish/os/forkhooks.py +2 -2
- omlish/os/pidfiles/pinning.py +2 -1
- omlish/reflect/types.py +4 -3
- omlish/secrets/crypto.py +1 -1
- omlish/sockets/bind.py +2 -1
- omlish/sockets/handlers.py +3 -2
- omlish/sockets/server/handlers.py +2 -1
- omlish/sockets/server/server.py +4 -3
- omlish/sql/api/base.py +2 -2
- omlish/subprocesses/asyncs.py +2 -1
- omlish/subprocesses/base.py +2 -2
- omlish/subprocesses/maysync.py +1 -2
- omlish/subprocesses/run.py +2 -1
- omlish/subprocesses/sync.py +2 -1
- omlish/term/coloring.py +3 -1
- omlish/testing/pytest/plugins/asyncs/backends/base.py +3 -1
- omlish/testing/unittest/loading.py +2 -2
- omlish/text/asdl.py +4 -3
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev421.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev421.dist-info}/RECORD +93 -88
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev421.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev421.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev421.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev421.dist-info}/top_level.txt +0 -0
omlish/lite/marshal.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007 UP045
|
1
2
|
"""
|
2
3
|
TODO:
|
3
4
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
4
5
|
- Options.sequence_cls = list, mapping_cls = dict, ... - def with_mutable_containers() -> Options
|
5
6
|
"""
|
6
|
-
# ruff: noqa: UP006 UP007 UP045
|
7
7
|
import abc
|
8
8
|
import base64
|
9
9
|
import collections.abc
|
@@ -19,8 +19,9 @@ import typing as ta
|
|
19
19
|
import uuid
|
20
20
|
import weakref
|
21
21
|
|
22
|
+
from .abstract import Abstract
|
22
23
|
from .check import check
|
23
|
-
from .
|
24
|
+
from .objects import deep_subclasses
|
24
25
|
from .reflect import get_literal_type_args
|
25
26
|
from .reflect import get_new_type_supertype
|
26
27
|
from .reflect import is_generic_alias
|
@@ -42,7 +43,7 @@ class ObjMarshalOptions:
|
|
42
43
|
non_strict_fields: bool = False
|
43
44
|
|
44
45
|
|
45
|
-
class ObjMarshaler(
|
46
|
+
class ObjMarshaler(Abstract):
|
46
47
|
@abc.abstractmethod
|
47
48
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
48
49
|
raise NotImplementedError
|
@@ -60,26 +61,30 @@ class NopObjMarshaler(ObjMarshaler):
|
|
60
61
|
return o
|
61
62
|
|
62
63
|
|
63
|
-
@dc.dataclass()
|
64
64
|
class ProxyObjMarshaler(ObjMarshaler):
|
65
|
-
m: ta.Optional[ObjMarshaler] = None
|
65
|
+
def __init__(self, m: ta.Optional[ObjMarshaler] = None) -> None:
|
66
|
+
super().__init__()
|
67
|
+
|
68
|
+
self._m = m
|
66
69
|
|
67
70
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
68
|
-
return check.not_none(self.
|
71
|
+
return check.not_none(self._m).marshal(o, ctx)
|
69
72
|
|
70
73
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
71
|
-
return check.not_none(self.
|
74
|
+
return check.not_none(self._m).unmarshal(o, ctx)
|
72
75
|
|
73
76
|
|
74
|
-
@dc.dataclass(frozen=True)
|
75
77
|
class CastObjMarshaler(ObjMarshaler):
|
76
|
-
ty: type
|
78
|
+
def __init__(self, ty: type) -> None:
|
79
|
+
super().__init__()
|
80
|
+
|
81
|
+
self._ty = ty
|
77
82
|
|
78
83
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
79
84
|
return o
|
80
85
|
|
81
86
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
82
|
-
return self.
|
87
|
+
return self._ty(o)
|
83
88
|
|
84
89
|
|
85
90
|
class DynamicObjMarshaler(ObjMarshaler):
|
@@ -90,121 +95,151 @@ class DynamicObjMarshaler(ObjMarshaler):
|
|
90
95
|
return o
|
91
96
|
|
92
97
|
|
93
|
-
@dc.dataclass(frozen=True)
|
94
98
|
class Base64ObjMarshaler(ObjMarshaler):
|
95
|
-
ty: type
|
99
|
+
def __init__(self, ty: type) -> None:
|
100
|
+
super().__init__()
|
101
|
+
|
102
|
+
self._ty = ty
|
96
103
|
|
97
104
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
98
105
|
return base64.b64encode(o).decode('ascii')
|
99
106
|
|
100
107
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
101
|
-
return self.
|
108
|
+
return self._ty(base64.b64decode(o))
|
102
109
|
|
103
110
|
|
104
|
-
@dc.dataclass(frozen=True)
|
105
111
|
class BytesSwitchedObjMarshaler(ObjMarshaler):
|
106
|
-
m: ObjMarshaler
|
112
|
+
def __init__(self, m: ObjMarshaler) -> None:
|
113
|
+
super().__init__()
|
114
|
+
|
115
|
+
self._m = m
|
107
116
|
|
108
117
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
109
118
|
if ctx.options.raw_bytes:
|
110
119
|
return o
|
111
|
-
return self.
|
120
|
+
return self._m.marshal(o, ctx)
|
112
121
|
|
113
122
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
114
123
|
if ctx.options.raw_bytes:
|
115
124
|
return o
|
116
|
-
return self.
|
125
|
+
return self._m.unmarshal(o, ctx)
|
117
126
|
|
118
127
|
|
119
|
-
@dc.dataclass(frozen=True)
|
120
128
|
class EnumObjMarshaler(ObjMarshaler):
|
121
|
-
ty: type
|
129
|
+
def __init__(self, ty: type) -> None:
|
130
|
+
super().__init__()
|
131
|
+
|
132
|
+
self._ty = ty
|
122
133
|
|
123
134
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
124
135
|
return o.name
|
125
136
|
|
126
137
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
127
|
-
return self.
|
138
|
+
return self._ty.__members__[o] # type: ignore
|
128
139
|
|
129
140
|
|
130
|
-
@dc.dataclass(frozen=True)
|
131
141
|
class OptionalObjMarshaler(ObjMarshaler):
|
132
|
-
item: ObjMarshaler
|
142
|
+
def __init__(self, item: ObjMarshaler) -> None:
|
143
|
+
super().__init__()
|
144
|
+
|
145
|
+
self._item = item
|
133
146
|
|
134
147
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
135
148
|
if o is None:
|
136
149
|
return None
|
137
|
-
return self.
|
150
|
+
return self._item.marshal(o, ctx)
|
138
151
|
|
139
152
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
140
153
|
if o is None:
|
141
154
|
return None
|
142
|
-
return self.
|
155
|
+
return self._item.unmarshal(o, ctx)
|
143
156
|
|
144
157
|
|
145
|
-
@dc.dataclass(frozen=True)
|
146
158
|
class PrimitiveUnionObjMarshaler(ObjMarshaler):
|
147
|
-
|
148
|
-
|
159
|
+
def __init__(
|
160
|
+
self,
|
161
|
+
pt: ta.Tuple[type, ...],
|
162
|
+
x: ta.Optional[ObjMarshaler] = None,
|
163
|
+
) -> None:
|
164
|
+
super().__init__()
|
165
|
+
|
166
|
+
self._pt = pt
|
167
|
+
self._x = x
|
149
168
|
|
150
169
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
151
|
-
if isinstance(o, self.
|
170
|
+
if isinstance(o, self._pt):
|
152
171
|
return o
|
153
|
-
elif self.
|
154
|
-
return self.
|
172
|
+
elif self._x is not None:
|
173
|
+
return self._x.marshal(o, ctx)
|
155
174
|
else:
|
156
175
|
raise TypeError(o)
|
157
176
|
|
158
177
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
159
|
-
if isinstance(o, self.
|
178
|
+
if isinstance(o, self._pt):
|
160
179
|
return o
|
161
|
-
elif self.
|
162
|
-
return self.
|
180
|
+
elif self._x is not None:
|
181
|
+
return self._x.unmarshal(o, ctx)
|
163
182
|
else:
|
164
183
|
raise TypeError(o)
|
165
184
|
|
166
185
|
|
167
|
-
@dc.dataclass(frozen=True)
|
168
186
|
class LiteralObjMarshaler(ObjMarshaler):
|
169
|
-
|
170
|
-
|
187
|
+
def __init__(
|
188
|
+
self,
|
189
|
+
item: ObjMarshaler,
|
190
|
+
vs: frozenset,
|
191
|
+
) -> None:
|
192
|
+
super().__init__()
|
193
|
+
|
194
|
+
self._item = item
|
195
|
+
self._vs = vs
|
171
196
|
|
172
197
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
173
|
-
return self.
|
198
|
+
return self._item.marshal(check.in_(o, self._vs), ctx)
|
174
199
|
|
175
200
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
176
|
-
return check.in_(self.
|
201
|
+
return check.in_(self._item.unmarshal(o, ctx), self._vs)
|
177
202
|
|
178
203
|
|
179
|
-
@dc.dataclass(frozen=True)
|
180
204
|
class MappingObjMarshaler(ObjMarshaler):
|
181
|
-
|
182
|
-
|
183
|
-
|
205
|
+
def __init__(
|
206
|
+
self,
|
207
|
+
ty: type,
|
208
|
+
km: ObjMarshaler,
|
209
|
+
vm: ObjMarshaler,
|
210
|
+
) -> None:
|
211
|
+
super().__init__()
|
212
|
+
|
213
|
+
self._ty = ty
|
214
|
+
self._km = km
|
215
|
+
self._vm = vm
|
184
216
|
|
185
217
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
186
|
-
return {self.
|
218
|
+
return {self._km.marshal(k, ctx): self._vm.marshal(v, ctx) for k, v in o.items()}
|
187
219
|
|
188
220
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
189
|
-
return self.
|
221
|
+
return self._ty((self._km.unmarshal(k, ctx), self._vm.unmarshal(v, ctx)) for k, v in o.items())
|
190
222
|
|
191
223
|
|
192
|
-
@dc.dataclass(frozen=True)
|
193
224
|
class IterableObjMarshaler(ObjMarshaler):
|
194
|
-
|
195
|
-
|
225
|
+
def __init__(
|
226
|
+
self,
|
227
|
+
ty: type,
|
228
|
+
item: ObjMarshaler,
|
229
|
+
) -> None:
|
230
|
+
super().__init__()
|
231
|
+
|
232
|
+
self._ty = ty
|
233
|
+
self._item = item
|
196
234
|
|
197
235
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
198
|
-
return [self.
|
236
|
+
return [self._item.marshal(e, ctx) for e in o]
|
199
237
|
|
200
238
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
201
|
-
return self.
|
239
|
+
return self._ty(self._item.unmarshal(e, ctx) for e in o)
|
202
240
|
|
203
241
|
|
204
|
-
@dc.dataclass(frozen=True)
|
205
242
|
class FieldsObjMarshaler(ObjMarshaler):
|
206
|
-
ty: type
|
207
|
-
|
208
243
|
@dc.dataclass(frozen=True)
|
209
244
|
class Field:
|
210
245
|
att: str
|
@@ -213,31 +248,43 @@ class FieldsObjMarshaler(ObjMarshaler):
|
|
213
248
|
|
214
249
|
omit_if_none: bool = False
|
215
250
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
251
|
+
def __init__(
|
252
|
+
self,
|
253
|
+
ty: type,
|
254
|
+
fs: ta.Sequence[Field],
|
255
|
+
*,
|
256
|
+
non_strict: bool = False,
|
257
|
+
) -> None:
|
258
|
+
super().__init__()
|
221
259
|
|
222
|
-
|
223
|
-
|
260
|
+
self._ty = ty
|
261
|
+
self._fs = fs
|
262
|
+
self._non_strict = non_strict
|
224
263
|
|
225
|
-
def __post_init__(self) -> None:
|
226
264
|
fs_by_att: dict = {}
|
227
265
|
fs_by_key: dict = {}
|
228
|
-
for f in self.
|
266
|
+
for f in self._fs:
|
229
267
|
check.not_in(check.non_empty_str(f.att), fs_by_att)
|
230
268
|
check.not_in(check.non_empty_str(f.key), fs_by_key)
|
231
269
|
fs_by_att[f.att] = f
|
232
270
|
fs_by_key[f.key] = f
|
233
|
-
|
234
|
-
self.
|
271
|
+
|
272
|
+
self._fs_by_att: ta.Mapping[str, FieldsObjMarshaler.Field] = fs_by_att
|
273
|
+
self._fs_by_key: ta.Mapping[str, FieldsObjMarshaler.Field] = fs_by_key
|
274
|
+
|
275
|
+
@property
|
276
|
+
def ty(self) -> type:
|
277
|
+
return self._ty
|
278
|
+
|
279
|
+
@property
|
280
|
+
def fs(self) -> ta.Sequence[Field]:
|
281
|
+
return self._fs
|
235
282
|
|
236
283
|
#
|
237
284
|
|
238
285
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
239
286
|
d = {}
|
240
|
-
for f in self.
|
287
|
+
for f in self._fs:
|
241
288
|
mv = f.m.marshal(getattr(o, f.att), ctx)
|
242
289
|
if mv is None and f.omit_if_none:
|
243
290
|
continue
|
@@ -248,34 +295,46 @@ class FieldsObjMarshaler(ObjMarshaler):
|
|
248
295
|
kw = {}
|
249
296
|
for k, v in o.items():
|
250
297
|
if (f := self._fs_by_key.get(k)) is None:
|
251
|
-
if not (self.
|
298
|
+
if not (self._non_strict or ctx.options.non_strict_fields):
|
252
299
|
raise KeyError(k)
|
253
300
|
continue
|
254
301
|
kw[f.att] = f.m.unmarshal(v, ctx)
|
255
|
-
return self.
|
302
|
+
return self._ty(**kw)
|
256
303
|
|
257
304
|
|
258
|
-
@dc.dataclass(frozen=True)
|
259
305
|
class SingleFieldObjMarshaler(ObjMarshaler):
|
260
|
-
|
261
|
-
|
306
|
+
def __init__(
|
307
|
+
self,
|
308
|
+
ty: type,
|
309
|
+
fld: str,
|
310
|
+
) -> None:
|
311
|
+
super().__init__()
|
312
|
+
|
313
|
+
self._ty = ty
|
314
|
+
self._fld = fld
|
262
315
|
|
263
316
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
264
|
-
return getattr(o, self.
|
317
|
+
return getattr(o, self._fld)
|
265
318
|
|
266
319
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
267
|
-
return self.
|
320
|
+
return self._ty(**{self._fld: o})
|
268
321
|
|
269
322
|
|
270
|
-
@dc.dataclass(frozen=True)
|
271
323
|
class PolymorphicObjMarshaler(ObjMarshaler):
|
272
324
|
class Impl(ta.NamedTuple):
|
273
325
|
ty: type
|
274
326
|
tag: str
|
275
327
|
m: ObjMarshaler
|
276
328
|
|
277
|
-
|
278
|
-
|
329
|
+
def __init__(
|
330
|
+
self,
|
331
|
+
impls_by_ty: ta.Mapping[type, Impl],
|
332
|
+
impls_by_tag: ta.Mapping[str, Impl],
|
333
|
+
) -> None:
|
334
|
+
super().__init__()
|
335
|
+
|
336
|
+
self._impls_by_ty = impls_by_ty
|
337
|
+
self._impls_by_tag = impls_by_tag
|
279
338
|
|
280
339
|
@classmethod
|
281
340
|
def of(cls, impls: ta.Iterable[Impl]) -> 'PolymorphicObjMarshaler':
|
@@ -285,24 +344,29 @@ class PolymorphicObjMarshaler(ObjMarshaler):
|
|
285
344
|
)
|
286
345
|
|
287
346
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
288
|
-
impl = self.
|
347
|
+
impl = self._impls_by_ty[type(o)]
|
289
348
|
return {impl.tag: impl.m.marshal(o, ctx)}
|
290
349
|
|
291
350
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
292
351
|
[(t, v)] = o.items()
|
293
|
-
impl = self.
|
352
|
+
impl = self._impls_by_tag[t]
|
294
353
|
return impl.m.unmarshal(v, ctx)
|
295
354
|
|
296
355
|
|
297
|
-
@dc.dataclass(frozen=True)
|
298
356
|
class DatetimeObjMarshaler(ObjMarshaler):
|
299
|
-
|
357
|
+
def __init__(
|
358
|
+
self,
|
359
|
+
ty: type,
|
360
|
+
) -> None:
|
361
|
+
super().__init__()
|
362
|
+
|
363
|
+
self._ty = ty
|
300
364
|
|
301
365
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
302
366
|
return o.isoformat()
|
303
367
|
|
304
368
|
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
305
|
-
return self.
|
369
|
+
return self._ty.fromisoformat(o) # type: ignore
|
306
370
|
|
307
371
|
|
308
372
|
class DecimalObjMarshaler(ObjMarshaler):
|
@@ -410,7 +474,78 @@ class OBJ_MARSHALER_OMIT_IF_NONE(ObjMarshalerFieldMetadata): # noqa
|
|
410
474
|
##
|
411
475
|
|
412
476
|
|
413
|
-
class ObjMarshalerManager:
|
477
|
+
class ObjMarshalerManager(Abstract):
|
478
|
+
@abc.abstractmethod
|
479
|
+
def make_obj_marshaler(
|
480
|
+
self,
|
481
|
+
ty: ta.Any,
|
482
|
+
rec: ta.Callable[[ta.Any], ObjMarshaler],
|
483
|
+
*,
|
484
|
+
non_strict_fields: bool = False,
|
485
|
+
) -> ObjMarshaler:
|
486
|
+
raise NotImplementedError
|
487
|
+
|
488
|
+
@abc.abstractmethod
|
489
|
+
def set_obj_marshaler(
|
490
|
+
self,
|
491
|
+
ty: ta.Any,
|
492
|
+
m: ObjMarshaler,
|
493
|
+
*,
|
494
|
+
override: bool = False,
|
495
|
+
) -> None:
|
496
|
+
raise NotImplementedError
|
497
|
+
|
498
|
+
@abc.abstractmethod
|
499
|
+
def get_obj_marshaler(
|
500
|
+
self,
|
501
|
+
ty: ta.Any,
|
502
|
+
*,
|
503
|
+
no_cache: bool = False,
|
504
|
+
**kwargs: ta.Any,
|
505
|
+
) -> ObjMarshaler:
|
506
|
+
raise NotImplementedError
|
507
|
+
|
508
|
+
@abc.abstractmethod
|
509
|
+
def make_context(self, opts: ta.Optional[ObjMarshalOptions]) -> 'ObjMarshalContext':
|
510
|
+
raise NotImplementedError
|
511
|
+
|
512
|
+
#
|
513
|
+
|
514
|
+
def marshal_obj(
|
515
|
+
self,
|
516
|
+
o: ta.Any,
|
517
|
+
ty: ta.Any = None,
|
518
|
+
opts: ta.Optional[ObjMarshalOptions] = None,
|
519
|
+
) -> ta.Any:
|
520
|
+
m = self.get_obj_marshaler(ty if ty is not None else type(o))
|
521
|
+
return m.marshal(o, self.make_context(opts))
|
522
|
+
|
523
|
+
def unmarshal_obj(
|
524
|
+
self,
|
525
|
+
o: ta.Any,
|
526
|
+
ty: ta.Union[ta.Type[T], ta.Any],
|
527
|
+
opts: ta.Optional[ObjMarshalOptions] = None,
|
528
|
+
) -> T:
|
529
|
+
m = self.get_obj_marshaler(ty)
|
530
|
+
return m.unmarshal(o, self.make_context(opts))
|
531
|
+
|
532
|
+
def roundtrip_obj(
|
533
|
+
self,
|
534
|
+
o: ta.Any,
|
535
|
+
ty: ta.Any = None,
|
536
|
+
opts: ta.Optional[ObjMarshalOptions] = None,
|
537
|
+
) -> ta.Any:
|
538
|
+
if ty is None:
|
539
|
+
ty = type(o)
|
540
|
+
m: ta.Any = self.marshal_obj(o, ty, opts)
|
541
|
+
u: ta.Any = self.unmarshal_obj(m, ty, opts)
|
542
|
+
return u
|
543
|
+
|
544
|
+
|
545
|
+
#
|
546
|
+
|
547
|
+
|
548
|
+
class ObjMarshalerManagerImpl(ObjMarshalerManager):
|
414
549
|
def __init__(
|
415
550
|
self,
|
416
551
|
*,
|
@@ -437,6 +572,12 @@ class ObjMarshalerManager:
|
|
437
572
|
|
438
573
|
#
|
439
574
|
|
575
|
+
@classmethod
|
576
|
+
def _is_abstract(cls, ty: type) -> bool:
|
577
|
+
return abc.ABC in ty.__bases__ or Abstract in ty.__bases__
|
578
|
+
|
579
|
+
#
|
580
|
+
|
440
581
|
def make_obj_marshaler(
|
441
582
|
self,
|
442
583
|
ty: ta.Any,
|
@@ -448,12 +589,12 @@ class ObjMarshalerManager:
|
|
448
589
|
if (reg := self._registered_obj_marshalers.get(ty)) is not None:
|
449
590
|
return reg
|
450
591
|
|
451
|
-
if
|
592
|
+
if self._is_abstract(ty):
|
452
593
|
tn = ty.__name__
|
453
594
|
impls: ta.List[ta.Tuple[type, str]] = [ # type: ignore[var-annotated]
|
454
595
|
(ity, ity.__name__)
|
455
596
|
for ity in deep_subclasses(ty)
|
456
|
-
if
|
597
|
+
if not self._is_abstract(ity)
|
457
598
|
]
|
458
599
|
|
459
600
|
if all(itn.endswith(tn) for _, itn in impls):
|
@@ -619,49 +760,24 @@ class ObjMarshalerManager:
|
|
619
760
|
m = self.make_obj_marshaler(ty, rec, **kwargs)
|
620
761
|
finally:
|
621
762
|
del self._proxies[ty]
|
622
|
-
p.
|
763
|
+
p._m = m # noqa
|
623
764
|
|
624
765
|
if not no_cache:
|
625
766
|
self._obj_marshalers[ty] = m
|
626
767
|
return m
|
627
768
|
|
628
|
-
|
629
|
-
|
630
|
-
def _make_context(self, opts: ta.Optional[ObjMarshalOptions]) -> 'ObjMarshalContext':
|
769
|
+
def make_context(self, opts: ta.Optional[ObjMarshalOptions]) -> 'ObjMarshalContext':
|
631
770
|
return ObjMarshalContext(
|
632
771
|
options=opts or self._default_options,
|
633
772
|
manager=self,
|
634
773
|
)
|
635
774
|
|
636
|
-
def marshal_obj(
|
637
|
-
self,
|
638
|
-
o: ta.Any,
|
639
|
-
ty: ta.Any = None,
|
640
|
-
opts: ta.Optional[ObjMarshalOptions] = None,
|
641
|
-
) -> ta.Any:
|
642
|
-
m = self.get_obj_marshaler(ty if ty is not None else type(o))
|
643
|
-
return m.marshal(o, self._make_context(opts))
|
644
775
|
|
645
|
-
|
646
|
-
|
647
|
-
o: ta.Any,
|
648
|
-
ty: ta.Union[ta.Type[T], ta.Any],
|
649
|
-
opts: ta.Optional[ObjMarshalOptions] = None,
|
650
|
-
) -> T:
|
651
|
-
m = self.get_obj_marshaler(ty)
|
652
|
-
return m.unmarshal(o, self._make_context(opts))
|
776
|
+
def new_obj_marshaler_manager(**kwargs: ta.Any) -> ObjMarshalerManager:
|
777
|
+
return ObjMarshalerManagerImpl(**kwargs)
|
653
778
|
|
654
|
-
|
655
|
-
|
656
|
-
o: ta.Any,
|
657
|
-
ty: ta.Any = None,
|
658
|
-
opts: ta.Optional[ObjMarshalOptions] = None,
|
659
|
-
) -> ta.Any:
|
660
|
-
if ty is None:
|
661
|
-
ty = type(o)
|
662
|
-
m: ta.Any = self.marshal_obj(o, ty, opts)
|
663
|
-
u: ta.Any = self.unmarshal_obj(m, ty, opts)
|
664
|
-
return u
|
779
|
+
|
780
|
+
##
|
665
781
|
|
666
782
|
|
667
783
|
@dc.dataclass(frozen=True)
|
@@ -673,7 +789,7 @@ class ObjMarshalContext:
|
|
673
789
|
##
|
674
790
|
|
675
791
|
|
676
|
-
OBJ_MARSHALER_MANAGER =
|
792
|
+
OBJ_MARSHALER_MANAGER = new_obj_marshaler_manager()
|
677
793
|
|
678
794
|
set_obj_marshaler = OBJ_MARSHALER_MANAGER.set_obj_marshaler
|
679
795
|
get_obj_marshaler = OBJ_MARSHALER_MANAGER.get_obj_marshaler
|
omlish/lite/maybes.py
CHANGED
@@ -3,6 +3,8 @@ import abc
|
|
3
3
|
import functools
|
4
4
|
import typing as ta
|
5
5
|
|
6
|
+
from .abstract import Abstract
|
7
|
+
|
6
8
|
|
7
9
|
T = ta.TypeVar('T')
|
8
10
|
U = ta.TypeVar('U')
|
@@ -134,7 +136,7 @@ class Maybe(ta.Generic[T]):
|
|
134
136
|
##
|
135
137
|
|
136
138
|
|
137
|
-
class _Maybe(Maybe[T],
|
139
|
+
class _Maybe(Maybe[T], Abstract):
|
138
140
|
def __lt__(self, other):
|
139
141
|
if not isinstance(other, _Maybe):
|
140
142
|
return NotImplemented
|
omlish/lite/maysync.py
CHANGED
@@ -45,6 +45,8 @@ import sys
|
|
45
45
|
import threading
|
46
46
|
import typing as ta
|
47
47
|
|
48
|
+
from .abstract import Abstract
|
49
|
+
|
48
50
|
|
49
51
|
T = ta.TypeVar('T')
|
50
52
|
O = ta.TypeVar('O')
|
@@ -58,7 +60,7 @@ _MaysyncRA = ta.TypeVar('_MaysyncRA')
|
|
58
60
|
##
|
59
61
|
|
60
62
|
|
61
|
-
class AnyMaysyncFn(
|
63
|
+
class AnyMaysyncFn(Abstract, ta.Generic[_MaysyncRS, _MaysyncRA]):
|
62
64
|
def __init__(
|
63
65
|
self,
|
64
66
|
s: ta.Callable[..., _MaysyncRS],
|
@@ -105,7 +107,7 @@ class MaywaitableAlreadyConsumedError(Exception):
|
|
105
107
|
pass
|
106
108
|
|
107
109
|
|
108
|
-
class AnyMaywaitable(
|
110
|
+
class AnyMaywaitable(Abstract, ta.Generic[_MaysyncX]):
|
109
111
|
@ta.final
|
110
112
|
def __init__(
|
111
113
|
self,
|
omlish/lite/objects.py
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# ruff: noqa: UP006 UP036 UP045
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
|
5
|
+
T = ta.TypeVar('T')
|
6
|
+
|
7
|
+
|
8
|
+
##
|
9
|
+
|
10
|
+
|
11
|
+
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
12
|
+
seen = set()
|
13
|
+
todo = list(reversed(cls.__subclasses__()))
|
14
|
+
while todo:
|
15
|
+
cur = todo.pop()
|
16
|
+
if cur in seen:
|
17
|
+
continue
|
18
|
+
seen.add(cur)
|
19
|
+
yield cur
|
20
|
+
todo.extend(reversed(cur.__subclasses__()))
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
|
25
|
+
|
26
|
+
def mro_owner_dict(
|
27
|
+
instance_cls: type,
|
28
|
+
owner_cls: ta.Optional[type] = None,
|
29
|
+
*,
|
30
|
+
bottom_up_key_order: bool = False,
|
31
|
+
sort_keys: bool = False,
|
32
|
+
) -> ta.Mapping[str, ta.Tuple[type, ta.Any]]:
|
33
|
+
if owner_cls is None:
|
34
|
+
owner_cls = instance_cls
|
35
|
+
|
36
|
+
mro = instance_cls.__mro__[-2::-1]
|
37
|
+
try:
|
38
|
+
pos = mro.index(owner_cls)
|
39
|
+
except ValueError:
|
40
|
+
raise TypeError(f'Owner class {owner_cls} not in mro of instance class {instance_cls}') from None
|
41
|
+
|
42
|
+
dct: ta.Dict[str, ta.Tuple[type, ta.Any]] = {}
|
43
|
+
if not bottom_up_key_order:
|
44
|
+
for cur_cls in mro[:pos + 1][::-1]:
|
45
|
+
for k, v in cur_cls.__dict__.items():
|
46
|
+
if k not in dct:
|
47
|
+
dct[k] = (cur_cls, v)
|
48
|
+
|
49
|
+
else:
|
50
|
+
for cur_cls in mro[:pos + 1]:
|
51
|
+
dct.update({k: (cur_cls, v) for k, v in cur_cls.__dict__.items()})
|
52
|
+
|
53
|
+
if sort_keys:
|
54
|
+
dct = dict(sorted(dct.items(), key=lambda t: t[0]))
|
55
|
+
|
56
|
+
return dct
|
57
|
+
|
58
|
+
|
59
|
+
def mro_dict(
|
60
|
+
instance_cls: type,
|
61
|
+
owner_cls: ta.Optional[type] = None,
|
62
|
+
*,
|
63
|
+
bottom_up_key_order: bool = False,
|
64
|
+
sort_keys: bool = False,
|
65
|
+
) -> ta.Mapping[str, ta.Any]:
|
66
|
+
return {
|
67
|
+
k: v
|
68
|
+
for k, (o, v) in mro_owner_dict(
|
69
|
+
instance_cls,
|
70
|
+
owner_cls,
|
71
|
+
bottom_up_key_order=bottom_up_key_order,
|
72
|
+
sort_keys=sort_keys,
|
73
|
+
).items()
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
def dir_dict(o: ta.Any) -> ta.Dict[str, ta.Any]:
|
78
|
+
return {
|
79
|
+
a: getattr(o, a)
|
80
|
+
for a in dir(o)
|
81
|
+
}
|