omlish 0.0.0.dev454__py3-none-any.whl → 0.0.0.dev456__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 (48) hide show
  1. omlish/__about__.py +2 -2
  2. omlish/lang/__init__.py +7 -1
  3. omlish/lang/functions.py +2 -2
  4. omlish/lang/iterables.py +0 -8
  5. omlish/lang/sequences.py +124 -0
  6. omlish/marshal/__init__.py +6 -0
  7. omlish/marshal/base/configs.py +12 -0
  8. omlish/marshal/base/contexts.py +32 -16
  9. omlish/marshal/base/funcs.py +4 -12
  10. omlish/marshal/base/options.py +8 -0
  11. omlish/marshal/base/registries.py +32 -4
  12. omlish/marshal/base/types.py +27 -13
  13. omlish/marshal/composite/iterables.py +10 -8
  14. omlish/marshal/composite/literals.py +6 -4
  15. omlish/marshal/composite/mappings.py +10 -8
  16. omlish/marshal/composite/maybes.py +10 -8
  17. omlish/marshal/composite/newtypes.py +6 -6
  18. omlish/marshal/composite/optionals.py +6 -4
  19. omlish/marshal/composite/special.py +6 -6
  20. omlish/marshal/composite/unions/literals.py +6 -4
  21. omlish/marshal/composite/unions/primitives.py +6 -4
  22. omlish/marshal/factories/invalidate.py +4 -4
  23. omlish/marshal/factories/method.py +4 -6
  24. omlish/marshal/factories/moduleimport/factories.py +6 -6
  25. omlish/marshal/factories/multi.py +4 -4
  26. omlish/marshal/factories/recursive.py +4 -2
  27. omlish/marshal/factories/typecache.py +4 -9
  28. omlish/marshal/factories/typemap.py +4 -4
  29. omlish/marshal/objects/dataclasses.py +30 -16
  30. omlish/marshal/objects/marshal.py +4 -3
  31. omlish/marshal/objects/namedtuples.py +6 -6
  32. omlish/marshal/objects/unmarshal.py +4 -3
  33. omlish/marshal/polymorphism/marshal.py +4 -3
  34. omlish/marshal/polymorphism/unions.py +7 -7
  35. omlish/marshal/polymorphism/unmarshal.py +4 -3
  36. omlish/marshal/singular/enums.py +4 -2
  37. omlish/marshal/trivial/any.py +1 -1
  38. omlish/marshal/trivial/forbidden.py +4 -4
  39. omlish/specs/jsonrpc/_marshal.py +4 -4
  40. omlish/specs/openapi/_marshal.py +16 -10
  41. omlish/typedvalues/marshal.py +14 -14
  42. {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/METADATA +1 -1
  43. {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/RECORD +47 -47
  44. omlish/funcs/match.py +0 -229
  45. {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/WHEEL +0 -0
  46. {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/entry_points.txt +0 -0
  47. {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/licenses/LICENSE +0 -0
  48. {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/top_level.txt +0 -0
omlish/funcs/match.py DELETED
@@ -1,229 +0,0 @@
1
- """
2
- Analogous to scala's partial functions ( https://www.scala-lang.org/api/current/scala/PartialFunction.html ).
3
-
4
- TODO:
5
- - unify MatchFnClass with dispatch.method?
6
- - __call__ = mfs.method(); @__call__.register(lambda: ...) def _call_... ?
7
- - not really the same thing, dispatch is unordered this is necessarily ordered
8
- - !! well.. unify interface at least?
9
- - guard(*a, **k) -> bool + fn(*a, **k) -> T becomes dispatch(*a, **k) -> (Callable -> T) | None
10
- """
11
- import abc
12
- import dataclasses as dc
13
- import typing as ta
14
-
15
- from .. import lang
16
-
17
-
18
- T = ta.TypeVar('T')
19
- P = ta.ParamSpec('P')
20
-
21
-
22
- ##
23
-
24
-
25
- class MatchGuardError(Exception):
26
- pass
27
-
28
-
29
- class MatchFn(lang.Abstract, ta.Generic[P, T]):
30
- @abc.abstractmethod
31
- def guard(self, *args: P.args, **kwargs: P.kwargs) -> bool:
32
- raise NotImplementedError
33
-
34
- @abc.abstractmethod
35
- def fn(self, *args: P.args, **kwargs: P.kwargs) -> T:
36
- raise NotImplementedError
37
-
38
- def __get__(self, instance, owner=None):
39
- return self
40
-
41
- @ta.final
42
- def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
43
- if not self.guard(*args, **kwargs):
44
- raise MatchGuardError(*args, **kwargs)
45
- return self.fn(*args, **kwargs)
46
-
47
-
48
- ##
49
-
50
-
51
- @dc.dataclass(frozen=True)
52
- class SimpleMatchFn(MatchFn[P, T]):
53
- _guard: ta.Callable[P, bool]
54
- _fn: ta.Callable[P, T]
55
-
56
- def guard(self, *args: P.args, **kwargs: P.kwargs) -> bool:
57
- return self._guard(*args, **kwargs)
58
-
59
- def fn(self, *args: P.args, **kwargs: P.kwargs) -> T:
60
- return self._fn(*args, **kwargs)
61
-
62
- def __get__(self, instance, owner=None):
63
- return self.__class__(
64
- self._guard.__get__(instance, owner), # noqa
65
- self._fn.__get__(instance, owner), # noqa
66
- )
67
-
68
-
69
- @ta.overload
70
- def simple(guard: ta.Callable[..., bool], fn: ta.Callable[P, T]) -> SimpleMatchFn[P, T]:
71
- ...
72
-
73
-
74
- @ta.overload
75
- def simple(guard: ta.Callable[..., bool]) -> ta.Callable[[ta.Callable[P, T]], SimpleMatchFn[P, T]]:
76
- ...
77
-
78
-
79
- def simple(guard, fn=None):
80
- def inner(fn): # noqa
81
- return SimpleMatchFn(guard, fn)
82
- if fn is not None:
83
- return inner(fn)
84
- else:
85
- return inner
86
-
87
-
88
- ##
89
-
90
-
91
- class AmbiguousMatchesError(Exception):
92
- pass
93
-
94
-
95
- @dc.dataclass(frozen=True)
96
- class MultiMatchFn(MatchFn[P, T]):
97
- children: ta.Sequence[MatchFn[P, T]]
98
- strict: bool = False
99
-
100
- def match(self, *args: P.args, **kwargs: P.kwargs) -> MatchFn[P, T] | None:
101
- matches = []
102
- for cur in self.children:
103
- if cur.guard(*args, **kwargs):
104
- if self.strict:
105
- matches.append(cur)
106
- else:
107
- return cur
108
- if not matches:
109
- return None
110
- elif len(matches) > 1:
111
- raise AmbiguousMatchesError
112
- else:
113
- return matches[0]
114
-
115
- def guard(self, *args: P.args, **kwargs: P.kwargs) -> bool:
116
- return self.match(*args, **kwargs) is not None
117
-
118
- def fn(self, *args: P.args, **kwargs: P.kwargs) -> T:
119
- if (m := self.match(*args, **kwargs)) is None:
120
- raise MatchGuardError(*args, **kwargs)
121
- return m.fn(*args, **kwargs)
122
-
123
- def __get__(self, instance, owner=None):
124
- return self.__class__(
125
- [c.__get__(instance, owner) for c in self.children],
126
- strict=self.strict,
127
- )
128
-
129
-
130
- def multi(*children: MatchFn[P, T], strict: bool = False) -> MultiMatchFn: # MultiMatchFn[P[0], T[-1]]
131
- return MultiMatchFn(children, strict=strict) # noqa
132
-
133
-
134
- ##
135
-
136
-
137
- class CachedMatchFn(MatchFn[P, T]):
138
- @staticmethod
139
- def _default_key(*args, **kwargs):
140
- return (args, tuple(sorted(kwargs.items(), key=lambda t: t[0])))
141
-
142
- def __init__(
143
- self,
144
- f: MatchFn[P, T],
145
- *,
146
- key: ta.Callable[P, ta.Any] = _default_key,
147
- lock: lang.DefaultLockable = None,
148
- ) -> None:
149
- super().__init__()
150
-
151
- self._f = f
152
- self._key = key
153
- self._lock = lock
154
- self._lock_impl = lang.default_lock(lock)()
155
- self._dct: dict[ta.Any, lang.Maybe[ta.Any]] = {}
156
-
157
- def guard(self, *args: P.args, **kwargs: P.kwargs) -> bool:
158
- with self._lock_impl:
159
- k = self._key(*args, **kwargs)
160
- try:
161
- e = self._dct[k]
162
- except KeyError:
163
- if self._f.guard(*args, **kwargs):
164
- return True
165
- else:
166
- self._dct[k] = lang.empty()
167
- return False
168
- else:
169
- return e.present
170
-
171
- def fn(self, *args: P.args, **kwargs: P.kwargs) -> T:
172
- with self._lock_impl:
173
- k = self._key(*args, **kwargs)
174
- try:
175
- e = self._dct[k]
176
- except KeyError:
177
- try:
178
- ret = self._f(*args, **kwargs)
179
- except MatchGuardError:
180
- self._dct[k] = lang.empty()
181
- raise
182
- else:
183
- self._dct[k] = lang.just(ret)
184
- return ret
185
- else:
186
- if e.present:
187
- return e.must()
188
- else:
189
- raise MatchGuardError(*args, **kwargs)
190
-
191
- def __get__(self, instance, owner=None):
192
- return self.__class__(self._f.__get__(instance, owner), key=self._key) # noqa
193
-
194
-
195
- cached = CachedMatchFn
196
-
197
-
198
- ##
199
-
200
-
201
- class MatchFnClass(MatchFn[P, T]):
202
- _cls_match_fn: ta.ClassVar[MultiMatchFn]
203
-
204
- __match_fn: MatchFn[P, T] | None = None
205
-
206
- @property
207
- def _match_fn(self) -> MatchFn[P, T]:
208
- if (mf := self.__match_fn) is None:
209
- mf = self.__match_fn = self._cls_match_fn.__get__(self)
210
- return mf
211
-
212
- def __init_subclass__(cls, strict: bool = False, **kwargs: ta.Any) -> None:
213
- super().__init_subclass__(**kwargs)
214
-
215
- if '_cls_match_fn' in cls.__dict__:
216
- raise AttributeError('_cls_match_fn')
217
-
218
- d = {}
219
- for c in cls.__mro__:
220
- for a, o in c.__dict__.items():
221
- if isinstance(o, MatchFn) and a not in d:
222
- d[a] = o
223
- cls._cls_match_fn = MultiMatchFn(list(d.values()), strict=strict)
224
-
225
- def guard(self, *args: P.args, **kwargs: P.kwargs) -> bool:
226
- return self._match_fn.guard(*args, **kwargs)
227
-
228
- def fn(self, *args: P.args, **kwargs: P.kwargs) -> T:
229
- return self._match_fn.fn(*args, **kwargs)