omlish 0.0.0.dev453__py3-none-any.whl → 0.0.0.dev455__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/collections/identity.py +1 -0
- omlish/dataclasses/__init__.py +2 -0
- omlish/funcs/guard.py +27 -16
- omlish/lang/__init__.py +1 -0
- omlish/lang/functions.py +2 -2
- omlish/lang/iterables.py +8 -0
- omlish/lite/attrops.py +2 -0
- omlish/lite/dataclasses.py +30 -0
- omlish/marshal/__init__.py +16 -11
- omlish/marshal/base/contexts.py +33 -20
- omlish/marshal/base/funcs.py +8 -11
- omlish/marshal/base/options.py +8 -0
- omlish/marshal/base/types.py +38 -14
- omlish/marshal/composite/iterables.py +33 -20
- omlish/marshal/composite/literals.py +16 -18
- omlish/marshal/composite/mappings.py +36 -23
- omlish/marshal/composite/maybes.py +29 -19
- omlish/marshal/composite/newtypes.py +16 -16
- omlish/marshal/composite/optionals.py +14 -14
- omlish/marshal/composite/special.py +15 -15
- omlish/marshal/composite/unions/__init__.py +0 -0
- omlish/marshal/composite/unions/literals.py +93 -0
- omlish/marshal/composite/unions/primitives.py +103 -0
- omlish/marshal/factories/invalidate.py +18 -68
- omlish/marshal/factories/method.py +26 -0
- omlish/marshal/factories/moduleimport/factories.py +15 -56
- omlish/marshal/factories/multi.py +13 -25
- omlish/marshal/factories/recursive.py +42 -56
- omlish/marshal/factories/typecache.py +20 -77
- omlish/marshal/factories/typemap.py +42 -43
- omlish/marshal/objects/dataclasses.py +129 -106
- omlish/marshal/objects/marshal.py +18 -14
- omlish/marshal/objects/namedtuples.py +48 -42
- omlish/marshal/objects/unmarshal.py +19 -15
- omlish/marshal/polymorphism/marshal.py +9 -11
- omlish/marshal/polymorphism/unions.py +17 -11
- omlish/marshal/polymorphism/unmarshal.py +9 -10
- omlish/marshal/singular/enums.py +14 -18
- omlish/marshal/standard.py +8 -8
- omlish/marshal/trivial/any.py +1 -1
- omlish/marshal/trivial/forbidden.py +21 -26
- omlish/os/forkhooks.py +4 -0
- omlish/specs/jsonrpc/_marshal.py +33 -24
- omlish/specs/openapi/_marshal.py +30 -21
- omlish/typedvalues/marshal.py +83 -57
- {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/RECORD +52 -52
- omlish/funcs/match.py +0 -229
- omlish/marshal/composite/unions.py +0 -213
- omlish/marshal/factories/match.py +0 -34
- omlish/marshal/factories/simple.py +0 -28
- {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/top_level.txt +0 -0
@@ -3,63 +3,62 @@ import typing as ta
|
|
3
3
|
from ... import check
|
4
4
|
from ... import dataclasses as dc
|
5
5
|
from ... import reflect as rfl
|
6
|
-
from
|
7
|
-
from ..base.contexts import
|
8
|
-
from ..base.contexts import UnmarshalContext
|
6
|
+
from ..base.contexts import MarshalFactoryContext
|
7
|
+
from ..base.contexts import UnmarshalFactoryContext
|
9
8
|
from ..base.types import Marshaler
|
10
9
|
from ..base.types import MarshalerFactory
|
11
|
-
from ..base.types import MarshalerMaker
|
12
10
|
from ..base.types import Unmarshaler
|
13
11
|
from ..base.types import UnmarshalerFactory
|
14
|
-
from ..base.types import UnmarshalerMaker
|
15
|
-
|
16
|
-
|
17
|
-
R = ta.TypeVar('R')
|
18
|
-
C = ta.TypeVar('C')
|
19
12
|
|
20
13
|
|
21
14
|
##
|
22
15
|
|
23
16
|
|
24
17
|
@dc.dataclass(frozen=True)
|
25
|
-
class
|
26
|
-
m: ta.Mapping[rfl.Type,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
return rty in self.m
|
36
|
-
|
37
|
-
def fn(self, ctx: C, rty: rfl.Type) -> R:
|
18
|
+
class TypeMapMarshalerFactory(MarshalerFactory):
|
19
|
+
m: ta.Mapping[rfl.Type, Marshaler | MarshalerFactory] = dc.xfield(
|
20
|
+
default_factory=dict,
|
21
|
+
coerce=lambda d: {
|
22
|
+
check.isinstance(k, rfl.TYPES): check.isinstance(v, (Marshaler, UnmarshalerFactory))
|
23
|
+
for k, v in d.items()
|
24
|
+
},
|
25
|
+
)
|
26
|
+
|
27
|
+
def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
|
38
28
|
check.isinstance(rty, rfl.TYPES)
|
39
29
|
try:
|
40
|
-
|
30
|
+
m = self.m[rty]
|
41
31
|
except KeyError:
|
42
|
-
|
43
|
-
|
32
|
+
return None
|
44
33
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
MarshalerFactory,
|
52
|
-
):
|
53
|
-
@property
|
54
|
-
def make_marshaler(self) -> MarshalerMaker:
|
55
|
-
return self # noqa
|
34
|
+
if isinstance(m, Marshaler):
|
35
|
+
return lambda: m
|
36
|
+
elif isinstance(m, MarshalerFactory):
|
37
|
+
return m.make_marshaler(ctx, rty)
|
38
|
+
else:
|
39
|
+
raise TypeError(m)
|
56
40
|
|
57
41
|
|
58
42
|
@dc.dataclass(frozen=True)
|
59
|
-
class TypeMapUnmarshalerFactory(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
43
|
+
class TypeMapUnmarshalerFactory(UnmarshalerFactory):
|
44
|
+
u: ta.Mapping[rfl.Type, Unmarshaler | UnmarshalerFactory] = dc.xfield(
|
45
|
+
default_factory=dict,
|
46
|
+
coerce=lambda d: {
|
47
|
+
check.isinstance(k, rfl.TYPES): check.isinstance(v, (Unmarshaler, UnmarshalerFactory))
|
48
|
+
for k, v in d.items()
|
49
|
+
},
|
50
|
+
)
|
51
|
+
|
52
|
+
def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
|
53
|
+
check.isinstance(rty, rfl.TYPES)
|
54
|
+
try:
|
55
|
+
u = self.u[rty]
|
56
|
+
except KeyError:
|
57
|
+
return None
|
58
|
+
|
59
|
+
if isinstance(u, Unmarshaler):
|
60
|
+
return lambda: u
|
61
|
+
elif isinstance(u, UnmarshalerFactory):
|
62
|
+
return u.make_unmarshaler(ctx, rty)
|
63
|
+
else:
|
64
|
+
raise TypeError(u)
|
@@ -11,13 +11,14 @@ from ... import dataclasses as dc
|
|
11
11
|
from ... import lang
|
12
12
|
from ... import reflect as rfl
|
13
13
|
from ...lite import marshal as lm
|
14
|
-
from ..base.contexts import
|
15
|
-
from ..base.contexts import
|
14
|
+
from ..base.contexts import MarshalFactoryContext
|
15
|
+
from ..base.contexts import UnmarshalFactoryContext
|
16
|
+
from ..base.errors import UnhandledTypeError
|
16
17
|
from ..base.options import Option
|
17
18
|
from ..base.types import Marshaler
|
19
|
+
from ..base.types import MarshalerFactory
|
18
20
|
from ..base.types import Unmarshaler
|
19
|
-
from ..
|
20
|
-
from ..factories.simple import SimpleUnmarshalerFactory
|
21
|
+
from ..base.types import UnmarshalerFactory
|
21
22
|
from ..naming import Naming
|
22
23
|
from ..naming import translate_name
|
23
24
|
from .marshal import ObjectMarshaler
|
@@ -159,19 +160,37 @@ def get_dataclass_field_infos(
|
|
159
160
|
return FieldInfos(ret)
|
160
161
|
|
161
162
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
163
|
+
##
|
164
|
+
|
165
|
+
|
166
|
+
def _make_field_marshal_obj(
|
167
|
+
ctx: MarshalFactoryContext,
|
168
|
+
ty: ta.Any,
|
169
|
+
obj: Marshaler | None,
|
170
|
+
fac: MarshalerFactory | None,
|
168
171
|
):
|
169
172
|
if obj is not None:
|
170
173
|
return obj
|
171
174
|
if fac is not None:
|
172
|
-
|
173
|
-
|
175
|
+
if (m := fac.make_marshaler(ctx, ty)) is None:
|
176
|
+
raise UnhandledTypeError(ty)
|
177
|
+
return m()
|
178
|
+
return ctx.make_marshaler(ty)
|
179
|
+
|
174
180
|
|
181
|
+
def _make_field_unmarshal_obj(
|
182
|
+
ctx: UnmarshalFactoryContext,
|
183
|
+
ty: ta.Any,
|
184
|
+
obj: Unmarshaler | None,
|
185
|
+
fac: UnmarshalerFactory | None,
|
186
|
+
):
|
187
|
+
if obj is not None:
|
188
|
+
return obj
|
189
|
+
if fac is not None:
|
190
|
+
if (m := fac.make_unmarshaler(ctx, ty)) is None:
|
191
|
+
raise UnhandledTypeError(ty)
|
192
|
+
return m()
|
193
|
+
return ctx.make_unmarshaler(ty)
|
175
194
|
|
176
195
|
##
|
177
196
|
|
@@ -200,119 +219,123 @@ def _type_or_generic_base(rty: rfl.Type) -> type | None:
|
|
200
219
|
return None
|
201
220
|
|
202
221
|
|
203
|
-
class DataclassMarshalerFactory(AbstractDataclassFactory,
|
204
|
-
def
|
205
|
-
|
222
|
+
class DataclassMarshalerFactory(AbstractDataclassFactory, MarshalerFactory):
|
223
|
+
def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
|
224
|
+
if not (
|
206
225
|
(ty := _type_or_generic_base(rty)) is not None and
|
207
226
|
dc.is_dataclass(ty) and
|
208
227
|
not lang.is_abstract_class(ty)
|
209
|
-
)
|
228
|
+
):
|
229
|
+
return None
|
230
|
+
|
231
|
+
def inner() -> Marshaler:
|
232
|
+
ty = check.isinstance(_type_or_generic_base(rty), type)
|
233
|
+
check.state(dc.is_dataclass(ty))
|
234
|
+
check.state(not lang.is_abstract_class(ty))
|
235
|
+
|
236
|
+
dc_md = self._get_metadata(ty)
|
237
|
+
fis = self._get_field_infos(ty, ctx.options)
|
238
|
+
|
239
|
+
fields = [
|
240
|
+
(
|
241
|
+
fi,
|
242
|
+
_make_field_marshal_obj(
|
243
|
+
ctx,
|
244
|
+
fi.type,
|
245
|
+
fi.metadata.marshaler,
|
246
|
+
fi.metadata.marshaler_factory,
|
247
|
+
),
|
248
|
+
)
|
249
|
+
for fi in fis
|
250
|
+
if fi.name not in dc_md.specials.set
|
251
|
+
]
|
210
252
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
check.state(not lang.is_abstract_class(ty))
|
215
|
-
|
216
|
-
dc_md = self._get_metadata(ty)
|
217
|
-
fis = self._get_field_infos(ty, ctx.options)
|
218
|
-
|
219
|
-
fields = [
|
220
|
-
(
|
221
|
-
fi,
|
222
|
-
_make_field_obj(
|
223
|
-
ctx,
|
224
|
-
fi.type,
|
225
|
-
fi.metadata.marshaler,
|
226
|
-
fi.metadata.marshaler_factory,
|
227
|
-
'make_marshaler',
|
228
|
-
),
|
253
|
+
return ObjectMarshaler(
|
254
|
+
fields,
|
255
|
+
specials=dc_md.specials,
|
229
256
|
)
|
230
|
-
for fi in fis
|
231
|
-
if fi.name not in dc_md.specials.set
|
232
|
-
]
|
233
257
|
|
234
|
-
return
|
235
|
-
fields,
|
236
|
-
specials=dc_md.specials,
|
237
|
-
)
|
258
|
+
return inner
|
238
259
|
|
239
260
|
|
240
261
|
##
|
241
262
|
|
242
263
|
|
243
|
-
class DataclassUnmarshalerFactory(AbstractDataclassFactory,
|
244
|
-
def
|
245
|
-
|
264
|
+
class DataclassUnmarshalerFactory(AbstractDataclassFactory, UnmarshalerFactory):
|
265
|
+
def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
|
266
|
+
if not (
|
246
267
|
(ty := _type_or_generic_base(rty)) is not None and
|
247
268
|
dc.is_dataclass(ty) and
|
248
269
|
not lang.is_abstract_class(ty)
|
249
|
-
)
|
270
|
+
):
|
271
|
+
return None
|
250
272
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
273
|
+
def inner() -> Unmarshaler:
|
274
|
+
ty = check.isinstance(_type_or_generic_base(rty), type)
|
275
|
+
check.state(dc.is_dataclass(ty))
|
276
|
+
check.state(not lang.is_abstract_class(ty))
|
255
277
|
|
256
|
-
|
257
|
-
|
278
|
+
dc_md = self._get_metadata(ty)
|
279
|
+
fis = self._get_field_infos(ty, ctx.options)
|
258
280
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
281
|
+
d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
|
282
|
+
defaults: dict[str, ta.Any] = {}
|
283
|
+
embeds: dict[str, type] = {}
|
284
|
+
embeds_by_unmarshal_name: dict[str, tuple[str, str]] = {}
|
263
285
|
|
264
|
-
|
265
|
-
|
286
|
+
def add_field(fi: FieldInfo, *, prefixes: ta.Iterable[str] = ('',)) -> ta.Iterable[str]:
|
287
|
+
ret: list[str] = []
|
266
288
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
289
|
+
if fi.options.embed:
|
290
|
+
e_ty = check.isinstance(fi.type, type)
|
291
|
+
check.state(dc.is_dataclass(e_ty))
|
292
|
+
e_dc_md = get_dataclass_metadata(e_ty)
|
293
|
+
if e_dc_md.specials.set:
|
294
|
+
raise Exception(f'Embedded fields cannot have specials: {e_ty}')
|
273
295
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
296
|
+
embeds[fi.name] = e_ty
|
297
|
+
for e_fi in self._get_field_infos(e_ty, ctx.options):
|
298
|
+
e_ns = add_field(e_fi, prefixes=[p + ep for p in prefixes for ep in fi.unmarshal_names])
|
299
|
+
embeds_by_unmarshal_name.update({e_f: (fi.name, e_fi.name) for e_f in e_ns})
|
300
|
+
ret.extend(e_ns)
|
279
301
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
)
|
290
|
-
)
|
302
|
+
else:
|
303
|
+
tup = (
|
304
|
+
fi,
|
305
|
+
_make_field_unmarshal_obj(
|
306
|
+
ctx,
|
307
|
+
fi.type,
|
308
|
+
fi.metadata.unmarshaler,
|
309
|
+
fi.metadata.unmarshaler_factory,
|
310
|
+
),
|
311
|
+
)
|
291
312
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
313
|
+
for pfx in prefixes:
|
314
|
+
for un in fi.unmarshal_names:
|
315
|
+
un = pfx + un
|
316
|
+
if un in d:
|
317
|
+
raise KeyError(f'Duplicate fields for name {un!r}: {fi.name!r}, {d[un][0].name!r}')
|
318
|
+
d[un] = tup
|
319
|
+
ret.append(un)
|
320
|
+
|
321
|
+
if fi.options.default.present:
|
322
|
+
defaults[fi.name] = fi.options.default.must()
|
323
|
+
|
324
|
+
return ret
|
325
|
+
|
326
|
+
for fi in fis:
|
327
|
+
if fi.name in dc_md.specials.set:
|
328
|
+
continue
|
329
|
+
add_field(fi)
|
330
|
+
|
331
|
+
return ObjectUnmarshaler(
|
332
|
+
ty,
|
333
|
+
d,
|
334
|
+
specials=dc_md.specials,
|
335
|
+
defaults=defaults,
|
336
|
+
embeds=embeds,
|
337
|
+
embeds_by_unmarshal_name=embeds_by_unmarshal_name,
|
338
|
+
ignore_unknown=dc_md.ignore_unknown,
|
339
|
+
)
|
340
|
+
|
341
|
+
return inner
|
@@ -5,9 +5,10 @@ from ... import check
|
|
5
5
|
from ... import dataclasses as dc
|
6
6
|
from ... import reflect as rfl
|
7
7
|
from ..base.contexts import MarshalContext
|
8
|
+
from ..base.contexts import MarshalFactoryContext
|
8
9
|
from ..base.types import Marshaler
|
10
|
+
from ..base.types import MarshalerFactory
|
9
11
|
from ..base.values import Value
|
10
|
-
from ..factories.simple import SimpleMarshalerFactory
|
11
12
|
from .metadata import FieldInfo
|
12
13
|
from .metadata import FieldInfos
|
13
14
|
from .metadata import ObjectSpecials
|
@@ -29,12 +30,12 @@ class ObjectMarshaler(Marshaler):
|
|
29
30
|
@classmethod
|
30
31
|
def make(
|
31
32
|
cls,
|
32
|
-
ctx:
|
33
|
+
ctx: MarshalFactoryContext,
|
33
34
|
fis: FieldInfos,
|
34
35
|
**kwargs: ta.Any,
|
35
36
|
) -> Marshaler:
|
36
37
|
fields = [
|
37
|
-
(fi, ctx.
|
38
|
+
(fi, ctx.make_marshaler(fi.type))
|
38
39
|
for fi in fis
|
39
40
|
]
|
40
41
|
|
@@ -86,23 +87,26 @@ class ObjectMarshaler(Marshaler):
|
|
86
87
|
|
87
88
|
|
88
89
|
@dc.dataclass(frozen=True)
|
89
|
-
class SimpleObjectMarshalerFactory(
|
90
|
+
class SimpleObjectMarshalerFactory(MarshalerFactory):
|
90
91
|
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
91
92
|
|
92
93
|
_: dc.KW_ONLY
|
93
94
|
|
94
95
|
specials: ObjectSpecials = ObjectSpecials()
|
95
96
|
|
96
|
-
def
|
97
|
-
|
97
|
+
def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
|
98
|
+
if not (isinstance(rty, type) and rty in self.dct):
|
99
|
+
return None
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
+
def inner() -> Marshaler:
|
102
|
+
ty = check.isinstance(rty, type)
|
101
103
|
|
102
|
-
|
104
|
+
fis = FieldInfos(self.dct[ty])
|
103
105
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
return ObjectMarshaler.make(
|
107
|
+
ctx,
|
108
|
+
fis,
|
109
|
+
specials=self.specials,
|
110
|
+
)
|
111
|
+
|
112
|
+
return inner
|
@@ -5,13 +5,13 @@ from ... import check
|
|
5
5
|
from ... import collections as col
|
6
6
|
from ... import lang
|
7
7
|
from ... import reflect as rfl
|
8
|
-
from ..base.contexts import
|
9
|
-
from ..base.contexts import
|
8
|
+
from ..base.contexts import MarshalFactoryContext
|
9
|
+
from ..base.contexts import UnmarshalFactoryContext
|
10
10
|
from ..base.options import Option
|
11
11
|
from ..base.types import Marshaler
|
12
|
+
from ..base.types import MarshalerFactory
|
12
13
|
from ..base.types import Unmarshaler
|
13
|
-
from ..
|
14
|
-
from ..factories.simple import SimpleUnmarshalerFactory
|
14
|
+
from ..base.types import UnmarshalerFactory
|
15
15
|
from .marshal import ObjectMarshaler
|
16
16
|
from .metadata import FieldInfo
|
17
17
|
from .metadata import FieldInfos
|
@@ -55,57 +55,63 @@ def get_namedtuple_field_infos(
|
|
55
55
|
##
|
56
56
|
|
57
57
|
|
58
|
-
class NamedtupleMarshalerFactory(
|
59
|
-
def
|
60
|
-
|
58
|
+
class NamedtupleMarshalerFactory(MarshalerFactory):
|
59
|
+
def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
|
60
|
+
if not _is_namedtuple(rty):
|
61
|
+
return None
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
def inner() -> Marshaler:
|
64
|
+
check.state(_is_namedtuple(rty))
|
65
|
+
ty = check.isinstance(rty, type)
|
66
|
+
check.state(not lang.is_abstract_class(ty))
|
66
67
|
|
67
|
-
|
68
|
+
fis = get_namedtuple_field_infos(ty, ctx.options)
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
fields = [
|
71
|
+
(fi, ctx.make_marshaler(fi.type))
|
72
|
+
for fi in fis
|
73
|
+
]
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
return ObjectMarshaler(
|
76
|
+
fields,
|
77
|
+
)
|
78
|
+
|
79
|
+
return inner
|
77
80
|
|
78
81
|
|
79
82
|
##
|
80
83
|
|
81
84
|
|
82
|
-
class NamedtupleUnmarshalerFactory(
|
83
|
-
def
|
84
|
-
|
85
|
+
class NamedtupleUnmarshalerFactory(UnmarshalerFactory):
|
86
|
+
def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
|
87
|
+
if not _is_namedtuple(rty):
|
88
|
+
return None
|
89
|
+
|
90
|
+
def inner() -> Unmarshaler:
|
91
|
+
check.state(_is_namedtuple(rty))
|
92
|
+
ty = check.isinstance(rty, type)
|
93
|
+
check.state(not lang.is_abstract_class(ty))
|
85
94
|
|
86
|
-
|
87
|
-
check.state(_is_namedtuple(rty))
|
88
|
-
ty = check.isinstance(rty, type)
|
89
|
-
check.state(not lang.is_abstract_class(ty))
|
95
|
+
fis = get_namedtuple_field_infos(ty, ctx.options)
|
90
96
|
|
91
|
-
|
97
|
+
d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
|
98
|
+
defaults: dict[str, ta.Any] = {}
|
92
99
|
|
93
|
-
|
94
|
-
|
100
|
+
for fi in fis:
|
101
|
+
tup = (fi, ctx.make_unmarshaler(fi.type))
|
95
102
|
|
96
|
-
|
97
|
-
|
103
|
+
for un in fi.unmarshal_names:
|
104
|
+
if un in d:
|
105
|
+
raise KeyError(f'Duplicate fields for name {un!r}: {fi.name!r}, {d[un][0].name!r}')
|
106
|
+
d[un] = tup
|
98
107
|
|
99
|
-
|
100
|
-
|
101
|
-
raise KeyError(f'Duplicate fields for name {un!r}: {fi.name!r}, {d[un][0].name!r}')
|
102
|
-
d[un] = tup
|
108
|
+
if fi.options.default.present:
|
109
|
+
defaults[fi.name] = fi.options.default.must()
|
103
110
|
|
104
|
-
|
105
|
-
|
111
|
+
return ObjectUnmarshaler(
|
112
|
+
ty,
|
113
|
+
d,
|
114
|
+
defaults=defaults,
|
115
|
+
)
|
106
116
|
|
107
|
-
return
|
108
|
-
ty,
|
109
|
-
d,
|
110
|
-
defaults=defaults,
|
111
|
-
)
|
117
|
+
return inner
|
@@ -5,9 +5,10 @@ from ... import check
|
|
5
5
|
from ... import dataclasses as dc
|
6
6
|
from ... import reflect as rfl
|
7
7
|
from ..base.contexts import UnmarshalContext
|
8
|
+
from ..base.contexts import UnmarshalFactoryContext
|
8
9
|
from ..base.types import Unmarshaler
|
10
|
+
from ..base.types import UnmarshalerFactory
|
9
11
|
from ..base.values import Value
|
10
|
-
from ..factories.simple import SimpleUnmarshalerFactory
|
11
12
|
from .metadata import FieldInfo
|
12
13
|
from .metadata import FieldInfos
|
13
14
|
from .metadata import ObjectSpecials
|
@@ -35,13 +36,13 @@ class ObjectUnmarshaler(Unmarshaler):
|
|
35
36
|
@classmethod
|
36
37
|
def make(
|
37
38
|
cls,
|
38
|
-
ctx:
|
39
|
+
ctx: UnmarshalFactoryContext,
|
39
40
|
factory: ta.Callable,
|
40
41
|
fis: FieldInfos,
|
41
42
|
**kwargs: ta.Any,
|
42
43
|
) -> Unmarshaler:
|
43
44
|
fields_by_unmarshal_name = {
|
44
|
-
n: (fi, ctx.
|
45
|
+
n: (fi, ctx.make_unmarshaler(fi.type))
|
45
46
|
for fi in fis
|
46
47
|
for n in fi.unmarshal_names
|
47
48
|
}
|
@@ -118,24 +119,27 @@ class ObjectUnmarshaler(Unmarshaler):
|
|
118
119
|
|
119
120
|
|
120
121
|
@dc.dataclass(frozen=True)
|
121
|
-
class SimpleObjectUnmarshalerFactory(
|
122
|
+
class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
|
122
123
|
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
123
124
|
|
124
125
|
_: dc.KW_ONLY
|
125
126
|
|
126
127
|
specials: ObjectSpecials = ObjectSpecials()
|
127
128
|
|
128
|
-
def
|
129
|
-
|
129
|
+
def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
|
130
|
+
if not (isinstance(rty, type) and rty in self.dct):
|
131
|
+
return None
|
130
132
|
|
131
|
-
|
132
|
-
|
133
|
+
def inner() -> Unmarshaler:
|
134
|
+
ty = check.isinstance(rty, type)
|
133
135
|
|
134
|
-
|
136
|
+
fis = FieldInfos(self.dct[ty])
|
135
137
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
138
|
+
return ObjectUnmarshaler.make(
|
139
|
+
ctx,
|
140
|
+
ty,
|
141
|
+
fis,
|
142
|
+
specials=self.specials,
|
143
|
+
)
|
144
|
+
|
145
|
+
return inner
|