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.
- omlish/__about__.py +2 -2
- omlish/lang/__init__.py +7 -1
- omlish/lang/functions.py +2 -2
- omlish/lang/iterables.py +0 -8
- omlish/lang/sequences.py +124 -0
- omlish/marshal/__init__.py +6 -0
- omlish/marshal/base/configs.py +12 -0
- omlish/marshal/base/contexts.py +32 -16
- omlish/marshal/base/funcs.py +4 -12
- omlish/marshal/base/options.py +8 -0
- omlish/marshal/base/registries.py +32 -4
- omlish/marshal/base/types.py +27 -13
- omlish/marshal/composite/iterables.py +10 -8
- omlish/marshal/composite/literals.py +6 -4
- omlish/marshal/composite/mappings.py +10 -8
- omlish/marshal/composite/maybes.py +10 -8
- omlish/marshal/composite/newtypes.py +6 -6
- omlish/marshal/composite/optionals.py +6 -4
- omlish/marshal/composite/special.py +6 -6
- omlish/marshal/composite/unions/literals.py +6 -4
- omlish/marshal/composite/unions/primitives.py +6 -4
- omlish/marshal/factories/invalidate.py +4 -4
- omlish/marshal/factories/method.py +4 -6
- omlish/marshal/factories/moduleimport/factories.py +6 -6
- omlish/marshal/factories/multi.py +4 -4
- omlish/marshal/factories/recursive.py +4 -2
- omlish/marshal/factories/typecache.py +4 -9
- omlish/marshal/factories/typemap.py +4 -4
- omlish/marshal/objects/dataclasses.py +30 -16
- omlish/marshal/objects/marshal.py +4 -3
- omlish/marshal/objects/namedtuples.py +6 -6
- omlish/marshal/objects/unmarshal.py +4 -3
- omlish/marshal/polymorphism/marshal.py +4 -3
- omlish/marshal/polymorphism/unions.py +7 -7
- omlish/marshal/polymorphism/unmarshal.py +4 -3
- omlish/marshal/singular/enums.py +4 -2
- omlish/marshal/trivial/any.py +1 -1
- omlish/marshal/trivial/forbidden.py +4 -4
- omlish/specs/jsonrpc/_marshal.py +4 -4
- omlish/specs/openapi/_marshal.py +16 -10
- omlish/typedvalues/marshal.py +14 -14
- {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/RECORD +47 -47
- omlish/funcs/match.py +0 -229
- {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev454.dist-info → omlish-0.0.0.dev456.dist-info}/licenses/LICENSE +0 -0
- {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)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|