omlish 0.0.0.dev226__py3-none-any.whl → 0.0.0.dev228__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. omlish/__about__.py +3 -3
  2. omlish/diag/lslocks.py +4 -4
  3. omlish/diag/lsof.py +3 -4
  4. omlish/diag/ps.py +9 -0
  5. omlish/lite/timeouts.py +1 -1
  6. omlish/marshal/__init__.py +39 -24
  7. omlish/marshal/composite/__init__.py +0 -0
  8. omlish/marshal/{iterables.py → composite/iterables.py} +10 -10
  9. omlish/marshal/{literals.py → composite/literals.py} +9 -9
  10. omlish/marshal/{mappings.py → composite/mappings.py} +10 -10
  11. omlish/marshal/{maybes.py → composite/maybes.py} +11 -11
  12. omlish/marshal/{newtypes.py → composite/newtypes.py} +8 -8
  13. omlish/marshal/{optionals.py → composite/optionals.py} +9 -9
  14. omlish/marshal/objects/__init__.py +7 -0
  15. omlish/marshal/{dataclasses.py → objects/dataclasses.py} +24 -24
  16. omlish/marshal/{helpers.py → objects/helpers.py} +6 -3
  17. omlish/marshal/objects/marshal.py +108 -0
  18. omlish/marshal/objects/metadata.py +124 -0
  19. omlish/marshal/{namedtuples.py → objects/namedtuples.py} +16 -16
  20. omlish/marshal/objects/unmarshal.py +141 -0
  21. omlish/marshal/polymorphism/__init__.py +7 -0
  22. omlish/marshal/polymorphism/marshal.py +66 -0
  23. omlish/marshal/polymorphism/metadata.py +140 -0
  24. omlish/marshal/{unions.py → polymorphism/unions.py} +18 -18
  25. omlish/marshal/polymorphism/unmarshal.py +73 -0
  26. omlish/marshal/singular/__init__.py +0 -0
  27. omlish/marshal/{any.py → singular/any.py} +8 -8
  28. omlish/marshal/{base64.py → singular/base64.py} +9 -9
  29. omlish/marshal/{datetimes.py → singular/datetimes.py} +9 -9
  30. omlish/marshal/{enums.py → singular/enums.py} +9 -9
  31. omlish/marshal/{numbers.py → singular/numbers.py} +8 -8
  32. omlish/marshal/{primitives.py → singular/primitives.py} +8 -8
  33. omlish/marshal/{uuids.py → singular/uuids.py} +8 -8
  34. omlish/marshal/standard.py +32 -32
  35. omlish/os/death.py +70 -4
  36. omlish/os/fcntl.py +11 -12
  37. omlish/os/files.py +18 -3
  38. omlish/os/forkhooks.py +215 -0
  39. omlish/os/pidfiles/manager.py +4 -1
  40. omlish/os/pidfiles/pidfile.py +31 -11
  41. omlish/os/pidfiles/pinning.py +250 -0
  42. omlish/sockets/bind.py +4 -4
  43. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/METADATA +3 -3
  44. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/RECORD +48 -38
  45. omlish/marshal/objects.py +0 -317
  46. omlish/marshal/polymorphism.py +0 -267
  47. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/LICENSE +0 -0
  48. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/WHEEL +0 -0
  49. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/entry_points.txt +0 -0
  50. {omlish-0.0.0.dev226.dist-info → omlish-0.0.0.dev228.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,124 @@
1
+ import typing as ta
2
+
3
+ from ... import cached
4
+ from ... import collections as col
5
+ from ... import dataclasses as dc
6
+ from ... import lang
7
+ from ..base import Marshaler
8
+ from ..base import MarshalerFactory
9
+ from ..base import Unmarshaler
10
+ from ..base import UnmarshalerFactory
11
+ from ..naming import Naming
12
+
13
+
14
+ ##
15
+
16
+
17
+ @dc.dataclass(frozen=True, kw_only=True)
18
+ class FieldOptions:
19
+ omit_if: ta.Callable[[ta.Any], bool] | None = None
20
+
21
+ default: lang.Maybe[ta.Any] = dc.xfield(default=lang.empty(), check_type=lang.Maybe)
22
+
23
+ embed: bool = False
24
+
25
+ no_marshal: bool = False
26
+ no_unmarshal: bool = False
27
+
28
+
29
+ DEFAULT_FIELD_OPTIONS = FieldOptions()
30
+ FIELD_OPTIONS_KWARGS: frozenset[str] = frozenset(dc.fields_dict(FieldOptions).keys())
31
+
32
+
33
+ @dc.dataclass(frozen=True, kw_only=True)
34
+ class FieldMetadata:
35
+ name: str | None = None
36
+ alts: ta.Iterable[str] | None = None
37
+
38
+ options: FieldOptions = DEFAULT_FIELD_OPTIONS
39
+
40
+ marshaler: Marshaler | None = dc.xfield(None, check_type=(Marshaler, None))
41
+ marshaler_factory: MarshalerFactory | None = None
42
+
43
+ unmarshaler: Unmarshaler | None = dc.xfield(None, check_type=(Unmarshaler, None))
44
+ unmarshaler_factory: UnmarshalerFactory | None = None
45
+
46
+ def update(self, **kwargs: ta.Any) -> 'FieldMetadata':
47
+ okw = {k: v for k, v in kwargs.items() if k in FIELD_OPTIONS_KWARGS}
48
+ mkw = {k: v for k, v in kwargs.items() if k not in FIELD_OPTIONS_KWARGS}
49
+ return dc.replace(
50
+ self,
51
+ **(dict(options=dc.replace(self.options, **okw)) if okw else {}),
52
+ **mkw,
53
+ )
54
+
55
+
56
+ @dc.dataclass(frozen=True, kw_only=True)
57
+ class ObjectMetadata:
58
+ field_naming: Naming | None = None
59
+
60
+ unknown_field: str | None = None
61
+ source_field: str | None = None
62
+
63
+ @cached.property
64
+ def specials(self) -> 'ObjectSpecials':
65
+ return ObjectSpecials(
66
+ unknown=self.unknown_field,
67
+ source=self.source_field,
68
+ )
69
+
70
+ field_defaults: FieldMetadata = FieldMetadata()
71
+
72
+ ignore_unknown: bool = False
73
+
74
+
75
+ @dc.dataclass(frozen=True, kw_only=True)
76
+ class ObjectSpecials:
77
+ unknown: str | None = None
78
+ source: str | None = None
79
+
80
+ @cached.property
81
+ def set(self) -> frozenset[str]:
82
+ return frozenset(v for v in dc.asdict(self).values() if v is not None)
83
+
84
+
85
+ ##
86
+
87
+
88
+ @dc.dataclass(frozen=True, kw_only=True)
89
+ class FieldInfo:
90
+ name: str
91
+ type: ta.Any
92
+
93
+ marshal_name: str | None
94
+ unmarshal_names: ta.Sequence[str]
95
+
96
+ metadata: FieldMetadata = FieldMetadata()
97
+
98
+ options: FieldOptions = FieldOptions()
99
+
100
+
101
+ @dc.dataclass(frozen=True)
102
+ class FieldInfos:
103
+ lst: ta.Sequence[FieldInfo]
104
+
105
+ def __iter__(self) -> ta.Iterator[FieldInfo]:
106
+ return iter(self.lst)
107
+
108
+ def __len__(self) -> int:
109
+ return len(self.lst)
110
+
111
+ @cached.property
112
+ @dc.init
113
+ def by_name(self) -> ta.Mapping[str, FieldInfo]:
114
+ return col.make_map(((fi.name, fi) for fi in self), strict=True)
115
+
116
+ @cached.property
117
+ @dc.init
118
+ def by_marshal_name(self) -> ta.Mapping[str, FieldInfo]:
119
+ return col.make_map(((fi.marshal_name, fi) for fi in self if fi.marshal_name is not None), strict=True)
120
+
121
+ @cached.property
122
+ @dc.init
123
+ def by_unmarshal_name(self) -> ta.Mapping[str, FieldInfo]:
124
+ return col.make_map(((n, fi) for fi in self for n in fi.unmarshal_names), strict=True)
@@ -1,22 +1,22 @@
1
1
  import inspect
2
2
  import typing as ta
3
3
 
4
- from .. import check
5
- from .. import collections as col
6
- from .. import lang
7
- from .. import reflect as rfl
8
- from .base import MarshalContext
9
- from .base import Marshaler
10
- from .base import MarshalerFactory
11
- from .base import Option
12
- from .base import UnmarshalContext
13
- from .base import Unmarshaler
14
- from .base import UnmarshalerFactory
15
- from .objects import FieldInfo
16
- from .objects import FieldInfos
17
- from .objects import FieldMetadata
18
- from .objects import ObjectMarshaler
19
- from .objects import ObjectUnmarshaler
4
+ from ... import check
5
+ from ... import collections as col
6
+ from ... import lang
7
+ from ... import reflect as rfl
8
+ from ..base import MarshalContext
9
+ from ..base import Marshaler
10
+ from ..base import MarshalerFactory
11
+ from ..base import Option
12
+ from ..base import UnmarshalContext
13
+ from ..base import Unmarshaler
14
+ from ..base import UnmarshalerFactory
15
+ from .marshal import ObjectMarshaler
16
+ from .metadata import FieldInfo
17
+ from .metadata import FieldInfos
18
+ from .metadata import FieldMetadata
19
+ from .unmarshal import ObjectUnmarshaler
20
20
 
21
21
 
22
22
  ##
@@ -0,0 +1,141 @@
1
+ import collections.abc
2
+ import typing as ta
3
+
4
+ from ... import check
5
+ from ... import dataclasses as dc
6
+ from ... import reflect as rfl
7
+ from ..base import UnmarshalContext
8
+ from ..base import Unmarshaler
9
+ from ..base import UnmarshalerFactory
10
+ from ..values import Value
11
+ from .metadata import FieldInfo
12
+ from .metadata import FieldInfos
13
+ from .metadata import ObjectSpecials
14
+
15
+
16
+ ##
17
+
18
+
19
+ @dc.dataclass(frozen=True)
20
+ class ObjectUnmarshaler(Unmarshaler):
21
+ factory: ta.Callable
22
+ fields_by_unmarshal_name: ta.Mapping[str, tuple[FieldInfo, Unmarshaler]]
23
+
24
+ _: dc.KW_ONLY
25
+
26
+ specials: ObjectSpecials = ObjectSpecials()
27
+
28
+ defaults: ta.Mapping[str, ta.Any] | None = None
29
+
30
+ embeds: ta.Mapping[str, type] | None = None
31
+ embeds_by_unmarshal_name: ta.Mapping[str, tuple[str, str]] | None = None
32
+
33
+ ignore_unknown: bool = False
34
+
35
+ @classmethod
36
+ def make(
37
+ cls,
38
+ ctx: UnmarshalContext,
39
+ factory: ta.Callable,
40
+ fis: FieldInfos,
41
+ **kwargs: ta.Any,
42
+ ) -> Unmarshaler:
43
+ fields_by_unmarshal_name = {
44
+ n: (fi, ctx.make(fi.type))
45
+ for fi in fis
46
+ for n in fi.unmarshal_names
47
+ }
48
+
49
+ defaults = {
50
+ fi.name: fi.options.default.must()
51
+ for fi in fis
52
+ if fi.options.default.present
53
+ }
54
+
55
+ return cls(
56
+ factory,
57
+ fields_by_unmarshal_name,
58
+ defaults=defaults,
59
+ **kwargs,
60
+ )
61
+
62
+ #
63
+
64
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
65
+ ma = check.isinstance(v, collections.abc.Mapping)
66
+
67
+ u: ta.Any
68
+ kw: dict[str, ta.Any] = {}
69
+ ukf: dict[str, ta.Any] | None = None
70
+
71
+ ekws: dict[str, dict[str, ta.Any]] = {en: {} for en in self.embeds or ()}
72
+
73
+ if self.specials.source is not None:
74
+ kw[self.specials.source] = v
75
+
76
+ if self.specials.unknown is not None:
77
+ kw[self.specials.unknown] = ukf = {}
78
+
79
+ for k, mv in ma.items():
80
+ ks = check.isinstance(k, str)
81
+
82
+ try:
83
+ fi, u = self.fields_by_unmarshal_name[ks]
84
+
85
+ except KeyError:
86
+ if ukf is not None:
87
+ ukf[ks] = mv # FIXME: unmarshal?
88
+ continue
89
+
90
+ if self.ignore_unknown:
91
+ continue
92
+
93
+ raise
94
+
95
+ if self.embeds_by_unmarshal_name and (en := self.embeds_by_unmarshal_name.get(ks)):
96
+ tkw, tk = ekws[en[0]], en[1]
97
+ else:
98
+ tkw, tk = kw, fi.name
99
+
100
+ if tk in tkw:
101
+ raise KeyError(f'Duplicate keys for field {tk!r}: {ks!r}')
102
+
103
+ tkw[tk] = u.unmarshal(ctx, mv)
104
+
105
+ for em, ecls in self.embeds.items() if self.embeds else ():
106
+ ekw = ekws[em]
107
+ ev = ecls(**ekw)
108
+ kw[em] = ev
109
+
110
+ if self.defaults:
111
+ for dk, dv in self.defaults.items():
112
+ kw.setdefault(dk, dv)
113
+
114
+ return self.factory(**kw)
115
+
116
+
117
+ ##
118
+
119
+
120
+ @dc.dataclass(frozen=True)
121
+ class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
122
+ dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
123
+
124
+ _: dc.KW_ONLY
125
+
126
+ specials: ObjectSpecials = ObjectSpecials()
127
+
128
+ def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
129
+ return isinstance(rty, type) and rty in self.dct
130
+
131
+ def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
132
+ ty = check.isinstance(rty, type)
133
+
134
+ fis = FieldInfos(self.dct[ty])
135
+
136
+ return ObjectUnmarshaler.make(
137
+ ctx,
138
+ ty,
139
+ fis,
140
+ specials=self.specials,
141
+ )
@@ -0,0 +1,7 @@
1
+ """
2
+ TODO:
3
+ - auto-gen from __subclasses__ if abstract
4
+ - cfg: unless prefixed with _ or abstract
5
+ - iff Sealed
6
+ - auto-name
7
+ """
@@ -0,0 +1,66 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from ... import check
5
+ from ... import reflect as rfl
6
+ from ..base import MarshalContext
7
+ from ..base import Marshaler
8
+ from ..base import MarshalerFactory
9
+ from ..values import Value
10
+ from .metadata import FieldTypeTagging
11
+ from .metadata import Impls
12
+ from .metadata import Polymorphism
13
+ from .metadata import TypeTagging
14
+ from .metadata import WrapperTypeTagging
15
+
16
+
17
+ ##
18
+
19
+
20
+ @dc.dataclass(frozen=True)
21
+ class WrapperPolymorphismMarshaler(Marshaler):
22
+ m: ta.Mapping[type, tuple[str, Marshaler]]
23
+
24
+ def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
25
+ tag, m = self.m[type(o)]
26
+ return {tag: m.marshal(ctx, o)}
27
+
28
+
29
+ @dc.dataclass(frozen=True)
30
+ class FieldPolymorphismMarshaler(Marshaler):
31
+ m: ta.Mapping[type, tuple[str, Marshaler]]
32
+ tf: str
33
+
34
+ def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
35
+ tag, m = self.m[type(o)]
36
+ return {self.tf: tag, **m.marshal(ctx, o)} # type: ignore
37
+
38
+
39
+ def make_polymorphism_marshaler(
40
+ impls: Impls,
41
+ tt: TypeTagging,
42
+ ctx: MarshalContext,
43
+ ) -> Marshaler:
44
+ m = {
45
+ i.ty: (i.tag, ctx.make(i.ty))
46
+ for i in impls
47
+ }
48
+ if isinstance(tt, WrapperTypeTagging):
49
+ return WrapperPolymorphismMarshaler(m)
50
+ elif isinstance(tt, FieldTypeTagging):
51
+ return FieldPolymorphismMarshaler(m, tt.field)
52
+ else:
53
+ raise TypeError(tt)
54
+
55
+
56
+ @dc.dataclass(frozen=True)
57
+ class PolymorphismMarshalerFactory(MarshalerFactory):
58
+ p: Polymorphism
59
+ tt: TypeTagging = WrapperTypeTagging()
60
+
61
+ def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
62
+ return rty is self.p.ty
63
+
64
+ def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
65
+ check.is_(rty, self.p.ty)
66
+ return make_polymorphism_marshaler(self.p.impls, self.tt, ctx)
@@ -0,0 +1,140 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from ... import lang
5
+ from ..naming import Naming
6
+ from ..naming import translate_name
7
+ from ..registries import RegistryItem
8
+
9
+
10
+ ##
11
+
12
+
13
+ class TypeTagging(RegistryItem, lang.Abstract, lang.Sealed):
14
+ pass
15
+
16
+
17
+ class WrapperTypeTagging(TypeTagging, lang.Final):
18
+ pass
19
+
20
+
21
+ @dc.dataclass(frozen=True)
22
+ class FieldTypeTagging(TypeTagging, lang.Final):
23
+ field: str
24
+
25
+
26
+ ##
27
+
28
+
29
+ @dc.dataclass(frozen=True)
30
+ class Impl:
31
+ ty: type
32
+ tag: str
33
+ alts: ta.AbstractSet[str] = frozenset()
34
+
35
+
36
+ class Impls(ta.Sequence[Impl]):
37
+ def __init__(
38
+ self,
39
+ lst: ta.Iterable[Impl],
40
+ ) -> None:
41
+ super().__init__()
42
+ self._lst = list(lst)
43
+
44
+ by_ty: dict[type, Impl] = {}
45
+ by_tag: dict[str, Impl] = {}
46
+ for i in self._lst:
47
+ if i.ty in by_ty:
48
+ raise TypeError(i.ty)
49
+ if i.tag in by_tag:
50
+ raise NameError(i.tag)
51
+ for a in i.alts:
52
+ if a in by_tag:
53
+ raise NameError(a)
54
+ by_ty[i.ty] = i
55
+ by_tag[i.tag] = i
56
+ for a in i.alts:
57
+ by_tag[a] = i
58
+ self._by_ty = by_ty
59
+ self._by_tag = by_tag
60
+
61
+ def __iter__(self) -> ta.Iterator[Impl]:
62
+ return iter(self._lst)
63
+
64
+ def __len__(self) -> int:
65
+ return len(self._lst)
66
+
67
+ @ta.overload
68
+ def __getitem__(self, index: int) -> Impl: ...
69
+
70
+ @ta.overload
71
+ def __getitem__(self, index: slice) -> ta.Sequence[Impl]: ...
72
+
73
+ def __getitem__(self, index):
74
+ return self._lst[index]
75
+
76
+ @property
77
+ def by_ty(self) -> ta.Mapping[type, Impl]:
78
+ return self._by_ty
79
+
80
+ @property
81
+ def by_tag(self) -> ta.Mapping[str, Impl]:
82
+ return self._by_tag
83
+
84
+
85
+ class Polymorphism:
86
+ def __init__(
87
+ self,
88
+ ty: type,
89
+ impls: ta.Iterable[Impl],
90
+ ) -> None:
91
+ super().__init__()
92
+ self._ty = ty
93
+ self._impls = Impls(impls)
94
+
95
+ for i in self._impls:
96
+ if not issubclass(i.ty, ty):
97
+ raise TypeError(i.ty, ty)
98
+
99
+ @property
100
+ def ty(self) -> type:
101
+ return self._ty
102
+
103
+ @property
104
+ def impls(self) -> Impls:
105
+ return self._impls
106
+
107
+
108
+ def polymorphism_from_subclasses(
109
+ ty: type,
110
+ *,
111
+ naming: Naming | None = None,
112
+ strip_suffix: bool = False,
113
+ ) -> Polymorphism:
114
+ dct: dict[str, Impl] = {}
115
+
116
+ seen: set[type] = set()
117
+ todo: list[type] = [ty]
118
+ while todo:
119
+ cur = todo.pop()
120
+ seen.add(cur)
121
+
122
+ todo.extend(nxt for nxt in cur.__subclasses__() if nxt not in seen)
123
+
124
+ if lang.is_abstract_class(cur):
125
+ continue
126
+
127
+ name = cur.__name__
128
+ if strip_suffix:
129
+ name = lang.strip_suffix(name, ty.__name__)
130
+ if naming is not None:
131
+ name = translate_name(name, naming)
132
+ if name in dct:
133
+ raise KeyError(f'Duplicate name: {name}')
134
+
135
+ dct[name] = Impl(
136
+ cur,
137
+ name,
138
+ )
139
+
140
+ return Polymorphism(ty, dct.values())
@@ -1,23 +1,23 @@
1
1
  import typing as ta
2
2
 
3
- from .. import cached
4
- from .. import check
5
- from .. import dataclasses as dc
6
- from .. import lang
7
- from .. import reflect as rfl
8
- from ..funcs import match as mfs
9
- from .base import MarshalContext
10
- from .base import Marshaler
11
- from .base import MarshalerFactory
12
- from .base import UnmarshalContext
13
- from .base import Unmarshaler
14
- from .base import UnmarshalerFactory
15
- from .polymorphism import Impls
16
- from .polymorphism import TypeTagging
17
- from .polymorphism import WrapperTypeTagging
18
- from .polymorphism import make_polymorphism_marshaler
19
- from .polymorphism import make_polymorphism_unmarshaler
20
- from .values import Value
3
+ from ... import cached
4
+ from ... import check
5
+ from ... import dataclasses as dc
6
+ from ... import lang
7
+ from ... import reflect as rfl
8
+ from ...funcs import match as mfs
9
+ from ..base import MarshalContext
10
+ from ..base import Marshaler
11
+ from ..base import MarshalerFactory
12
+ from ..base import UnmarshalContext
13
+ from ..base import Unmarshaler
14
+ from ..base import UnmarshalerFactory
15
+ from ..values import Value
16
+ from .marshal import make_polymorphism_marshaler
17
+ from .metadata import Impls
18
+ from .metadata import TypeTagging
19
+ from .metadata import WrapperTypeTagging
20
+ from .unmarshal import make_polymorphism_unmarshaler
21
21
 
22
22
 
23
23
  ##
@@ -0,0 +1,73 @@
1
+ import collections.abc
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+ from ... import check
6
+ from ... import reflect as rfl
7
+ from ..base import UnmarshalContext
8
+ from ..base import Unmarshaler
9
+ from ..base import UnmarshalerFactory
10
+ from ..values import Value
11
+ from .metadata import FieldTypeTagging
12
+ from .metadata import Impls
13
+ from .metadata import Polymorphism
14
+ from .metadata import TypeTagging
15
+ from .metadata import WrapperTypeTagging
16
+
17
+
18
+ ##
19
+
20
+
21
+ @dc.dataclass(frozen=True)
22
+ class WrapperPolymorphismUnmarshaler(Unmarshaler):
23
+ m: ta.Mapping[str, Unmarshaler]
24
+
25
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
26
+ ma = check.isinstance(v, collections.abc.Mapping)
27
+ [(tag, iv)] = ma.items()
28
+ u = self.m[tag]
29
+ return u.unmarshal(ctx, iv)
30
+
31
+
32
+ @dc.dataclass(frozen=True)
33
+ class FieldPolymorphismUnmarshaler(Unmarshaler):
34
+ m: ta.Mapping[str, Unmarshaler]
35
+ tf: str
36
+
37
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
38
+ ma = dict(check.isinstance(v, collections.abc.Mapping))
39
+ tag = ma.pop(self.tf)
40
+ u = self.m[tag]
41
+ return u.unmarshal(ctx, ma)
42
+
43
+
44
+ def make_polymorphism_unmarshaler(
45
+ impls: Impls,
46
+ tt: TypeTagging,
47
+ ctx: UnmarshalContext,
48
+ ) -> Unmarshaler:
49
+ m = {
50
+ t: u
51
+ for i in impls
52
+ for u in [ctx.make(i.ty)]
53
+ for t in [i.tag, *i.alts]
54
+ }
55
+ if isinstance(tt, WrapperTypeTagging):
56
+ return WrapperPolymorphismUnmarshaler(m)
57
+ elif isinstance(tt, FieldTypeTagging):
58
+ return FieldPolymorphismUnmarshaler(m, tt.field)
59
+ else:
60
+ raise TypeError(tt)
61
+
62
+
63
+ @dc.dataclass(frozen=True)
64
+ class PolymorphismUnmarshalerFactory(UnmarshalerFactory):
65
+ p: Polymorphism
66
+ tt: TypeTagging = WrapperTypeTagging()
67
+
68
+ def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
69
+ return rty is self.p.ty
70
+
71
+ def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
72
+ check.is_(rty, self.p.ty)
73
+ return make_polymorphism_unmarshaler(self.p.impls, self.tt, ctx)
File without changes
@@ -1,13 +1,13 @@
1
1
  import typing as ta
2
2
 
3
- from .. import reflect as rfl
4
- from .base import MarshalContext
5
- from .base import Marshaler
6
- from .base import TypeMapMarshalerFactory
7
- from .base import TypeMapUnmarshalerFactory
8
- from .base import UnmarshalContext
9
- from .base import Unmarshaler
10
- from .values import Value
3
+ from ... import reflect as rfl
4
+ from ..base import MarshalContext
5
+ from ..base import Marshaler
6
+ from ..base import TypeMapMarshalerFactory
7
+ from ..base import TypeMapUnmarshalerFactory
8
+ from ..base import UnmarshalContext
9
+ from ..base import Unmarshaler
10
+ from ..values import Value
11
11
 
12
12
 
13
13
  class AnyMarshalerUnmarshaler(Marshaler, Unmarshaler):
@@ -5,15 +5,15 @@ FIXME:
5
5
  import base64
6
6
  import typing as ta
7
7
 
8
- from .. import check
9
- from .. import dataclasses as dc
10
- from .base import MarshalContext
11
- from .base import Marshaler
12
- from .base import TypeMapMarshalerFactory
13
- from .base import TypeMapUnmarshalerFactory
14
- from .base import UnmarshalContext
15
- from .base import Unmarshaler
16
- from .values import Value
8
+ from ... import check
9
+ from ... import dataclasses as dc
10
+ from ..base import MarshalContext
11
+ from ..base import Marshaler
12
+ from ..base import TypeMapMarshalerFactory
13
+ from ..base import TypeMapUnmarshalerFactory
14
+ from ..base import UnmarshalContext
15
+ from ..base import Unmarshaler
16
+ from ..values import Value
17
17
 
18
18
 
19
19
  T = ta.TypeVar('T')