omlish 0.0.0.dev452__py3-none-any.whl → 0.0.0.dev454__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 (61) hide show
  1. omlish/__about__.py +2 -2
  2. omlish/collections/__init__.py +7 -1
  3. omlish/collections/attrregistry.py +182 -0
  4. omlish/collections/identity.py +1 -0
  5. omlish/collections/mappings.py +25 -0
  6. omlish/dataclasses/__init__.py +2 -0
  7. omlish/dispatch/methods.py +50 -140
  8. omlish/dom/rendering.py +1 -1
  9. omlish/funcs/guard.py +225 -0
  10. omlish/graphs/dot/rendering.py +1 -1
  11. omlish/lang/__init__.py +1 -0
  12. omlish/lang/iterables.py +8 -0
  13. omlish/lite/attrops.py +2 -0
  14. omlish/lite/dataclasses.py +30 -0
  15. omlish/lite/maybes.py +8 -0
  16. omlish/marshal/__init__.py +12 -11
  17. omlish/marshal/base/contexts.py +4 -7
  18. omlish/marshal/base/funcs.py +16 -11
  19. omlish/marshal/base/types.py +17 -7
  20. omlish/marshal/composite/iterables.py +31 -20
  21. omlish/marshal/composite/literals.py +14 -18
  22. omlish/marshal/composite/mappings.py +34 -23
  23. omlish/marshal/composite/maybes.py +27 -19
  24. omlish/marshal/composite/newtypes.py +14 -14
  25. omlish/marshal/composite/optionals.py +12 -14
  26. omlish/marshal/composite/special.py +13 -13
  27. omlish/marshal/composite/unions/__init__.py +0 -0
  28. omlish/marshal/composite/unions/literals.py +91 -0
  29. omlish/marshal/composite/unions/primitives.py +101 -0
  30. omlish/marshal/factories/invalidate.py +16 -66
  31. omlish/marshal/factories/method.py +28 -0
  32. omlish/marshal/factories/moduleimport/factories.py +13 -54
  33. omlish/marshal/factories/multi.py +11 -23
  34. omlish/marshal/factories/recursive.py +40 -56
  35. omlish/marshal/factories/typecache.py +23 -75
  36. omlish/marshal/factories/typemap.py +40 -41
  37. omlish/marshal/objects/dataclasses.py +106 -97
  38. omlish/marshal/objects/marshal.py +15 -12
  39. omlish/marshal/objects/namedtuples.py +46 -40
  40. omlish/marshal/objects/unmarshal.py +16 -13
  41. omlish/marshal/polymorphism/marshal.py +6 -9
  42. omlish/marshal/polymorphism/unions.py +15 -9
  43. omlish/marshal/polymorphism/unmarshal.py +6 -8
  44. omlish/marshal/singular/enums.py +12 -18
  45. omlish/marshal/standard.py +8 -8
  46. omlish/marshal/trivial/forbidden.py +19 -24
  47. omlish/os/forkhooks.py +4 -0
  48. omlish/specs/jsonrpc/_marshal.py +33 -24
  49. omlish/specs/openapi/_marshal.py +20 -17
  50. omlish/sql/queries/rendering.py +1 -1
  51. omlish/text/parts.py +2 -2
  52. omlish/typedvalues/marshal.py +81 -55
  53. {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev454.dist-info}/METADATA +1 -1
  54. {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev454.dist-info}/RECORD +58 -55
  55. omlish/marshal/composite/unions.py +0 -213
  56. omlish/marshal/factories/match.py +0 -34
  57. omlish/marshal/factories/simple.py +0 -28
  58. {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev454.dist-info}/WHEEL +0 -0
  59. {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev454.dist-info}/entry_points.txt +0 -0
  60. {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev454.dist-info}/licenses/LICENSE +0 -0
  61. {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev454.dist-info}/top_level.txt +0 -0
@@ -4,14 +4,13 @@ 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
9
8
  from ..base.contexts import UnmarshalContext
10
9
  from ..base.types import Marshaler
11
10
  from ..base.types import Unmarshaler
12
11
  from ..base.values import Value
13
- from ..factories.match import MarshalerFactoryMatchClass
14
- from ..factories.match import UnmarshalerFactoryMatchClass
12
+ from ..factories.method import MarshalerFactoryMethodClass
13
+ from ..factories.method import UnmarshalerFactoryMethodClass
15
14
 
16
15
 
17
16
  ##
@@ -23,6 +22,9 @@ DEFAULT_MAPPING_CONCRETE_TYPES: dict[type[collections.abc.Mapping], type[collect
23
22
  }
24
23
 
25
24
 
25
+ #
26
+
27
+
26
28
  @dc.dataclass(frozen=True)
27
29
  class MappingMarshaler(Marshaler):
28
30
  ke: Marshaler
@@ -35,16 +37,22 @@ class MappingMarshaler(Marshaler):
35
37
  }
36
38
 
37
39
 
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))
40
+ class MappingMarshalerFactory(MarshalerFactoryMethodClass):
41
+ @MarshalerFactoryMethodClass.make_marshaler.register
42
+ def _build_generic(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
43
+ if not (isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping)):
44
+ return None
45
+ kt, vt = rty.args
46
+ return lambda: MappingMarshaler(ctx.make(kt), ctx.make(vt))
47
+
48
+ @MarshalerFactoryMethodClass.make_marshaler.register
49
+ def _build_concrete(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
50
+ if not (isinstance(rty, type) and issubclass(rty, collections.abc.Mapping)):
51
+ return None
52
+ return lambda: MappingMarshaler(a := ctx.make(ta.Any), a)
44
53
 
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)
54
+
55
+ #
48
56
 
49
57
 
50
58
  @dc.dataclass(frozen=True)
@@ -60,14 +68,17 @@ class MappingUnmarshaler(Unmarshaler):
60
68
  return self.ctor(dct)
61
69
 
62
70
 
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)
71
+ class MappingUnmarshalerFactory(UnmarshalerFactoryMethodClass):
72
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
73
+ def _build_generic(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
74
+ if not (isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping)):
75
+ return None
76
+ cty = DEFAULT_MAPPING_CONCRETE_TYPES.get(rty.cls, rty.cls) # noqa
77
+ kt, vt = rty.args
78
+ return lambda: MappingUnmarshaler(cty, ctx.make(kt), ctx.make(vt))
79
+
80
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
81
+ def _build_concrete(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
82
+ if not (isinstance(rty, type) and issubclass(rty, collections.abc.Mapping)):
83
+ return None
84
+ return lambda: MappingUnmarshaler(check.isinstance(rty, type), a := ctx.make(ta.Any), a)
@@ -8,14 +8,13 @@ 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
13
12
  from ..base.contexts import UnmarshalContext
14
13
  from ..base.types import Marshaler
15
14
  from ..base.types import Unmarshaler
16
15
  from ..base.values import Value
17
- from ..factories.match import MarshalerFactoryMatchClass
18
- from ..factories.match import UnmarshalerFactoryMatchClass
16
+ from ..factories.method import MarshalerFactoryMethodClass
17
+ from ..factories.method import UnmarshalerFactoryMethodClass
19
18
 
20
19
 
21
20
  ##
@@ -33,15 +32,21 @@ class MaybeMarshaler(Marshaler):
33
32
  return []
34
33
 
35
34
 
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)))
35
+ class MaybeMarshalerFactory(MarshalerFactoryMethodClass):
36
+ @MarshalerFactoryMethodClass.make_marshaler.register
37
+ def _make_generic(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
38
+ if not (isinstance(rty, rfl.Generic) and rty.cls is lang.Maybe):
39
+ return None
40
+ return lambda: MaybeMarshaler(ctx.make(check.single(rty.args)))
41
41
 
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))
42
+ @MarshalerFactoryMethodClass.make_marshaler.register
43
+ def _make_concrete(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
44
+ if not (isinstance(rty, type) and issubclass(rty, lang.Maybe)):
45
+ return None
46
+ return lambda: MaybeMarshaler(ctx.make(ta.Any))
47
+
48
+
49
+ #
45
50
 
46
51
 
47
52
  @dc.dataclass(frozen=True)
@@ -55,12 +60,15 @@ class MaybeUnmarshaler(Unmarshaler):
55
60
  return lang.empty()
56
61
 
57
62
 
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)))
63
+ class MaybeUnmarshalerFactory(UnmarshalerFactoryMethodClass):
64
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
65
+ def _make_generic(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
66
+ if not (isinstance(rty, rfl.Generic) and rty.cls is lang.Maybe):
67
+ return None
68
+ return lambda: MaybeUnmarshaler(ctx.make(check.single(rty.args)))
63
69
 
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))
70
+ @UnmarshalerFactoryMethodClass.make_unmarshaler.register
71
+ def _make_concrete(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
72
+ if not (isinstance(rty, type) and issubclass(rty, lang.Maybe)):
73
+ return None
74
+ return lambda: MaybeUnmarshaler(ctx.make(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
5
  from ..base.contexts import MarshalContext
4
6
  from ..base.contexts import UnmarshalContext
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: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
18
+ if not isinstance(rty, rfl.NewType):
19
+ return None
20
+ return lambda: ctx.make(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: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
25
+ if not isinstance(rty, rfl.NewType):
26
+ return None
27
+ return lambda: ctx.make(check.isinstance(rty, rfl.NewType).ty)
@@ -6,10 +6,10 @@ from ... import reflect as rfl
6
6
  from ..base.contexts import MarshalContext
7
7
  from ..base.contexts import UnmarshalContext
8
8
  from ..base.types import Marshaler
9
+ from ..base.types import MarshalerFactory
9
10
  from ..base.types import Unmarshaler
11
+ from ..base.types import UnmarshalerFactory
10
12
  from ..base.values import Value
11
- from ..factories.simple import SimpleMarshalerFactory
12
- from ..factories.simple import SimpleUnmarshalerFactory
13
13
 
14
14
 
15
15
  ##
@@ -25,12 +25,11 @@ class OptionalMarshaler(Marshaler):
25
25
  return self.e.marshal(ctx, o)
26
26
 
27
27
 
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()))
28
+ class OptionalMarshalerFactory(MarshalerFactory):
29
+ def make_marshaler(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
30
+ if not (isinstance(rty, rfl.Union) and rty.is_optional):
31
+ return None
32
+ return lambda: OptionalMarshaler(ctx.make(check.isinstance(rty, rfl.Union).without_none()))
34
33
 
35
34
 
36
35
  @dc.dataclass(frozen=True)
@@ -43,9 +42,8 @@ class OptionalUnmarshaler(Unmarshaler):
43
42
  return self.e.unmarshal(ctx, v)
44
43
 
45
44
 
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()))
45
+ class OptionalUnmarshalerFactory(UnmarshalerFactory):
46
+ def make_unmarshaler(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
47
+ if not (isinstance(rty, rfl.Union) and rty.is_optional):
48
+ return None
49
+ return lambda: OptionalUnmarshaler(ctx.make(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
7
  from ..base.contexts import MarshalContext
8
8
  from ..base.contexts import UnmarshalContext
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: MarshalContext, 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(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: UnmarshalContext, 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(check.single(rty.args)))
File without changes
@@ -0,0 +1,91 @@
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 UnmarshalContext
10
+ from ...base.types import Marshaler
11
+ from ...base.types import MarshalerFactory
12
+ from ...base.types import Unmarshaler
13
+ from ...base.types import UnmarshalerFactory
14
+ from ...base.values import Value
15
+
16
+
17
+ ##
18
+
19
+
20
+ LITERAL_UNION_TYPES: tuple[type, ...] = (
21
+ int,
22
+ str,
23
+ )
24
+
25
+
26
+ class DestructuredLiteralUnionType(ta.NamedTuple):
27
+ v_ty: type
28
+ lit: rfl.Literal
29
+ non_lit: rfl.Type
30
+
31
+
32
+ def _destructure_literal_union_type(rty: rfl.Type) -> DestructuredLiteralUnionType | None:
33
+ if not isinstance(rty, rfl.Union):
34
+ return None
35
+ lits, non_lits = col.partition(rty.args, lang.isinstance_of(rfl.Literal)) # noqa
36
+ if len(lits) != 1 or len(non_lits) != 1:
37
+ return None
38
+ lit = check.isinstance(check.single(lits), rfl.Literal)
39
+ v_tys = set(map(type, lit.args))
40
+ if len(v_tys) != 1:
41
+ return None
42
+ [v_ty] = v_tys
43
+ if v_ty in rty.args or v_ty not in LITERAL_UNION_TYPES:
44
+ return None
45
+ return DestructuredLiteralUnionType(v_ty, lit, check.single(non_lits))
46
+
47
+
48
+ #
49
+
50
+
51
+ @dc.dataclass(frozen=True)
52
+ class LiteralUnionMarshaler(Marshaler):
53
+ v_ty: type
54
+ l: Marshaler
55
+ x: Marshaler
56
+
57
+ def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
58
+ if isinstance(o, self.v_ty):
59
+ return self.l.marshal(ctx, o)
60
+ else:
61
+ return self.x.marshal(ctx, o)
62
+
63
+
64
+ class LiteralUnionMarshalerFactory(MarshalerFactory):
65
+ def make_marshaler(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
66
+ if (ds := _destructure_literal_union_type(rty)) is None:
67
+ return None
68
+ return lambda: LiteralUnionMarshaler(ds.v_ty, ctx.make(ds.lit), ctx.make(ds.non_lit))
69
+
70
+
71
+ #
72
+
73
+
74
+ @dc.dataclass(frozen=True)
75
+ class LiteralUnionUnmarshaler(Unmarshaler):
76
+ v_ty: type
77
+ l: Unmarshaler
78
+ x: Unmarshaler
79
+
80
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
81
+ if isinstance(v, self.v_ty):
82
+ return self.l.unmarshal(ctx, v) # type: ignore[arg-type]
83
+ else:
84
+ return self.x.unmarshal(ctx, v)
85
+
86
+
87
+ class LiteralUnionUnmarshalerFactory(UnmarshalerFactory):
88
+ def make_unmarshaler(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
89
+ if (ds := _destructure_literal_union_type(rty)) is None:
90
+ return None
91
+ return lambda: LiteralUnionUnmarshaler(ds.v_ty, ctx.make(ds.lit), ctx.make(ds.non_lit))
@@ -0,0 +1,101 @@
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 UnmarshalContext
9
+ from ...base.types import Marshaler
10
+ from ...base.types import MarshalerFactory
11
+ from ...base.types import Unmarshaler
12
+ from ...base.types import UnmarshalerFactory
13
+ from ...base.values import Value
14
+
15
+
16
+ ##
17
+
18
+
19
+ PRIMITIVE_UNION_TYPES: tuple[type, ...] = (
20
+ float,
21
+ int,
22
+ str,
23
+ bool,
24
+ )
25
+
26
+
27
+ class DestructuredPrimitiveUnionType(ta.NamedTuple):
28
+ prim: ta.Sequence[type]
29
+ non_prim: ta.Sequence[rfl.Type]
30
+
31
+
32
+ def _destructure_primitive_union_type(
33
+ rty: rfl.Type,
34
+ prim_tys: ta.Container[type] = PRIMITIVE_UNION_TYPES,
35
+ ) -> DestructuredPrimitiveUnionType | None:
36
+ if not isinstance(rty, rfl.Union):
37
+ return None
38
+
39
+ pr = col.partition(rty.args, lambda a: isinstance(a, type) and a in prim_tys)
40
+ if not pr.t or len(pr.f) > 1:
41
+ return None
42
+
43
+ return DestructuredPrimitiveUnionType(*pr) # type: ignore[arg-type]
44
+
45
+
46
+ #
47
+
48
+
49
+ @dc.dataclass(frozen=True)
50
+ class PrimitiveUnionMarshaler(Marshaler):
51
+ tys: ta.Sequence[type]
52
+ x: Marshaler | None = None
53
+
54
+ def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
55
+ if type(o) not in self.tys:
56
+ if self.x is not None:
57
+ return self.x.marshal(ctx, o)
58
+ raise TypeError(o)
59
+ return o
60
+
61
+
62
+ @dc.dataclass(frozen=True)
63
+ class PrimitiveUnionMarshalerFactory(MarshalerFactory):
64
+ tys: ta.Sequence[type] = PRIMITIVE_UNION_TYPES
65
+
66
+ def make_marshaler(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
67
+ if (ds := _destructure_primitive_union_type(rty, self.tys)) is None:
68
+ return None
69
+ return lambda: PrimitiveUnionMarshaler(
70
+ ds.prim,
71
+ ctx.make(check.single(ds.non_prim)) if ds.non_prim else None,
72
+ )
73
+
74
+
75
+ #
76
+
77
+
78
+ @dc.dataclass(frozen=True)
79
+ class PrimitiveUnionUnmarshaler(Unmarshaler):
80
+ tys: ta.Sequence[type]
81
+ x: Unmarshaler | None = None
82
+
83
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
84
+ if type(v) not in self.tys:
85
+ if self.x is not None:
86
+ return self.x.unmarshal(ctx, v)
87
+ raise TypeError(v)
88
+ return v
89
+
90
+
91
+ @dc.dataclass(frozen=True)
92
+ class PrimitiveUnionUnmarshalerFactory(UnmarshalerFactory):
93
+ tys: ta.Sequence[type] = PRIMITIVE_UNION_TYPES
94
+
95
+ def make_unmarshaler(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
96
+ if (ds := _destructure_primitive_union_type(rty, self.tys)) is None:
97
+ return None
98
+ return lambda: PrimitiveUnionUnmarshaler(
99
+ ds.prim,
100
+ ctx.make(check.single(ds.non_prim)) if ds.non_prim else None,
101
+ )
@@ -2,44 +2,39 @@ import threading
2
2
  import typing as ta
3
3
 
4
4
  from ... import reflect as rfl
5
- from ...funcs import match as mfs
6
- from ..base.contexts import BaseContext
7
5
  from ..base.contexts import MarshalContext
8
6
  from ..base.contexts import UnmarshalContext
9
7
  from ..base.types import Marshaler
10
8
  from ..base.types import MarshalerFactory
11
- from ..base.types import MarshalerMaker
12
9
  from ..base.types import Unmarshaler
13
10
  from ..base.types import UnmarshalerFactory
14
- from ..base.types import UnmarshalerMaker
15
11
 
16
12
 
17
- R = ta.TypeVar('R')
18
- ContextT = ta.TypeVar('ContextT', bound=BaseContext)
13
+ FactoryT = ta.TypeVar('FactoryT', bound=MarshalerFactory | UnmarshalerFactory)
19
14
 
20
15
 
21
16
  ##
22
17
 
23
18
 
24
- class _InvalidatableFactory(mfs.MatchFn[[ContextT, rfl.Type], R]):
19
+ class _InvalidatableFactory(ta.Generic[FactoryT]):
25
20
  def __init__(
26
21
  self,
27
- fn: ta.Callable[[], mfs.MatchFn[[ContextT, rfl.Type], R]],
22
+ fac_fac: ta.Callable,
28
23
  check_fn: ta.Callable[[], bool] | None = None,
29
24
  ) -> None:
30
25
  super().__init__()
31
26
 
32
- self._fn = fn
27
+ self._fac_fac = fac_fac
33
28
  self._check_fn: ta.Callable[[], bool] | None = check_fn
34
29
 
35
30
  self._lock = threading.RLock()
36
31
 
37
32
  #
38
33
 
39
- _f_: mfs.MatchFn[[ContextT, rfl.Type], R] | None = None
34
+ __fac: FactoryT | None = None
40
35
 
41
36
  def _invalidate(self) -> None:
42
- self._f_ = None
37
+ self.__fac = None
43
38
 
44
39
  def invalidate(self) -> None:
45
40
  with self._lock:
@@ -52,67 +47,22 @@ class _InvalidatableFactory(mfs.MatchFn[[ContextT, rfl.Type], R]):
52
47
  if self._check_fn():
53
48
  self._invalidate()
54
49
 
55
- def _f(self) -> mfs.MatchFn[[ContextT, rfl.Type], R]:
50
+ def _fac(self) -> FactoryT:
56
51
  self._maybe_invalidate()
57
52
 
58
- if (f := self._f_) is None:
53
+ if (f := self.__fac) is None:
59
54
  with self._lock:
60
- if (f := self._f_) is None:
61
- f = self._f_ = self._fn()
55
+ if (f := self.__fac) is None:
56
+ f = self.__fac = self._fac_fac()
62
57
 
63
58
  return f
64
59
 
65
- #
66
-
67
- def guard(self, ctx: ContextT, rty: rfl.Type) -> bool:
68
- return self._f().guard(ctx, rty)
69
-
70
- def fn(self, ctx: ContextT, rty: rfl.Type) -> R:
71
- return self._f()(ctx, rty)
72
-
73
-
74
- ##
75
-
76
-
77
- class InvalidatableMarshalerFactory(MarshalerFactory):
78
- def __init__(
79
- self,
80
- fn: ta.Callable[[], MarshalerFactory],
81
- check_fn: ta.Callable[[], bool] | None = None,
82
- ) -> None:
83
- super().__init__()
84
60
 
85
- self._fn = fn
86
- self._u: _InvalidatableFactory[MarshalContext, Marshaler] = _InvalidatableFactory(
87
- lambda: fn().make_marshaler,
88
- check_fn,
89
- )
61
+ class InvalidatableMarshalerFactory(_InvalidatableFactory[MarshalerFactory], MarshalerFactory):
62
+ def make_marshaler(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
63
+ return self._fac().make_marshaler(ctx, rty)
90
64
 
91
- def invalidate(self) -> None:
92
- self._u.invalidate()
93
-
94
- @property
95
- def make_marshaler(self) -> MarshalerMaker:
96
- return self._u
97
-
98
-
99
- class InvalidatableUnmarshalerFactory(UnmarshalerFactory):
100
- def __init__(
101
- self,
102
- fn: ta.Callable[[], UnmarshalerFactory],
103
- check_fn: ta.Callable[[], bool] | None = None,
104
- ) -> None:
105
- super().__init__()
106
-
107
- self._fn = fn
108
- self._u: _InvalidatableFactory[UnmarshalContext, Unmarshaler] = _InvalidatableFactory(
109
- lambda: fn().make_unmarshaler,
110
- check_fn,
111
- )
112
-
113
- def invalidate(self) -> None:
114
- self._u.invalidate()
115
65
 
116
- @property
117
- def make_unmarshaler(self) -> UnmarshalerMaker:
118
- return self._u
66
+ class InvalidatableUnmarshalerFactory(_InvalidatableFactory[UnmarshalerFactory], UnmarshalerFactory):
67
+ def make_unmarshaler(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
68
+ return self._fac().make_unmarshaler(ctx, rty)
@@ -0,0 +1,28 @@
1
+ import typing as ta
2
+
3
+ from ... import lang
4
+ from ... import reflect as rfl
5
+ from ...funcs import guard as gfs
6
+ from ..base.contexts import MarshalContext
7
+ from ..base.contexts import UnmarshalContext
8
+ from ..base.types import Marshaler
9
+ from ..base.types import MarshalerFactory
10
+ from ..base.types import Unmarshaler
11
+ from ..base.types import UnmarshalerFactory
12
+
13
+
14
+ ##
15
+
16
+
17
+ class MarshalerFactoryMethodClass(MarshalerFactory, lang.Abstract):
18
+ @ta.final
19
+ @gfs.method(instance_cache=True)
20
+ def make_marshaler(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Callable[[], Marshaler] | None:
21
+ raise NotImplementedError
22
+
23
+
24
+ class UnmarshalerFactoryMethodClass(UnmarshalerFactory, lang.Abstract):
25
+ @ta.final
26
+ @gfs.method(instance_cache=True)
27
+ def make_unmarshaler(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Callable[[], Unmarshaler] | None:
28
+ raise NotImplementedError