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.
Files changed (56) hide show
  1. omlish/__about__.py +2 -2
  2. omlish/collections/identity.py +1 -0
  3. omlish/dataclasses/__init__.py +2 -0
  4. omlish/funcs/guard.py +27 -16
  5. omlish/lang/__init__.py +1 -0
  6. omlish/lang/functions.py +2 -2
  7. omlish/lang/iterables.py +8 -0
  8. omlish/lite/attrops.py +2 -0
  9. omlish/lite/dataclasses.py +30 -0
  10. omlish/marshal/__init__.py +16 -11
  11. omlish/marshal/base/contexts.py +33 -20
  12. omlish/marshal/base/funcs.py +8 -11
  13. omlish/marshal/base/options.py +8 -0
  14. omlish/marshal/base/types.py +38 -14
  15. omlish/marshal/composite/iterables.py +33 -20
  16. omlish/marshal/composite/literals.py +16 -18
  17. omlish/marshal/composite/mappings.py +36 -23
  18. omlish/marshal/composite/maybes.py +29 -19
  19. omlish/marshal/composite/newtypes.py +16 -16
  20. omlish/marshal/composite/optionals.py +14 -14
  21. omlish/marshal/composite/special.py +15 -15
  22. omlish/marshal/composite/unions/__init__.py +0 -0
  23. omlish/marshal/composite/unions/literals.py +93 -0
  24. omlish/marshal/composite/unions/primitives.py +103 -0
  25. omlish/marshal/factories/invalidate.py +18 -68
  26. omlish/marshal/factories/method.py +26 -0
  27. omlish/marshal/factories/moduleimport/factories.py +15 -56
  28. omlish/marshal/factories/multi.py +13 -25
  29. omlish/marshal/factories/recursive.py +42 -56
  30. omlish/marshal/factories/typecache.py +20 -77
  31. omlish/marshal/factories/typemap.py +42 -43
  32. omlish/marshal/objects/dataclasses.py +129 -106
  33. omlish/marshal/objects/marshal.py +18 -14
  34. omlish/marshal/objects/namedtuples.py +48 -42
  35. omlish/marshal/objects/unmarshal.py +19 -15
  36. omlish/marshal/polymorphism/marshal.py +9 -11
  37. omlish/marshal/polymorphism/unions.py +17 -11
  38. omlish/marshal/polymorphism/unmarshal.py +9 -10
  39. omlish/marshal/singular/enums.py +14 -18
  40. omlish/marshal/standard.py +8 -8
  41. omlish/marshal/trivial/any.py +1 -1
  42. omlish/marshal/trivial/forbidden.py +21 -26
  43. omlish/os/forkhooks.py +4 -0
  44. omlish/specs/jsonrpc/_marshal.py +33 -24
  45. omlish/specs/openapi/_marshal.py +30 -21
  46. omlish/typedvalues/marshal.py +83 -57
  47. {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/METADATA +1 -1
  48. {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/RECORD +52 -52
  49. omlish/funcs/match.py +0 -229
  50. omlish/marshal/composite/unions.py +0 -213
  51. omlish/marshal/factories/match.py +0 -34
  52. omlish/marshal/factories/simple.py +0 -28
  53. {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/WHEEL +0 -0
  54. {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/entry_points.txt +0 -0
  55. {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/licenses/LICENSE +0 -0
  56. {omlish-0.0.0.dev453.dist-info → omlish-0.0.0.dev455.dist-info}/top_level.txt +0 -0
@@ -8,12 +8,14 @@ import typing as ta
8
8
  from ... import check
9
9
  from ... import reflect as rfl
10
10
  from ..base.contexts import MarshalContext
11
+ from ..base.contexts import MarshalFactoryContext
11
12
  from ..base.contexts import UnmarshalContext
13
+ from ..base.contexts import UnmarshalFactoryContext
12
14
  from ..base.types import Marshaler
15
+ from ..base.types import MarshalerFactory
13
16
  from ..base.types import Unmarshaler
17
+ from ..base.types import UnmarshalerFactory
14
18
  from ..base.values import Value
15
- from ..factories.simple import SimpleMarshalerFactory
16
- from ..factories.simple import SimpleUnmarshalerFactory
17
19
 
18
20
 
19
21
  ##
@@ -28,14 +30,12 @@ class LiteralMarshaler(Marshaler):
28
30
  return self.e.marshal(ctx, check.in_(o, self.vs))
29
31
 
30
32
 
31
- class LiteralMarshalerFactory(SimpleMarshalerFactory):
32
- def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
33
- return isinstance(rty, rfl.Literal) and len(set(map(type, rty.args))) == 1
34
-
35
- def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
36
- lty = check.isinstance(rty, rfl.Literal)
37
- ety = check.single(set(map(type, lty.args)))
38
- return LiteralMarshaler(ctx.make(ety), frozenset(lty.args))
33
+ class LiteralMarshalerFactory(MarshalerFactory):
34
+ def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
35
+ if not (isinstance(rty, rfl.Literal) and len(set(map(type, rty.args))) == 1):
36
+ return None
37
+ ety = check.single(set(map(type, rty.args)))
38
+ return lambda: LiteralMarshaler(ctx.make_marshaler(ety), frozenset(rty.args))
39
39
 
40
40
 
41
41
  @dc.dataclass(frozen=True)
@@ -47,11 +47,9 @@ class LiteralUnmarshaler(Unmarshaler):
47
47
  return check.in_(self.e.unmarshal(ctx, v), self.vs)
48
48
 
49
49
 
50
- class LiteralUnmarshalerFactory(SimpleUnmarshalerFactory):
51
- def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
52
- return isinstance(rty, rfl.Literal) and len(set(map(type, rty.args))) == 1
53
-
54
- def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
55
- lty = check.isinstance(rty, rfl.Literal)
56
- ety = check.single(set(map(type, lty.args)))
57
- return LiteralUnmarshaler(ctx.make(ety), frozenset(lty.args))
50
+ class LiteralUnmarshalerFactory(UnmarshalerFactory):
51
+ def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
52
+ if not (isinstance(rty, rfl.Literal) and len(set(map(type, rty.args))) == 1):
53
+ return None
54
+ ety = check.single(set(map(type, rty.args)))
55
+ return lambda: LiteralUnmarshaler(ctx.make_unmarshaler(ety), frozenset(rty.args))
@@ -4,14 +4,15 @@ import typing as ta
4
4
 
5
5
  from ... import check
6
6
  from ... import reflect as rfl
7
- from ...funcs import match as mfs
8
7
  from ..base.contexts import MarshalContext
8
+ from ..base.contexts import MarshalFactoryContext
9
9
  from ..base.contexts import UnmarshalContext
10
+ from ..base.contexts import UnmarshalFactoryContext
10
11
  from ..base.types import Marshaler
11
12
  from ..base.types import Unmarshaler
12
13
  from ..base.values import Value
13
- from ..factories.match import MarshalerFactoryMatchClass
14
- from ..factories.match import UnmarshalerFactoryMatchClass
14
+ from ..factories.method import MarshalerFactoryMethodClass
15
+ from ..factories.method import UnmarshalerFactoryMethodClass
15
16
 
16
17
 
17
18
  ##
@@ -23,6 +24,9 @@ DEFAULT_MAPPING_CONCRETE_TYPES: dict[type[collections.abc.Mapping], type[collect
23
24
  }
24
25
 
25
26
 
27
+ #
28
+
29
+
26
30
  @dc.dataclass(frozen=True)
27
31
  class MappingMarshaler(Marshaler):
28
32
  ke: Marshaler
@@ -35,16 +39,22 @@ class MappingMarshaler(Marshaler):
35
39
  }
36
40
 
37
41
 
38
- class MappingMarshalerFactory(MarshalerFactoryMatchClass):
39
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping))
40
- def _build_generic(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
41
- gty = check.isinstance(rty, rfl.Generic)
42
- kt, vt = gty.args
43
- return MappingMarshaler(ctx.make(kt), ctx.make(vt))
42
+ class MappingMarshalerFactory(MarshalerFactoryMethodClass):
43
+ @MarshalerFactoryMethodClass.make_marshaler.register
44
+ def _make_generic(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
45
+ if not (isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping)):
46
+ return None
47
+ kt, vt = rty.args
48
+ return lambda: MappingMarshaler(ctx.make_marshaler(kt), ctx.make_marshaler(vt))
49
+
50
+ @MarshalerFactoryMethodClass.make_marshaler.register
51
+ def _make_concrete(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
52
+ if not (isinstance(rty, type) and issubclass(rty, collections.abc.Mapping)):
53
+ return None
54
+ return lambda: MappingMarshaler(a := ctx.make_marshaler(ta.Any), a)
44
55
 
45
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, type) and issubclass(rty, collections.abc.Mapping))
46
- def _build_concrete(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
47
- return MappingMarshaler(a := ctx.make(ta.Any), a)
56
+
57
+ #
48
58
 
49
59
 
50
60
  @dc.dataclass(frozen=True)
@@ -60,14 +70,17 @@ class MappingUnmarshaler(Unmarshaler):
60
70
  return self.ctor(dct)
61
71
 
62
72
 
63
- class MappingUnmarshalerFactory(UnmarshalerFactoryMatchClass):
64
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping))
65
- def _build_generic(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
66
- gty = check.isinstance(rty, rfl.Generic)
67
- cty = DEFAULT_MAPPING_CONCRETE_TYPES.get(gty.cls, gty.cls) # noqa
68
- kt, vt = gty.args
69
- return MappingUnmarshaler(cty, ctx.make(kt), ctx.make(vt))
70
-
71
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, type) and issubclass(rty, collections.abc.Mapping))
72
- def _build_concrete(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
73
- return MappingUnmarshaler(check.isinstance(rty, type), a := ctx.make(ta.Any), a)
73
+ class MappingUnmarshalerFactory(UnmarshalerFactoryMethodClass):
74
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
75
+ def _make_generic(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
76
+ if not (isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping)):
77
+ return None
78
+ cty = DEFAULT_MAPPING_CONCRETE_TYPES.get(rty.cls, rty.cls) # noqa
79
+ kt, vt = rty.args
80
+ return lambda: MappingUnmarshaler(cty, ctx.make_unmarshaler(kt), ctx.make_unmarshaler(vt))
81
+
82
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
83
+ def _make_concrete(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
84
+ if not (isinstance(rty, type) and issubclass(rty, collections.abc.Mapping)):
85
+ return None
86
+ return lambda: MappingUnmarshaler(check.isinstance(rty, type), a := ctx.make_unmarshaler(ta.Any), a)
@@ -8,14 +8,15 @@ import typing as ta
8
8
  from ... import check
9
9
  from ... import lang
10
10
  from ... import reflect as rfl
11
- from ...funcs import match as mfs
12
11
  from ..base.contexts import MarshalContext
12
+ from ..base.contexts import MarshalFactoryContext
13
13
  from ..base.contexts import UnmarshalContext
14
+ from ..base.contexts import UnmarshalFactoryContext
14
15
  from ..base.types import Marshaler
15
16
  from ..base.types import Unmarshaler
16
17
  from ..base.values import Value
17
- from ..factories.match import MarshalerFactoryMatchClass
18
- from ..factories.match import UnmarshalerFactoryMatchClass
18
+ from ..factories.method import MarshalerFactoryMethodClass
19
+ from ..factories.method import UnmarshalerFactoryMethodClass
19
20
 
20
21
 
21
22
  ##
@@ -33,15 +34,21 @@ class MaybeMarshaler(Marshaler):
33
34
  return []
34
35
 
35
36
 
36
- class MaybeMarshalerFactory(MarshalerFactoryMatchClass):
37
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Generic) and rty.cls is lang.Maybe)
38
- def _build_generic(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
39
- gty = check.isinstance(rty, rfl.Generic)
40
- return MaybeMarshaler(ctx.make(check.single(gty.args)))
37
+ class MaybeMarshalerFactory(MarshalerFactoryMethodClass):
38
+ @MarshalerFactoryMethodClass.make_marshaler.register
39
+ def _make_generic(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
40
+ if not (isinstance(rty, rfl.Generic) and rty.cls is lang.Maybe):
41
+ return None
42
+ return lambda: MaybeMarshaler(ctx.make_marshaler(check.single(rty.args)))
41
43
 
42
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, type) and issubclass(rty, lang.Maybe))
43
- def _build_concrete(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
44
- return MaybeMarshaler(ctx.make(ta.Any))
44
+ @MarshalerFactoryMethodClass.make_marshaler.register
45
+ def _make_concrete(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
46
+ if not (isinstance(rty, type) and issubclass(rty, lang.Maybe)):
47
+ return None
48
+ return lambda: MaybeMarshaler(ctx.make_marshaler(ta.Any))
49
+
50
+
51
+ #
45
52
 
46
53
 
47
54
  @dc.dataclass(frozen=True)
@@ -55,12 +62,15 @@ class MaybeUnmarshaler(Unmarshaler):
55
62
  return lang.empty()
56
63
 
57
64
 
58
- class MaybeUnmarshalerFactory(UnmarshalerFactoryMatchClass):
59
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Generic) and rty.cls is lang.Maybe)
60
- def _build_generic(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
61
- gty = check.isinstance(rty, rfl.Generic)
62
- return MaybeUnmarshaler(ctx.make(check.single(gty.args)))
65
+ class MaybeUnmarshalerFactory(UnmarshalerFactoryMethodClass):
66
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
67
+ def _make_generic(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
68
+ if not (isinstance(rty, rfl.Generic) and rty.cls is lang.Maybe):
69
+ return None
70
+ return lambda: MaybeUnmarshaler(ctx.make_unmarshaler(check.single(rty.args)))
63
71
 
64
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, type) and issubclass(rty, lang.Maybe))
65
- def _build_concrete(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
66
- return MaybeUnmarshaler(ctx.make(ta.Any))
72
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
73
+ def _make_concrete(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
74
+ if not (isinstance(rty, type) and issubclass(rty, lang.Maybe)):
75
+ return None
76
+ return lambda: MaybeUnmarshaler(ctx.make_unmarshaler(ta.Any))
@@ -1,27 +1,27 @@
1
+ import typing as ta
2
+
1
3
  from ... import check
2
4
  from ... import reflect as rfl
3
- from ..base.contexts import MarshalContext
4
- from ..base.contexts import UnmarshalContext
5
+ from ..base.contexts import MarshalFactoryContext
6
+ from ..base.contexts import UnmarshalFactoryContext
5
7
  from ..base.types import Marshaler
8
+ from ..base.types import MarshalerFactory
6
9
  from ..base.types import Unmarshaler
7
- from ..factories.simple import SimpleMarshalerFactory
8
- from ..factories.simple import SimpleUnmarshalerFactory
10
+ from ..base.types import UnmarshalerFactory
9
11
 
10
12
 
11
13
  ##
12
14
 
13
15
 
14
- class NewtypeMarshalerFactory(SimpleMarshalerFactory):
15
- def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
16
- return isinstance(rty, rfl.NewType)
17
-
18
- def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
19
- return ctx.make(check.isinstance(rty, rfl.NewType).ty)
20
-
16
+ class NewtypeMarshalerFactory(MarshalerFactory):
17
+ def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
18
+ if not isinstance(rty, rfl.NewType):
19
+ return None
20
+ return lambda: ctx.make_marshaler(check.isinstance(rty, rfl.NewType).ty)
21
21
 
22
- class NewtypeUnmarshalerFactory(SimpleUnmarshalerFactory):
23
- def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
24
- return isinstance(rty, rfl.NewType)
25
22
 
26
- def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
27
- return ctx.make(check.isinstance(rty, rfl.NewType).ty)
23
+ class NewtypeUnmarshalerFactory(UnmarshalerFactory):
24
+ def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
25
+ if not isinstance(rty, rfl.NewType):
26
+ return None
27
+ return lambda: ctx.make_unmarshaler(check.isinstance(rty, rfl.NewType).ty)
@@ -4,12 +4,14 @@ import typing as ta
4
4
  from ... import check
5
5
  from ... import reflect as rfl
6
6
  from ..base.contexts import MarshalContext
7
+ from ..base.contexts import MarshalFactoryContext
7
8
  from ..base.contexts import UnmarshalContext
9
+ from ..base.contexts import UnmarshalFactoryContext
8
10
  from ..base.types import Marshaler
11
+ from ..base.types import MarshalerFactory
9
12
  from ..base.types import Unmarshaler
13
+ from ..base.types import UnmarshalerFactory
10
14
  from ..base.values import Value
11
- from ..factories.simple import SimpleMarshalerFactory
12
- from ..factories.simple import SimpleUnmarshalerFactory
13
15
 
14
16
 
15
17
  ##
@@ -25,12 +27,11 @@ class OptionalMarshaler(Marshaler):
25
27
  return self.e.marshal(ctx, o)
26
28
 
27
29
 
28
- class OptionalMarshalerFactory(SimpleMarshalerFactory):
29
- def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
30
- return isinstance(rty, rfl.Union) and rty.is_optional
31
-
32
- def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
33
- return OptionalMarshaler(ctx.make(check.isinstance(rty, rfl.Union).without_none()))
30
+ class OptionalMarshalerFactory(MarshalerFactory):
31
+ def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
32
+ if not (isinstance(rty, rfl.Union) and rty.is_optional):
33
+ return None
34
+ return lambda: OptionalMarshaler(ctx.make_marshaler(check.isinstance(rty, rfl.Union).without_none()))
34
35
 
35
36
 
36
37
  @dc.dataclass(frozen=True)
@@ -43,9 +44,8 @@ class OptionalUnmarshaler(Unmarshaler):
43
44
  return self.e.unmarshal(ctx, v)
44
45
 
45
46
 
46
- class OptionalUnmarshalerFactory(SimpleUnmarshalerFactory):
47
- def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
48
- return isinstance(rty, rfl.Union) and rty.is_optional
49
-
50
- def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
51
- return OptionalUnmarshaler(ctx.make(check.isinstance(rty, rfl.Union).without_none()))
47
+ class OptionalUnmarshalerFactory(UnmarshalerFactory):
48
+ def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
49
+ if not (isinstance(rty, rfl.Union) and rty.is_optional):
50
+ return None
51
+ return lambda: OptionalUnmarshaler(ctx.make_unmarshaler(check.isinstance(rty, rfl.Union).without_none()))
@@ -1,15 +1,15 @@
1
1
  import collections.abc
2
+ import typing as ta
2
3
 
3
4
  from ... import check
4
5
  from ... import lang
5
6
  from ... import reflect as rfl
6
- from ...funcs import match as mfs
7
- from ..base.contexts import MarshalContext
8
- from ..base.contexts import UnmarshalContext
7
+ from ..base.contexts import MarshalFactoryContext
8
+ from ..base.contexts import UnmarshalFactoryContext
9
9
  from ..base.types import Marshaler
10
+ from ..base.types import MarshalerFactory
10
11
  from ..base.types import Unmarshaler
11
- from ..factories.match import MarshalerFactoryMatchClass
12
- from ..factories.match import UnmarshalerFactoryMatchClass
12
+ from ..base.types import UnmarshalerFactory
13
13
  from .iterables import DEFAULT_ITERABLE_CONCRETE_TYPES
14
14
  from .iterables import IterableMarshaler
15
15
  from .iterables import IterableUnmarshaler
@@ -18,16 +18,16 @@ from .iterables import IterableUnmarshaler
18
18
  ##
19
19
 
20
20
 
21
- class SequenceNotStrMarshalerFactory(MarshalerFactoryMatchClass):
22
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Protocol) and rty.cls is lang.SequenceNotStr)
23
- def _build_generic(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
24
- gty = check.isinstance(rty, rfl.Protocol)
25
- return IterableMarshaler(ctx.make(check.single(gty.args)))
21
+ class SequenceNotStrMarshalerFactory(MarshalerFactory):
22
+ def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
23
+ if not (isinstance(rty, rfl.Protocol) and rty.cls is lang.SequenceNotStr):
24
+ return None
25
+ return lambda: IterableMarshaler(ctx.make_marshaler(check.single(rty.args)))
26
26
 
27
27
 
28
- class SequenceNotStrUnmarshalerFactory(UnmarshalerFactoryMatchClass):
29
- @mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Protocol) and rty.cls is lang.SequenceNotStr)
30
- def _build_generic(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
31
- gty = check.isinstance(rty, rfl.Protocol)
28
+ class SequenceNotStrUnmarshalerFactory(UnmarshalerFactory):
29
+ def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
30
+ if not (isinstance(rty, rfl.Protocol) and rty.cls is lang.SequenceNotStr):
31
+ return None
32
32
  cty = DEFAULT_ITERABLE_CONCRETE_TYPES[collections.abc.Sequence] # type: ignore[type-abstract]
33
- return IterableUnmarshaler(cty, ctx.make(check.single(gty.args)))
33
+ return lambda: IterableUnmarshaler(cty, ctx.make_unmarshaler(check.single(rty.args)))
File without changes
@@ -0,0 +1,93 @@
1
+ import typing as ta
2
+
3
+ from .... import check
4
+ from .... import collections as col
5
+ from .... import dataclasses as dc
6
+ from .... import lang
7
+ from .... import reflect as rfl
8
+ from ...base.contexts import MarshalContext
9
+ from ...base.contexts import MarshalFactoryContext
10
+ from ...base.contexts import UnmarshalContext
11
+ from ...base.contexts import UnmarshalFactoryContext
12
+ from ...base.types import Marshaler
13
+ from ...base.types import MarshalerFactory
14
+ from ...base.types import Unmarshaler
15
+ from ...base.types import UnmarshalerFactory
16
+ from ...base.values import Value
17
+
18
+
19
+ ##
20
+
21
+
22
+ LITERAL_UNION_TYPES: tuple[type, ...] = (
23
+ int,
24
+ str,
25
+ )
26
+
27
+
28
+ class DestructuredLiteralUnionType(ta.NamedTuple):
29
+ v_ty: type
30
+ lit: rfl.Literal
31
+ non_lit: rfl.Type
32
+
33
+
34
+ def _destructure_literal_union_type(rty: rfl.Type) -> DestructuredLiteralUnionType | None:
35
+ if not isinstance(rty, rfl.Union):
36
+ return None
37
+ lits, non_lits = col.partition(rty.args, lang.isinstance_of(rfl.Literal)) # noqa
38
+ if len(lits) != 1 or len(non_lits) != 1:
39
+ return None
40
+ lit = check.isinstance(check.single(lits), rfl.Literal)
41
+ v_tys = set(map(type, lit.args))
42
+ if len(v_tys) != 1:
43
+ return None
44
+ [v_ty] = v_tys
45
+ if v_ty in rty.args or v_ty not in LITERAL_UNION_TYPES:
46
+ return None
47
+ return DestructuredLiteralUnionType(v_ty, lit, check.single(non_lits))
48
+
49
+
50
+ #
51
+
52
+
53
+ @dc.dataclass(frozen=True)
54
+ class LiteralUnionMarshaler(Marshaler):
55
+ v_ty: type
56
+ l: Marshaler
57
+ x: Marshaler
58
+
59
+ def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
60
+ if isinstance(o, self.v_ty):
61
+ return self.l.marshal(ctx, o)
62
+ else:
63
+ return self.x.marshal(ctx, o)
64
+
65
+
66
+ class LiteralUnionMarshalerFactory(MarshalerFactory):
67
+ def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
68
+ if (ds := _destructure_literal_union_type(rty)) is None:
69
+ return None
70
+ return lambda: LiteralUnionMarshaler(ds.v_ty, ctx.make_marshaler(ds.lit), ctx.make_marshaler(ds.non_lit))
71
+
72
+
73
+ #
74
+
75
+
76
+ @dc.dataclass(frozen=True)
77
+ class LiteralUnionUnmarshaler(Unmarshaler):
78
+ v_ty: type
79
+ l: Unmarshaler
80
+ x: Unmarshaler
81
+
82
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
83
+ if isinstance(v, self.v_ty):
84
+ return self.l.unmarshal(ctx, v) # type: ignore[arg-type]
85
+ else:
86
+ return self.x.unmarshal(ctx, v)
87
+
88
+
89
+ class LiteralUnionUnmarshalerFactory(UnmarshalerFactory):
90
+ def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
91
+ if (ds := _destructure_literal_union_type(rty)) is None:
92
+ return None
93
+ return lambda: LiteralUnionUnmarshaler(ds.v_ty, ctx.make_unmarshaler(ds.lit), ctx.make_unmarshaler(ds.non_lit))
@@ -0,0 +1,103 @@
1
+ import typing as ta
2
+
3
+ from .... import check
4
+ from .... import collections as col
5
+ from .... import dataclasses as dc
6
+ from .... import reflect as rfl
7
+ from ...base.contexts import MarshalContext
8
+ from ...base.contexts import MarshalFactoryContext
9
+ from ...base.contexts import UnmarshalContext
10
+ from ...base.contexts import UnmarshalFactoryContext
11
+ from ...base.types import Marshaler
12
+ from ...base.types import MarshalerFactory
13
+ from ...base.types import Unmarshaler
14
+ from ...base.types import UnmarshalerFactory
15
+ from ...base.values import Value
16
+
17
+
18
+ ##
19
+
20
+
21
+ PRIMITIVE_UNION_TYPES: tuple[type, ...] = (
22
+ float,
23
+ int,
24
+ str,
25
+ bool,
26
+ )
27
+
28
+
29
+ class DestructuredPrimitiveUnionType(ta.NamedTuple):
30
+ prim: ta.Sequence[type]
31
+ non_prim: ta.Sequence[rfl.Type]
32
+
33
+
34
+ def _destructure_primitive_union_type(
35
+ rty: rfl.Type,
36
+ prim_tys: ta.Container[type] = PRIMITIVE_UNION_TYPES,
37
+ ) -> DestructuredPrimitiveUnionType | None:
38
+ if not isinstance(rty, rfl.Union):
39
+ return None
40
+
41
+ pr = col.partition(rty.args, lambda a: isinstance(a, type) and a in prim_tys)
42
+ if not pr.t or len(pr.f) > 1:
43
+ return None
44
+
45
+ return DestructuredPrimitiveUnionType(*pr) # type: ignore[arg-type]
46
+
47
+
48
+ #
49
+
50
+
51
+ @dc.dataclass(frozen=True)
52
+ class PrimitiveUnionMarshaler(Marshaler):
53
+ tys: ta.Sequence[type]
54
+ x: Marshaler | None = None
55
+
56
+ def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
57
+ if type(o) not in self.tys:
58
+ if self.x is not None:
59
+ return self.x.marshal(ctx, o)
60
+ raise TypeError(o)
61
+ return o
62
+
63
+
64
+ @dc.dataclass(frozen=True)
65
+ class PrimitiveUnionMarshalerFactory(MarshalerFactory):
66
+ tys: ta.Sequence[type] = PRIMITIVE_UNION_TYPES
67
+
68
+ def make_marshaler(self, ctx: MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
69
+ if (ds := _destructure_primitive_union_type(rty, self.tys)) is None:
70
+ return None
71
+ return lambda: PrimitiveUnionMarshaler(
72
+ ds.prim,
73
+ ctx.make_marshaler(check.single(ds.non_prim)) if ds.non_prim else None,
74
+ )
75
+
76
+
77
+ #
78
+
79
+
80
+ @dc.dataclass(frozen=True)
81
+ class PrimitiveUnionUnmarshaler(Unmarshaler):
82
+ tys: ta.Sequence[type]
83
+ x: Unmarshaler | None = None
84
+
85
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
86
+ if type(v) not in self.tys:
87
+ if self.x is not None:
88
+ return self.x.unmarshal(ctx, v)
89
+ raise TypeError(v)
90
+ return v
91
+
92
+
93
+ @dc.dataclass(frozen=True)
94
+ class PrimitiveUnionUnmarshalerFactory(UnmarshalerFactory):
95
+ tys: ta.Sequence[type] = PRIMITIVE_UNION_TYPES
96
+
97
+ def make_unmarshaler(self, ctx: UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
98
+ if (ds := _destructure_primitive_union_type(rty, self.tys)) is None:
99
+ return None
100
+ return lambda: PrimitiveUnionUnmarshaler(
101
+ ds.prim,
102
+ ctx.make_unmarshaler(check.single(ds.non_prim)) if ds.non_prim else None,
103
+ )