omlish 0.0.0.dev226__py3-none-any.whl → 0.0.0.dev228__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 +3 -3
- omlish/diag/lslocks.py +4 -4
- omlish/diag/lsof.py +3 -4
- omlish/diag/ps.py +9 -0
- omlish/lite/timeouts.py +1 -1
- omlish/marshal/__init__.py +39 -24
- omlish/marshal/composite/__init__.py +0 -0
- omlish/marshal/{iterables.py → composite/iterables.py} +10 -10
- omlish/marshal/{literals.py → composite/literals.py} +9 -9
- omlish/marshal/{mappings.py → composite/mappings.py} +10 -10
- omlish/marshal/{maybes.py → composite/maybes.py} +11 -11
- omlish/marshal/{newtypes.py → composite/newtypes.py} +8 -8
- omlish/marshal/{optionals.py → composite/optionals.py} +9 -9
- omlish/marshal/objects/__init__.py +7 -0
- omlish/marshal/{dataclasses.py → objects/dataclasses.py} +24 -24
- omlish/marshal/{helpers.py → objects/helpers.py} +6 -3
- omlish/marshal/objects/marshal.py +108 -0
- omlish/marshal/objects/metadata.py +124 -0
- omlish/marshal/{namedtuples.py → objects/namedtuples.py} +16 -16
- omlish/marshal/objects/unmarshal.py +141 -0
- omlish/marshal/polymorphism/__init__.py +7 -0
- omlish/marshal/polymorphism/marshal.py +66 -0
- omlish/marshal/polymorphism/metadata.py +140 -0
- omlish/marshal/{unions.py → polymorphism/unions.py} +18 -18
- omlish/marshal/polymorphism/unmarshal.py +73 -0
- omlish/marshal/singular/__init__.py +0 -0
- omlish/marshal/{any.py → singular/any.py} +8 -8
- omlish/marshal/{base64.py → singular/base64.py} +9 -9
- omlish/marshal/{datetimes.py → singular/datetimes.py} +9 -9
- omlish/marshal/{enums.py → singular/enums.py} +9 -9
- omlish/marshal/{numbers.py → singular/numbers.py} +8 -8
- omlish/marshal/{primitives.py → singular/primitives.py} +8 -8
- omlish/marshal/{uuids.py → singular/uuids.py} +8 -8
- omlish/marshal/standard.py +32 -32
- omlish/os/death.py +70 -4
- omlish/os/fcntl.py +11 -12
- omlish/os/files.py +18 -3
- omlish/os/forkhooks.py +215 -0
- omlish/os/pidfiles/manager.py +4 -1
- omlish/os/pidfiles/pidfile.py +31 -11
- omlish/os/pidfiles/pinning.py +250 -0
- omlish/sockets/bind.py +4 -4
- {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/METADATA +3 -3
- {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/RECORD +48 -38
- omlish/marshal/objects.py +0 -317
- omlish/marshal/polymorphism.py +0 -267
- {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/top_level.txt +0 -0
omlish/marshal/objects.py
DELETED
@@ -1,317 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- cfg naming
|
4
|
-
- adapters for dataclasses / namedtuples / user objects (as configured)
|
5
|
-
- mro-merge ObjectMetadata
|
6
|
-
- key ordering override - like slice, -1 means last
|
7
|
-
"""
|
8
|
-
import collections.abc
|
9
|
-
import typing as ta
|
10
|
-
|
11
|
-
from .. import cached
|
12
|
-
from .. import check
|
13
|
-
from .. import collections as col
|
14
|
-
from .. import dataclasses as dc
|
15
|
-
from .. import lang
|
16
|
-
from .. import reflect as rfl
|
17
|
-
from .base import MarshalContext
|
18
|
-
from .base import Marshaler
|
19
|
-
from .base import MarshalerFactory
|
20
|
-
from .base import UnmarshalContext
|
21
|
-
from .base import Unmarshaler
|
22
|
-
from .base import UnmarshalerFactory
|
23
|
-
from .naming import Naming
|
24
|
-
from .values import Value
|
25
|
-
|
26
|
-
|
27
|
-
##
|
28
|
-
|
29
|
-
|
30
|
-
@dc.dataclass(frozen=True, kw_only=True)
|
31
|
-
class FieldOptions:
|
32
|
-
omit_if: ta.Callable[[ta.Any], bool] | None = None
|
33
|
-
|
34
|
-
default: lang.Maybe[ta.Any] = dc.xfield(default=lang.empty(), check_type=lang.Maybe)
|
35
|
-
|
36
|
-
embed: bool = False
|
37
|
-
|
38
|
-
no_marshal: bool = False
|
39
|
-
no_unmarshal: bool = False
|
40
|
-
|
41
|
-
|
42
|
-
DEFAULT_FIELD_OPTIONS = FieldOptions()
|
43
|
-
FIELD_OPTIONS_KWARGS: frozenset[str] = frozenset(dc.fields_dict(FieldOptions).keys())
|
44
|
-
|
45
|
-
|
46
|
-
@dc.dataclass(frozen=True, kw_only=True)
|
47
|
-
class FieldMetadata:
|
48
|
-
name: str | None = None
|
49
|
-
alts: ta.Iterable[str] | None = None
|
50
|
-
|
51
|
-
options: FieldOptions = DEFAULT_FIELD_OPTIONS
|
52
|
-
|
53
|
-
marshaler: Marshaler | None = dc.xfield(None, check_type=(Marshaler, None))
|
54
|
-
marshaler_factory: MarshalerFactory | None = None
|
55
|
-
|
56
|
-
unmarshaler: Unmarshaler | None = dc.xfield(None, check_type=(Unmarshaler, None))
|
57
|
-
unmarshaler_factory: UnmarshalerFactory | None = None
|
58
|
-
|
59
|
-
def update(self, **kwargs: ta.Any) -> 'FieldMetadata':
|
60
|
-
okw = {k: v for k, v in kwargs.items() if k in FIELD_OPTIONS_KWARGS}
|
61
|
-
mkw = {k: v for k, v in kwargs.items() if k not in FIELD_OPTIONS_KWARGS}
|
62
|
-
return dc.replace(
|
63
|
-
self,
|
64
|
-
**(dict(options=dc.replace(self.options, **okw)) if okw else {}),
|
65
|
-
**mkw,
|
66
|
-
)
|
67
|
-
|
68
|
-
|
69
|
-
@dc.dataclass(frozen=True, kw_only=True)
|
70
|
-
class ObjectMetadata:
|
71
|
-
field_naming: Naming | None = None
|
72
|
-
|
73
|
-
unknown_field: str | None = None
|
74
|
-
source_field: str | None = None
|
75
|
-
|
76
|
-
@cached.property
|
77
|
-
def specials(self) -> 'ObjectSpecials':
|
78
|
-
return ObjectSpecials(
|
79
|
-
unknown=self.unknown_field,
|
80
|
-
source=self.source_field,
|
81
|
-
)
|
82
|
-
|
83
|
-
field_defaults: FieldMetadata = FieldMetadata()
|
84
|
-
|
85
|
-
ignore_unknown: bool = False
|
86
|
-
|
87
|
-
|
88
|
-
@dc.dataclass(frozen=True, kw_only=True)
|
89
|
-
class ObjectSpecials:
|
90
|
-
unknown: str | None = None
|
91
|
-
source: str | None = None
|
92
|
-
|
93
|
-
@cached.property
|
94
|
-
def set(self) -> frozenset[str]:
|
95
|
-
return frozenset(v for v in dc.asdict(self).values() if v is not None)
|
96
|
-
|
97
|
-
|
98
|
-
##
|
99
|
-
|
100
|
-
|
101
|
-
@dc.dataclass(frozen=True, kw_only=True)
|
102
|
-
class FieldInfo:
|
103
|
-
name: str
|
104
|
-
type: ta.Any
|
105
|
-
|
106
|
-
marshal_name: str | None
|
107
|
-
unmarshal_names: ta.Sequence[str]
|
108
|
-
|
109
|
-
metadata: FieldMetadata = FieldMetadata()
|
110
|
-
|
111
|
-
options: FieldOptions = FieldOptions()
|
112
|
-
|
113
|
-
|
114
|
-
@dc.dataclass(frozen=True)
|
115
|
-
class FieldInfos:
|
116
|
-
lst: ta.Sequence[FieldInfo]
|
117
|
-
|
118
|
-
def __iter__(self) -> ta.Iterator[FieldInfo]:
|
119
|
-
return iter(self.lst)
|
120
|
-
|
121
|
-
def __len__(self) -> int:
|
122
|
-
return len(self.lst)
|
123
|
-
|
124
|
-
@cached.property
|
125
|
-
@dc.init
|
126
|
-
def by_name(self) -> ta.Mapping[str, FieldInfo]:
|
127
|
-
return col.make_map(((fi.name, fi) for fi in self), strict=True)
|
128
|
-
|
129
|
-
@cached.property
|
130
|
-
@dc.init
|
131
|
-
def by_marshal_name(self) -> ta.Mapping[str, FieldInfo]:
|
132
|
-
return col.make_map(((fi.marshal_name, fi) for fi in self if fi.marshal_name is not None), strict=True)
|
133
|
-
|
134
|
-
@cached.property
|
135
|
-
@dc.init
|
136
|
-
def by_unmarshal_name(self) -> ta.Mapping[str, FieldInfo]:
|
137
|
-
return col.make_map(((n, fi) for fi in self for n in fi.unmarshal_names), strict=True)
|
138
|
-
|
139
|
-
|
140
|
-
##
|
141
|
-
|
142
|
-
|
143
|
-
@dc.dataclass(frozen=True)
|
144
|
-
class ObjectMarshaler(Marshaler):
|
145
|
-
fields: ta.Sequence[tuple[FieldInfo, Marshaler]]
|
146
|
-
|
147
|
-
_: dc.KW_ONLY
|
148
|
-
|
149
|
-
specials: ObjectSpecials = ObjectSpecials()
|
150
|
-
|
151
|
-
def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
|
152
|
-
ret: dict[str, ta.Any] = {}
|
153
|
-
for fi, m in self.fields:
|
154
|
-
v = getattr(o, fi.name)
|
155
|
-
|
156
|
-
if fi.options.omit_if is not None and fi.options.omit_if(v):
|
157
|
-
continue
|
158
|
-
|
159
|
-
if fi.name in self.specials.set:
|
160
|
-
continue
|
161
|
-
|
162
|
-
mn = fi.marshal_name
|
163
|
-
if mn is None:
|
164
|
-
continue
|
165
|
-
|
166
|
-
mv = m.marshal(ctx, v)
|
167
|
-
|
168
|
-
if fi.options.embed:
|
169
|
-
for ek, ev in check.isinstance(mv, collections.abc.Mapping).items():
|
170
|
-
ret[mn + check.non_empty_str(ek)] = ev
|
171
|
-
|
172
|
-
else:
|
173
|
-
ret[mn] = mv
|
174
|
-
|
175
|
-
if self.specials.unknown is not None:
|
176
|
-
if (ukf := getattr(o, self.specials.unknown)):
|
177
|
-
if (dks := set(ret) & set(ukf)):
|
178
|
-
raise KeyError(f'Unknown field keys duplicate fields: {dks!r}')
|
179
|
-
|
180
|
-
ret.update(ukf) # FIXME: marshal?
|
181
|
-
|
182
|
-
return ret
|
183
|
-
|
184
|
-
|
185
|
-
@dc.dataclass(frozen=True)
|
186
|
-
class SimpleObjectMarshalerFactory(MarshalerFactory):
|
187
|
-
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
188
|
-
|
189
|
-
_: dc.KW_ONLY
|
190
|
-
|
191
|
-
specials: ObjectSpecials = ObjectSpecials()
|
192
|
-
|
193
|
-
def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
|
194
|
-
return isinstance(rty, type) and rty in self.dct
|
195
|
-
|
196
|
-
def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
197
|
-
ty = check.isinstance(rty, type)
|
198
|
-
|
199
|
-
flds = FieldInfos(self.dct[ty])
|
200
|
-
|
201
|
-
fields = [
|
202
|
-
(fi, ctx.make(fi.type))
|
203
|
-
for fi in flds
|
204
|
-
]
|
205
|
-
|
206
|
-
return ObjectMarshaler(
|
207
|
-
fields,
|
208
|
-
specials=self.specials,
|
209
|
-
)
|
210
|
-
|
211
|
-
|
212
|
-
##
|
213
|
-
|
214
|
-
|
215
|
-
@dc.dataclass(frozen=True)
|
216
|
-
class ObjectUnmarshaler(Unmarshaler):
|
217
|
-
cls: type
|
218
|
-
fields_by_unmarshal_name: ta.Mapping[str, tuple[FieldInfo, Unmarshaler]]
|
219
|
-
|
220
|
-
_: dc.KW_ONLY
|
221
|
-
|
222
|
-
specials: ObjectSpecials = ObjectSpecials()
|
223
|
-
|
224
|
-
defaults: ta.Mapping[str, ta.Any] | None = None
|
225
|
-
|
226
|
-
embeds: ta.Mapping[str, type] | None = None
|
227
|
-
embeds_by_unmarshal_name: ta.Mapping[str, tuple[str, str]] | None = None
|
228
|
-
|
229
|
-
ignore_unknown: bool = False
|
230
|
-
|
231
|
-
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
232
|
-
ma = check.isinstance(v, collections.abc.Mapping)
|
233
|
-
|
234
|
-
u: ta.Any
|
235
|
-
kw: dict[str, ta.Any] = {}
|
236
|
-
ukf: dict[str, ta.Any] | None = None
|
237
|
-
|
238
|
-
ekws: dict[str, dict[str, ta.Any]] = {en: {} for en in self.embeds or ()}
|
239
|
-
|
240
|
-
if self.specials.source is not None:
|
241
|
-
kw[self.specials.source] = v
|
242
|
-
|
243
|
-
if self.specials.unknown is not None:
|
244
|
-
kw[self.specials.unknown] = ukf = {}
|
245
|
-
|
246
|
-
for k, mv in ma.items():
|
247
|
-
ks = check.isinstance(k, str)
|
248
|
-
|
249
|
-
try:
|
250
|
-
fi, u = self.fields_by_unmarshal_name[ks]
|
251
|
-
|
252
|
-
except KeyError:
|
253
|
-
if ukf is not None:
|
254
|
-
ukf[ks] = mv # FIXME: unmarshal?
|
255
|
-
continue
|
256
|
-
|
257
|
-
if self.ignore_unknown:
|
258
|
-
continue
|
259
|
-
|
260
|
-
raise
|
261
|
-
|
262
|
-
if self.embeds_by_unmarshal_name and (en := self.embeds_by_unmarshal_name.get(ks)):
|
263
|
-
tkw, tk = ekws[en[0]], en[1]
|
264
|
-
else:
|
265
|
-
tkw, tk = kw, fi.name
|
266
|
-
|
267
|
-
if tk in tkw:
|
268
|
-
raise KeyError(f'Duplicate keys for field {tk!r}: {ks!r}')
|
269
|
-
|
270
|
-
tkw[tk] = u.unmarshal(ctx, mv)
|
271
|
-
|
272
|
-
for em, ecls in self.embeds.items() if self.embeds else ():
|
273
|
-
ekw = ekws[em]
|
274
|
-
ev = ecls(**ekw)
|
275
|
-
kw[em] = ev
|
276
|
-
|
277
|
-
if self.defaults:
|
278
|
-
for dk, dv in self.defaults.items():
|
279
|
-
kw.setdefault(dk, dv)
|
280
|
-
|
281
|
-
return self.cls(**kw)
|
282
|
-
|
283
|
-
|
284
|
-
@dc.dataclass(frozen=True)
|
285
|
-
class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
|
286
|
-
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
287
|
-
|
288
|
-
_: dc.KW_ONLY
|
289
|
-
|
290
|
-
specials: ObjectSpecials = ObjectSpecials()
|
291
|
-
|
292
|
-
def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
|
293
|
-
return isinstance(rty, type) and rty in self.dct
|
294
|
-
|
295
|
-
def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
|
296
|
-
ty = check.isinstance(rty, type)
|
297
|
-
|
298
|
-
flds = FieldInfos(self.dct[ty])
|
299
|
-
|
300
|
-
fields_by_unmarshal_name = {
|
301
|
-
n: (fi, ctx.make(fi.type))
|
302
|
-
for fi in flds
|
303
|
-
for n in fi.unmarshal_names
|
304
|
-
}
|
305
|
-
|
306
|
-
defaults = {
|
307
|
-
fi.name: fi.options.default.must()
|
308
|
-
for fi in flds
|
309
|
-
if fi.options.default.present
|
310
|
-
}
|
311
|
-
|
312
|
-
return ObjectUnmarshaler(
|
313
|
-
ty,
|
314
|
-
fields_by_unmarshal_name,
|
315
|
-
specials=self.specials,
|
316
|
-
defaults=defaults,
|
317
|
-
)
|
omlish/marshal/polymorphism.py
DELETED
@@ -1,267 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- auto-gen from __subclasses__ if abstract
|
4
|
-
- cfg: unless prefixed with _ or abstract
|
5
|
-
- iff Sealed
|
6
|
-
- auto-name
|
7
|
-
"""
|
8
|
-
import collections.abc
|
9
|
-
import dataclasses as dc
|
10
|
-
import typing as ta
|
11
|
-
|
12
|
-
from .. import check
|
13
|
-
from .. import lang
|
14
|
-
from .. import reflect as rfl
|
15
|
-
from .base import MarshalContext
|
16
|
-
from .base import Marshaler
|
17
|
-
from .base import MarshalerFactory
|
18
|
-
from .base import UnmarshalContext
|
19
|
-
from .base import Unmarshaler
|
20
|
-
from .base import UnmarshalerFactory
|
21
|
-
from .naming import Naming
|
22
|
-
from .naming import translate_name
|
23
|
-
from .registries import RegistryItem
|
24
|
-
from .values import Value
|
25
|
-
|
26
|
-
|
27
|
-
##
|
28
|
-
|
29
|
-
|
30
|
-
class TypeTagging(RegistryItem, lang.Abstract, lang.Sealed):
|
31
|
-
pass
|
32
|
-
|
33
|
-
|
34
|
-
class WrapperTypeTagging(TypeTagging, lang.Final):
|
35
|
-
pass
|
36
|
-
|
37
|
-
|
38
|
-
@dc.dataclass(frozen=True)
|
39
|
-
class FieldTypeTagging(TypeTagging, lang.Final):
|
40
|
-
field: str
|
41
|
-
|
42
|
-
|
43
|
-
##
|
44
|
-
|
45
|
-
|
46
|
-
@dc.dataclass(frozen=True)
|
47
|
-
class Impl:
|
48
|
-
ty: type
|
49
|
-
tag: str
|
50
|
-
alts: ta.AbstractSet[str] = frozenset()
|
51
|
-
|
52
|
-
|
53
|
-
class Impls(ta.Sequence[Impl]):
|
54
|
-
def __init__(
|
55
|
-
self,
|
56
|
-
lst: ta.Iterable[Impl],
|
57
|
-
) -> None:
|
58
|
-
super().__init__()
|
59
|
-
self._lst = list(lst)
|
60
|
-
|
61
|
-
by_ty: dict[type, Impl] = {}
|
62
|
-
by_tag: dict[str, Impl] = {}
|
63
|
-
for i in self._lst:
|
64
|
-
if i.ty in by_ty:
|
65
|
-
raise TypeError(i.ty)
|
66
|
-
if i.tag in by_tag:
|
67
|
-
raise NameError(i.tag)
|
68
|
-
for a in i.alts:
|
69
|
-
if a in by_tag:
|
70
|
-
raise NameError(a)
|
71
|
-
by_ty[i.ty] = i
|
72
|
-
by_tag[i.tag] = i
|
73
|
-
for a in i.alts:
|
74
|
-
by_tag[a] = i
|
75
|
-
self._by_ty = by_ty
|
76
|
-
self._by_tag = by_tag
|
77
|
-
|
78
|
-
def __iter__(self) -> ta.Iterator[Impl]:
|
79
|
-
return iter(self._lst)
|
80
|
-
|
81
|
-
def __len__(self) -> int:
|
82
|
-
return len(self._lst)
|
83
|
-
|
84
|
-
@ta.overload
|
85
|
-
def __getitem__(self, index: int) -> Impl: ...
|
86
|
-
|
87
|
-
@ta.overload
|
88
|
-
def __getitem__(self, index: slice) -> ta.Sequence[Impl]: ...
|
89
|
-
|
90
|
-
def __getitem__(self, index):
|
91
|
-
return self._lst[index]
|
92
|
-
|
93
|
-
@property
|
94
|
-
def by_ty(self) -> ta.Mapping[type, Impl]:
|
95
|
-
return self._by_ty
|
96
|
-
|
97
|
-
@property
|
98
|
-
def by_tag(self) -> ta.Mapping[str, Impl]:
|
99
|
-
return self._by_tag
|
100
|
-
|
101
|
-
|
102
|
-
class Polymorphism:
|
103
|
-
def __init__(
|
104
|
-
self,
|
105
|
-
ty: type,
|
106
|
-
impls: ta.Iterable[Impl],
|
107
|
-
) -> None:
|
108
|
-
super().__init__()
|
109
|
-
self._ty = ty
|
110
|
-
self._impls = Impls(impls)
|
111
|
-
|
112
|
-
for i in self._impls:
|
113
|
-
if not issubclass(i.ty, ty):
|
114
|
-
raise TypeError(i.ty, ty)
|
115
|
-
|
116
|
-
@property
|
117
|
-
def ty(self) -> type:
|
118
|
-
return self._ty
|
119
|
-
|
120
|
-
@property
|
121
|
-
def impls(self) -> Impls:
|
122
|
-
return self._impls
|
123
|
-
|
124
|
-
|
125
|
-
def polymorphism_from_subclasses(
|
126
|
-
ty: type,
|
127
|
-
*,
|
128
|
-
naming: Naming | None = None,
|
129
|
-
strip_suffix: bool = False,
|
130
|
-
) -> Polymorphism:
|
131
|
-
dct: dict[str, Impl] = {}
|
132
|
-
|
133
|
-
seen: set[type] = set()
|
134
|
-
todo: list[type] = [ty]
|
135
|
-
while todo:
|
136
|
-
cur = todo.pop()
|
137
|
-
seen.add(cur)
|
138
|
-
|
139
|
-
todo.extend(nxt for nxt in cur.__subclasses__() if nxt not in seen)
|
140
|
-
|
141
|
-
if lang.is_abstract_class(cur):
|
142
|
-
continue
|
143
|
-
|
144
|
-
name = cur.__name__
|
145
|
-
if strip_suffix:
|
146
|
-
name = lang.strip_suffix(name, ty.__name__)
|
147
|
-
if naming is not None:
|
148
|
-
name = translate_name(name, naming)
|
149
|
-
if name in dct:
|
150
|
-
raise KeyError(f'Duplicate name: {name}')
|
151
|
-
|
152
|
-
dct[name] = Impl(
|
153
|
-
cur,
|
154
|
-
name,
|
155
|
-
)
|
156
|
-
|
157
|
-
return Polymorphism(ty, dct.values())
|
158
|
-
|
159
|
-
|
160
|
-
##
|
161
|
-
|
162
|
-
|
163
|
-
@dc.dataclass(frozen=True)
|
164
|
-
class WrapperPolymorphismMarshaler(Marshaler):
|
165
|
-
m: ta.Mapping[type, tuple[str, Marshaler]]
|
166
|
-
|
167
|
-
def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
|
168
|
-
tag, m = self.m[type(o)]
|
169
|
-
return {tag: m.marshal(ctx, o)}
|
170
|
-
|
171
|
-
|
172
|
-
@dc.dataclass(frozen=True)
|
173
|
-
class FieldPolymorphismMarshaler(Marshaler):
|
174
|
-
m: ta.Mapping[type, tuple[str, Marshaler]]
|
175
|
-
tf: str
|
176
|
-
|
177
|
-
def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
|
178
|
-
tag, m = self.m[type(o)]
|
179
|
-
return {self.tf: tag, **m.marshal(ctx, o)} # type: ignore
|
180
|
-
|
181
|
-
|
182
|
-
def make_polymorphism_marshaler(
|
183
|
-
impls: Impls,
|
184
|
-
tt: TypeTagging,
|
185
|
-
ctx: MarshalContext,
|
186
|
-
) -> Marshaler:
|
187
|
-
m = {
|
188
|
-
i.ty: (i.tag, ctx.make(i.ty))
|
189
|
-
for i in impls
|
190
|
-
}
|
191
|
-
if isinstance(tt, WrapperTypeTagging):
|
192
|
-
return WrapperPolymorphismMarshaler(m)
|
193
|
-
elif isinstance(tt, FieldTypeTagging):
|
194
|
-
return FieldPolymorphismMarshaler(m, tt.field)
|
195
|
-
else:
|
196
|
-
raise TypeError(tt)
|
197
|
-
|
198
|
-
|
199
|
-
@dc.dataclass(frozen=True)
|
200
|
-
class PolymorphismMarshalerFactory(MarshalerFactory):
|
201
|
-
p: Polymorphism
|
202
|
-
tt: TypeTagging = WrapperTypeTagging()
|
203
|
-
|
204
|
-
def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
|
205
|
-
return rty is self.p.ty
|
206
|
-
|
207
|
-
def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
208
|
-
check.is_(rty, self.p.ty)
|
209
|
-
return make_polymorphism_marshaler(self.p.impls, self.tt, ctx)
|
210
|
-
|
211
|
-
|
212
|
-
##
|
213
|
-
|
214
|
-
|
215
|
-
@dc.dataclass(frozen=True)
|
216
|
-
class WrapperPolymorphismUnmarshaler(Unmarshaler):
|
217
|
-
m: ta.Mapping[str, Unmarshaler]
|
218
|
-
|
219
|
-
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
|
220
|
-
ma = check.isinstance(v, collections.abc.Mapping)
|
221
|
-
[(tag, iv)] = ma.items()
|
222
|
-
u = self.m[tag]
|
223
|
-
return u.unmarshal(ctx, iv)
|
224
|
-
|
225
|
-
|
226
|
-
@dc.dataclass(frozen=True)
|
227
|
-
class FieldPolymorphismUnmarshaler(Unmarshaler):
|
228
|
-
m: ta.Mapping[str, Unmarshaler]
|
229
|
-
tf: str
|
230
|
-
|
231
|
-
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
|
232
|
-
ma = dict(check.isinstance(v, collections.abc.Mapping))
|
233
|
-
tag = ma.pop(self.tf)
|
234
|
-
u = self.m[tag]
|
235
|
-
return u.unmarshal(ctx, ma)
|
236
|
-
|
237
|
-
|
238
|
-
def make_polymorphism_unmarshaler(
|
239
|
-
impls: Impls,
|
240
|
-
tt: TypeTagging,
|
241
|
-
ctx: UnmarshalContext,
|
242
|
-
) -> Unmarshaler:
|
243
|
-
m = {
|
244
|
-
t: u
|
245
|
-
for i in impls
|
246
|
-
for u in [ctx.make(i.ty)]
|
247
|
-
for t in [i.tag, *i.alts]
|
248
|
-
}
|
249
|
-
if isinstance(tt, WrapperTypeTagging):
|
250
|
-
return WrapperPolymorphismUnmarshaler(m)
|
251
|
-
elif isinstance(tt, FieldTypeTagging):
|
252
|
-
return FieldPolymorphismUnmarshaler(m, tt.field)
|
253
|
-
else:
|
254
|
-
raise TypeError(tt)
|
255
|
-
|
256
|
-
|
257
|
-
@dc.dataclass(frozen=True)
|
258
|
-
class PolymorphismUnmarshalerFactory(UnmarshalerFactory):
|
259
|
-
p: Polymorphism
|
260
|
-
tt: TypeTagging = WrapperTypeTagging()
|
261
|
-
|
262
|
-
def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
|
263
|
-
return rty is self.p.ty
|
264
|
-
|
265
|
-
def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
|
266
|
-
check.is_(rty, self.p.ty)
|
267
|
-
return make_polymorphism_unmarshaler(self.p.impls, self.tt, ctx)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|