omlish 0.0.0.dev452__py3-none-any.whl → 0.0.0.dev453__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/collections/__init__.py +7 -1
- omlish/collections/attrregistry.py +182 -0
- omlish/collections/mappings.py +25 -0
- omlish/dispatch/methods.py +50 -140
- omlish/dom/rendering.py +1 -1
- omlish/funcs/guard.py +214 -0
- omlish/graphs/dot/rendering.py +1 -1
- omlish/lite/maybes.py +8 -0
- omlish/sql/queries/rendering.py +1 -1
- omlish/text/parts.py +2 -2
- {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev453.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev453.dist-info}/RECORD +17 -15
- {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev453.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev453.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev453.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev452.dist-info → omlish-0.0.0.dev453.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/collections/__init__.py
CHANGED
@@ -6,6 +6,11 @@ from .. import lang as _lang
|
|
6
6
|
with _lang.auto_proxy_init(globals()):
|
7
7
|
##
|
8
8
|
|
9
|
+
from .attrregistry import ( # noqa
|
10
|
+
AttrRegistry,
|
11
|
+
AttrRegistryCache,
|
12
|
+
)
|
13
|
+
|
9
14
|
from .bimap import ( # noqa
|
10
15
|
BiMap,
|
11
16
|
|
@@ -64,9 +69,10 @@ with _lang.auto_proxy_init(globals()):
|
|
64
69
|
from . import kv # noqa
|
65
70
|
|
66
71
|
from .mappings import ( # noqa
|
72
|
+
DynamicTypeMap,
|
67
73
|
MissingDict,
|
68
74
|
TypeMap,
|
69
|
-
|
75
|
+
dict_factory,
|
70
76
|
guarded_map_update,
|
71
77
|
multikey_dict,
|
72
78
|
)
|
@@ -0,0 +1,182 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import typing as ta
|
3
|
+
import weakref
|
4
|
+
|
5
|
+
from .. import check
|
6
|
+
from .. import lang
|
7
|
+
from .mappings import dict_factory
|
8
|
+
|
9
|
+
|
10
|
+
T = ta.TypeVar('T')
|
11
|
+
K = ta.TypeVar('K')
|
12
|
+
V = ta.TypeVar('V')
|
13
|
+
|
14
|
+
|
15
|
+
##
|
16
|
+
|
17
|
+
|
18
|
+
class AttrRegistry(ta.Generic[K, V]):
|
19
|
+
"""
|
20
|
+
MRO-honoring class member registry. There are many ways to do this, and this one is attr name based: a class is
|
21
|
+
considered to have objects registered to it based on whether or not they are accessible by a non-shadowed,
|
22
|
+
MRO-resolved named attribute on that class.
|
23
|
+
|
24
|
+
Care must be taken when overriding registered objects from superclasses in subclasses - shadowing the attribute name
|
25
|
+
of the superclass member will not automatically register the new member with the same name to the registry - it must
|
26
|
+
be explicitly registered itself. This is a feature, allowing for selective de-registration of objects in subclasses
|
27
|
+
via name shadowing.
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(
|
31
|
+
self,
|
32
|
+
*,
|
33
|
+
requires_override: bool = False,
|
34
|
+
is_override: ta.Callable[[ta.Any], bool] | None = None,
|
35
|
+
forbid_duplicates: bool = False,
|
36
|
+
identity: bool = False,
|
37
|
+
weak: bool = False,
|
38
|
+
) -> None:
|
39
|
+
super().__init__()
|
40
|
+
|
41
|
+
self._requires_override = requires_override
|
42
|
+
self._is_override = is_override
|
43
|
+
self._forbid_duplicates = forbid_duplicates
|
44
|
+
self._identity = identity
|
45
|
+
self._weak = weak
|
46
|
+
|
47
|
+
self._objs: ta.MutableMapping[K, V] = dict_factory(identity=identity, weak=weak)()
|
48
|
+
self._invalidate_callbacks: list[ta.Callable[[], None]] = []
|
49
|
+
|
50
|
+
def add_invalidate_callback(self, callback: ta.Callable[[], None]) -> None:
|
51
|
+
self._invalidate_callbacks.append(callback)
|
52
|
+
|
53
|
+
def register(self, obj: K, val: V) -> None:
|
54
|
+
check.not_in(obj, self._objs)
|
55
|
+
|
56
|
+
self._objs[obj] = val
|
57
|
+
|
58
|
+
for iv in self._invalidate_callbacks:
|
59
|
+
iv()
|
60
|
+
|
61
|
+
def _lookup(self, obj: ta.Any) -> lang.Maybe[V]:
|
62
|
+
if not self._identity:
|
63
|
+
try:
|
64
|
+
hash(obj)
|
65
|
+
except TypeError:
|
66
|
+
return lang.empty()
|
67
|
+
|
68
|
+
try:
|
69
|
+
val = self._objs[obj]
|
70
|
+
except KeyError:
|
71
|
+
return lang.empty()
|
72
|
+
else:
|
73
|
+
return lang.just(val)
|
74
|
+
|
75
|
+
@dc.dataclass()
|
76
|
+
class DuplicatesForbiddenError(Exception):
|
77
|
+
owner_cls: type
|
78
|
+
instance_cls: type
|
79
|
+
att: str
|
80
|
+
ex_att: str
|
81
|
+
|
82
|
+
def collect(self, instance_cls: type, owner_cls: type | None = None) -> dict[str, tuple[K, V]]:
|
83
|
+
if owner_cls is None:
|
84
|
+
owner_cls = instance_cls
|
85
|
+
|
86
|
+
mro = instance_cls.__mro__[-2::-1]
|
87
|
+
try:
|
88
|
+
mro_pos = mro.index(owner_cls)
|
89
|
+
except ValueError:
|
90
|
+
raise TypeError(f'Owner class {owner_cls} not in mro of instance class {instance_cls}') from None
|
91
|
+
|
92
|
+
mro_dct: dict[str, list[tuple[type, ta.Any]]] = {}
|
93
|
+
for cur_cls in mro[:mro_pos + 1]:
|
94
|
+
for att, obj in cur_cls.__dict__.items():
|
95
|
+
if att not in mro_dct:
|
96
|
+
if not self._lookup(obj).present:
|
97
|
+
continue
|
98
|
+
|
99
|
+
try:
|
100
|
+
lst = mro_dct[att]
|
101
|
+
except KeyError:
|
102
|
+
lst = mro_dct[att] = []
|
103
|
+
lst.append((cur_cls, obj))
|
104
|
+
|
105
|
+
#
|
106
|
+
|
107
|
+
seen: ta.MutableMapping[ta.Any, str] | None = None
|
108
|
+
if self._forbid_duplicates:
|
109
|
+
seen = dict_factory(identity=self._identity)()
|
110
|
+
|
111
|
+
out: dict[str, tuple[K, V]] = {}
|
112
|
+
for att, lst in mro_dct.items():
|
113
|
+
if not lst:
|
114
|
+
raise RuntimeError
|
115
|
+
_, obj = lst[-1]
|
116
|
+
|
117
|
+
if len(lst) > 1:
|
118
|
+
if self._requires_override and not (self._is_override or lang.is_override)(obj):
|
119
|
+
raise lang.RequiresOverrideError(
|
120
|
+
att,
|
121
|
+
instance_cls,
|
122
|
+
lst[-1][0],
|
123
|
+
lst[0][0],
|
124
|
+
)
|
125
|
+
|
126
|
+
if not (mv := self._lookup(obj)).present:
|
127
|
+
continue
|
128
|
+
|
129
|
+
if seen is not None:
|
130
|
+
try:
|
131
|
+
ex_att = seen[obj]
|
132
|
+
except KeyError:
|
133
|
+
pass
|
134
|
+
else:
|
135
|
+
raise AttrRegistry.DuplicatesForbiddenError(owner_cls, instance_cls, att, ex_att) # noqa
|
136
|
+
seen[obj] = att
|
137
|
+
|
138
|
+
out[att] = (obj, mv.must())
|
139
|
+
|
140
|
+
return out
|
141
|
+
|
142
|
+
|
143
|
+
##
|
144
|
+
|
145
|
+
|
146
|
+
class AttrRegistryCache(ta.Generic[K, V, T]):
|
147
|
+
def __init__(
|
148
|
+
self,
|
149
|
+
registry: AttrRegistry[K, V],
|
150
|
+
prepare: ta.Callable[[type, dict[str, tuple[K, V]]], T],
|
151
|
+
) -> None:
|
152
|
+
super().__init__()
|
153
|
+
|
154
|
+
self._registry = registry
|
155
|
+
self._prepare = prepare
|
156
|
+
|
157
|
+
self._cache: dict[ta.Any, T] = {}
|
158
|
+
|
159
|
+
def cache_remove(k, self_ref=weakref.ref(self)):
|
160
|
+
if (ref_self := self_ref()) is not None:
|
161
|
+
cache = ref_self._cache # noqa
|
162
|
+
try:
|
163
|
+
del cache[k]
|
164
|
+
except KeyError:
|
165
|
+
pass
|
166
|
+
|
167
|
+
self._cache_remove = cache_remove
|
168
|
+
|
169
|
+
registry.add_invalidate_callback(self._cache.clear)
|
170
|
+
|
171
|
+
def get(self, instance_cls: type) -> T:
|
172
|
+
cls_ref = weakref.ref(instance_cls)
|
173
|
+
try:
|
174
|
+
return self._cache[cls_ref]
|
175
|
+
except KeyError:
|
176
|
+
pass
|
177
|
+
del cls_ref
|
178
|
+
|
179
|
+
collected = self._registry.collect(instance_cls)
|
180
|
+
out = self._prepare(instance_cls, collected)
|
181
|
+
self._cache[weakref.ref(instance_cls, self._cache_remove)] = out
|
182
|
+
return out
|
omlish/collections/mappings.py
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
import typing as ta
|
2
2
|
import weakref
|
3
3
|
|
4
|
+
from .. import lang
|
5
|
+
|
6
|
+
|
7
|
+
with lang.auto_proxy_import(globals()):
|
8
|
+
from . import identity as _identity
|
9
|
+
|
4
10
|
|
5
11
|
T = ta.TypeVar('T')
|
6
12
|
K = ta.TypeVar('K')
|
@@ -141,3 +147,22 @@ class MissingDict(dict[K, V]):
|
|
141
147
|
def __missing__(self, key):
|
142
148
|
v = self[key] = self._missing_fn(key)
|
143
149
|
return v
|
150
|
+
|
151
|
+
|
152
|
+
##
|
153
|
+
|
154
|
+
|
155
|
+
def dict_factory[K, V](
|
156
|
+
*,
|
157
|
+
identity: bool = False,
|
158
|
+
weak: bool = False,
|
159
|
+
) -> ta.Callable[..., ta.MutableMapping[K, V]]:
|
160
|
+
if identity:
|
161
|
+
if weak:
|
162
|
+
return _identity.IdentityWeakKeyDictionary
|
163
|
+
else:
|
164
|
+
return _identity.IdentityKeyDict
|
165
|
+
elif weak:
|
166
|
+
return weakref.WeakKeyDictionary
|
167
|
+
else:
|
168
|
+
return dict
|
omlish/dispatch/methods.py
CHANGED
@@ -4,13 +4,11 @@ TODO:
|
|
4
4
|
- ALT: A.f(super(), ... ? :/
|
5
5
|
- classmethod/staticmethod
|
6
6
|
"""
|
7
|
-
import contextlib
|
8
7
|
import functools
|
9
8
|
import typing as ta
|
10
|
-
import weakref
|
11
9
|
|
12
10
|
from .. import check
|
13
|
-
from .. import
|
11
|
+
from .. import collections as col
|
14
12
|
from .dispatch import Dispatcher
|
15
13
|
from .impls import get_impl_func_cls_set
|
16
14
|
|
@@ -34,9 +32,8 @@ class Method(ta.Generic[P, R]):
|
|
34
32
|
it must be explicitly `@register`'ed itself. This is a feature, allowing for selective de-registration of
|
35
33
|
implementations in subclasses via name shadowing.
|
36
34
|
|
37
|
-
Methods
|
38
|
-
|
39
|
-
visitors.
|
35
|
+
Methods can choose to allow external installation of implementations outside of direct subclasses. This is to be
|
36
|
+
used *extremely* rarely - basically only in the rare case of externally extensible type hierarchies with visitors.
|
40
37
|
"""
|
41
38
|
|
42
39
|
def __init__(
|
@@ -45,6 +42,7 @@ class Method(ta.Generic[P, R]):
|
|
45
42
|
*,
|
46
43
|
installable: bool = False,
|
47
44
|
requires_override: bool = False,
|
45
|
+
instance_cache: bool = False,
|
48
46
|
) -> None:
|
49
47
|
super().__init__()
|
50
48
|
|
@@ -53,9 +51,16 @@ class Method(ta.Generic[P, R]):
|
|
53
51
|
|
54
52
|
self._func = func
|
55
53
|
self._installable = installable
|
56
|
-
self.
|
54
|
+
self._instance_cache = instance_cache
|
57
55
|
|
58
|
-
self.
|
56
|
+
self._registry: col.AttrRegistry[ta.Callable, Method._Entry] = col.AttrRegistry(
|
57
|
+
requires_override=requires_override,
|
58
|
+
)
|
59
|
+
|
60
|
+
self._cache: col.AttrRegistryCache[ta.Callable, Method._Entry, ta.Callable] = col.AttrRegistryCache(
|
61
|
+
self._registry,
|
62
|
+
self._prepare,
|
63
|
+
)
|
59
64
|
|
60
65
|
# bpo-45678: special-casing for classmethod/staticmethod in Python <=3.9, as functools.update_wrapper doesn't
|
61
66
|
# work properly in singledispatchmethod.__get__ if it is applied to an unbound classmethod/staticmethod
|
@@ -68,19 +73,12 @@ class Method(ta.Generic[P, R]):
|
|
68
73
|
self._is_abstractmethod = getattr(func, '__isabstractmethod__', False) # noqa
|
69
74
|
self.update_wrapper(self)
|
70
75
|
|
71
|
-
self._dispatch_func_cache: dict[ta.Any, ta.Callable] = {}
|
72
|
-
|
73
|
-
def dispatch_func_cache_remove(k, self_ref=weakref.ref(self)):
|
74
|
-
if (ref_self := self_ref()) is not None:
|
75
|
-
cache = ref_self._dispatch_func_cache # noqa
|
76
|
-
with contextlib.suppress(KeyError):
|
77
|
-
del cache[k]
|
78
|
-
|
79
|
-
self._dispatch_func_cache_remove = dispatch_func_cache_remove
|
80
|
-
|
81
76
|
self._owner: type | None = None
|
82
77
|
self._name: str | None = None
|
83
78
|
|
79
|
+
class _Entry:
|
80
|
+
cls_set: frozenset[type]
|
81
|
+
|
84
82
|
def __set_name__(self, owner, name):
|
85
83
|
if self._owner is None:
|
86
84
|
self._owner = owner
|
@@ -102,83 +100,29 @@ class Method(ta.Generic[P, R]):
|
|
102
100
|
|
103
101
|
def register(self, impl: T, cls_set: frozenset[type] | None = None) -> T:
|
104
102
|
check.callable(impl)
|
105
|
-
if impl not in self._impls:
|
106
|
-
self._impls[impl] = cls_set # type: ignore
|
107
|
-
self._dispatch_func_cache.clear()
|
108
|
-
|
109
|
-
return impl
|
110
|
-
|
111
|
-
def _is_impl(self, obj: ta.Any) -> bool:
|
112
|
-
try:
|
113
|
-
hash(obj)
|
114
|
-
except TypeError:
|
115
|
-
return False
|
116
|
-
|
117
|
-
return obj in self._impls
|
118
103
|
|
119
|
-
|
120
|
-
if
|
121
|
-
|
104
|
+
entry = Method._Entry()
|
105
|
+
if cls_set is not None:
|
106
|
+
entry.cls_set = cls_set
|
122
107
|
|
123
|
-
|
124
|
-
try:
|
125
|
-
mro_pos = mro.index(owner_cls)
|
126
|
-
except ValueError:
|
127
|
-
raise TypeError(f'Owner class {owner_cls} not in mro of instance class {instance_cls}') from None
|
108
|
+
self._registry.register(ta.cast(ta.Callable, impl), entry)
|
128
109
|
|
129
|
-
|
130
|
-
for cur_cls in mro[:mro_pos + 1]:
|
131
|
-
for att, obj in cur_cls.__dict__.items():
|
132
|
-
if att not in mro_dct:
|
133
|
-
if not self._is_impl(obj):
|
134
|
-
continue
|
135
|
-
|
136
|
-
try:
|
137
|
-
lst = mro_dct[att]
|
138
|
-
except KeyError:
|
139
|
-
lst = mro_dct[att] = []
|
140
|
-
lst.append((cur_cls, obj))
|
141
|
-
|
142
|
-
#
|
110
|
+
return impl
|
143
111
|
|
112
|
+
def _build_dispatcher(self, collected: ta.Mapping[str, tuple[ta.Callable, _Entry]]) -> Dispatcher[str]:
|
144
113
|
disp: Dispatcher[str] = Dispatcher()
|
145
114
|
|
146
|
-
|
147
|
-
for att, lst in mro_dct.items():
|
148
|
-
if not lst:
|
149
|
-
raise RuntimeError
|
150
|
-
_, obj = lst[-1]
|
151
|
-
|
152
|
-
if len(lst) > 1:
|
153
|
-
if self._requires_override and not lang.is_override(obj):
|
154
|
-
raise lang.RequiresOverrideError(
|
155
|
-
att,
|
156
|
-
instance_cls,
|
157
|
-
lst[-1][0],
|
158
|
-
lst[0][0],
|
159
|
-
)
|
160
|
-
|
161
|
-
if not self._is_impl(obj):
|
162
|
-
continue
|
163
|
-
|
164
|
-
cls_set = self._impls[obj]
|
165
|
-
if cls_set is None:
|
166
|
-
cls_set = get_impl_func_cls_set(obj, arg_offset=1)
|
167
|
-
self._impls[obj] = cls_set
|
168
|
-
|
115
|
+
for a, (f, e) in collected.items():
|
169
116
|
try:
|
170
|
-
|
171
|
-
except
|
172
|
-
|
173
|
-
else:
|
174
|
-
raise TypeError(f'Duplicate impl: {owner_cls} {instance_cls} {att} {ex_att}')
|
175
|
-
seen[obj] = att
|
117
|
+
cls_set = e.cls_set
|
118
|
+
except AttributeError:
|
119
|
+
cls_set = e.cls_set = get_impl_func_cls_set(f, arg_offset=1)
|
176
120
|
|
177
|
-
disp.register(
|
121
|
+
disp.register(a, cls_set)
|
178
122
|
|
179
123
|
return disp
|
180
124
|
|
181
|
-
def
|
125
|
+
def _build_dispatch_func(self, disp: Dispatcher[str]) -> ta.Callable:
|
182
126
|
dispatch = disp.dispatch
|
183
127
|
type_ = type
|
184
128
|
getattr_ = getattr
|
@@ -190,25 +134,16 @@ class Method(ta.Generic[P, R]):
|
|
190
134
|
raise TypeError(f'{func_name} requires at least 1 positional argument')
|
191
135
|
|
192
136
|
if (impl_att := dispatch(type_(args[0]))) is not None:
|
193
|
-
|
194
|
-
return fn(*args, **kwargs)
|
137
|
+
return getattr_(self, impl_att)(*args, **kwargs)
|
195
138
|
|
196
139
|
return base_func.__get__(self)(*args, **kwargs) # noqa
|
197
140
|
|
198
141
|
self.update_wrapper(__call__)
|
199
142
|
return __call__
|
200
143
|
|
201
|
-
def
|
202
|
-
|
203
|
-
|
204
|
-
return self._dispatch_func_cache[cls_ref]
|
205
|
-
except KeyError:
|
206
|
-
pass
|
207
|
-
del cls_ref
|
208
|
-
|
209
|
-
att_disp = self.build_attr_dispatcher(instance_cls)
|
210
|
-
func = self.build_dispatch_func(att_disp)
|
211
|
-
self._dispatch_func_cache[weakref.ref(instance_cls, self._dispatch_func_cache_remove)] = func
|
144
|
+
def _prepare(self, instance_cls: type, collected: ta.Mapping[str, tuple[ta.Callable, _Entry]]) -> ta.Callable:
|
145
|
+
disp = self._build_dispatcher(collected)
|
146
|
+
func = self._build_dispatch_func(disp)
|
212
147
|
return func
|
213
148
|
|
214
149
|
def __get__(self, instance, owner=None):
|
@@ -216,16 +151,21 @@ class Method(ta.Generic[P, R]):
|
|
216
151
|
# FIXME: classmethod/staticmethod
|
217
152
|
return self
|
218
153
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
154
|
+
if self._instance_cache:
|
155
|
+
try:
|
156
|
+
return instance.__dict__[self._name]
|
157
|
+
except KeyError:
|
158
|
+
pass
|
159
|
+
|
160
|
+
bound = self._cache.get(type(instance)).__get__(instance, owner) # noqa
|
161
|
+
|
162
|
+
if self._instance_cache:
|
163
|
+
instance.__dict__[self._name] = bound
|
164
|
+
|
165
|
+
return bound
|
225
166
|
|
226
167
|
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
|
227
168
|
instance, *rest = args
|
228
|
-
instance_cls = type(instance)
|
229
169
|
|
230
170
|
# if instance_cls is super:
|
231
171
|
# owner = instance.__self_class__.__mro__[instance.__self_class__.__mro__.index(instance.__thisclass__) + 1]
|
@@ -233,55 +173,25 @@ class Method(ta.Generic[P, R]):
|
|
233
173
|
# func = self.build_dispatch_func(att_disp)
|
234
174
|
# return func.__get__(instance, instance.__thisclass__)(*rest, **kwargs)
|
235
175
|
|
236
|
-
|
237
|
-
func = self._dispatch_func_cache[weakref.ref(instance_cls)]
|
238
|
-
except KeyError:
|
239
|
-
func = self.get_dispatch_func(instance_cls)
|
240
|
-
return func.__get__(instance)(*rest, **kwargs) # noqa
|
176
|
+
return self.__get__(instance)(*rest, **kwargs)
|
241
177
|
|
242
178
|
|
243
179
|
##
|
244
180
|
|
245
181
|
|
246
|
-
@ta.overload
|
247
|
-
def method(
|
248
|
-
func: ta.Callable[P, R],
|
249
|
-
/,
|
250
|
-
*,
|
251
|
-
installable: bool = False,
|
252
|
-
requires_override: bool = False,
|
253
|
-
) -> Method[P, R]: # noqa
|
254
|
-
...
|
255
|
-
|
256
|
-
|
257
|
-
@ta.overload
|
258
182
|
def method(
|
259
|
-
func: None = None,
|
260
|
-
/,
|
261
183
|
*,
|
262
184
|
installable: bool = False,
|
263
185
|
requires_override: bool = False,
|
186
|
+
instance_cache: bool = False,
|
264
187
|
) -> ta.Callable[[ta.Callable[P, R]], Method[P, R]]: # noqa
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
def method(
|
269
|
-
func=None,
|
270
|
-
/,
|
271
|
-
*,
|
272
|
-
installable=False,
|
273
|
-
requires_override=False,
|
274
|
-
):
|
275
|
-
kw = dict(
|
188
|
+
return functools.partial(
|
189
|
+
Method, # type: ignore[arg-type]
|
276
190
|
installable=installable,
|
277
191
|
requires_override=requires_override,
|
192
|
+
instance_cache=instance_cache,
|
278
193
|
)
|
279
194
|
|
280
|
-
if func is None:
|
281
|
-
return functools.partial(Method, **kw)
|
282
|
-
|
283
|
-
return Method(func, **kw)
|
284
|
-
|
285
195
|
|
286
196
|
#
|
287
197
|
|
@@ -305,7 +215,7 @@ def install_method(
|
|
305
215
|
if on is None:
|
306
216
|
cls = owner
|
307
217
|
else:
|
308
|
-
cls = check.issubclass(on, owner)
|
218
|
+
cls = check.issubclass(on, owner) # noqa
|
309
219
|
|
310
220
|
check.arg(not hasattr(cls, a))
|
311
221
|
setattr(cls, a, fn)
|
omlish/dom/rendering.py
CHANGED
omlish/funcs/guard.py
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
import abc
|
2
|
+
import functools
|
3
|
+
import operator
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from .. import check
|
7
|
+
from .. import collections as col
|
8
|
+
from .. import lang
|
9
|
+
|
10
|
+
|
11
|
+
T = ta.TypeVar('T')
|
12
|
+
T_co = ta.TypeVar('T_co', covariant=True)
|
13
|
+
U = ta.TypeVar('U')
|
14
|
+
P = ta.ParamSpec('P')
|
15
|
+
|
16
|
+
|
17
|
+
##
|
18
|
+
|
19
|
+
|
20
|
+
class GuardFn(ta.Protocol[P, T_co]):
|
21
|
+
def __get__(self, instance, owner=None) -> ta.Self: ...
|
22
|
+
|
23
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> ta.Callable[[], T_co] | None: ...
|
24
|
+
|
25
|
+
|
26
|
+
##
|
27
|
+
|
28
|
+
|
29
|
+
@ta.final
|
30
|
+
class DumbGuardFn(ta.Generic[P, T]):
|
31
|
+
def __init__(self, fn: ta.Callable[P, T]) -> None:
|
32
|
+
self._fn = fn
|
33
|
+
|
34
|
+
def __get__(self, instance, owner=None):
|
35
|
+
return DumbGuardFn(self._fn.__get__(instance, owner)) # noqa
|
36
|
+
|
37
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> ta.Callable[[], T]:
|
38
|
+
return functools.partial(self._fn, *args, **kwargs)
|
39
|
+
|
40
|
+
|
41
|
+
dumb = DumbGuardFn
|
42
|
+
|
43
|
+
|
44
|
+
##
|
45
|
+
|
46
|
+
|
47
|
+
class AmbiguousGuardFnError(Exception):
|
48
|
+
pass
|
49
|
+
|
50
|
+
|
51
|
+
@ta.final
|
52
|
+
class MultiGuardFn(ta.Generic[P, T]):
|
53
|
+
def __init__(
|
54
|
+
self,
|
55
|
+
*children: GuardFn[P, T],
|
56
|
+
strict: bool = False,
|
57
|
+
) -> None:
|
58
|
+
self._children, self._strict = children, strict
|
59
|
+
|
60
|
+
def __get__(self, instance, owner=None):
|
61
|
+
return MultiGuardFn(*map(operator.methodcaller('__get__', instance, owner), self._children), strict=self._strict) # noqa
|
62
|
+
|
63
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> ta.Callable[[], T] | None:
|
64
|
+
matches = []
|
65
|
+
for c in self._children:
|
66
|
+
if (m := c(*args, **kwargs)) is not None:
|
67
|
+
if not self._strict:
|
68
|
+
return m
|
69
|
+
matches.append(m)
|
70
|
+
if not matches:
|
71
|
+
return None
|
72
|
+
elif len(matches) > 1:
|
73
|
+
raise AmbiguousGuardFnError
|
74
|
+
else:
|
75
|
+
return matches[0]
|
76
|
+
|
77
|
+
|
78
|
+
multi = MultiGuardFn
|
79
|
+
|
80
|
+
|
81
|
+
##
|
82
|
+
|
83
|
+
|
84
|
+
class _BaseGuardFnMethod(lang.Abstract, ta.Generic[P, T]):
|
85
|
+
def __init__(
|
86
|
+
self,
|
87
|
+
*,
|
88
|
+
strict: bool = False,
|
89
|
+
requires_override: bool = False,
|
90
|
+
instance_cache: bool = False,
|
91
|
+
prototype: ta.Callable[P, T] | None = None,
|
92
|
+
) -> None:
|
93
|
+
super().__init__()
|
94
|
+
|
95
|
+
self._strict = strict
|
96
|
+
self._instance_cache = instance_cache
|
97
|
+
self._prototype = prototype
|
98
|
+
|
99
|
+
self._registry: col.AttrRegistry[ta.Callable, None] = col.AttrRegistry(
|
100
|
+
requires_override=requires_override,
|
101
|
+
)
|
102
|
+
|
103
|
+
self._cache: col.AttrRegistryCache[ta.Callable, None, MultiGuardFn] = col.AttrRegistryCache(
|
104
|
+
self._registry,
|
105
|
+
self._prepare,
|
106
|
+
)
|
107
|
+
|
108
|
+
_owner: type | None = None
|
109
|
+
_name: str | None = None
|
110
|
+
|
111
|
+
def __set_name__(self, owner, name):
|
112
|
+
if self._owner is None:
|
113
|
+
self._owner = owner
|
114
|
+
if self._name is None:
|
115
|
+
self._name = name
|
116
|
+
|
117
|
+
def register(self, fn: U) -> U:
|
118
|
+
check.callable(fn)
|
119
|
+
self._registry.register(ta.cast(ta.Callable, fn), None)
|
120
|
+
return fn
|
121
|
+
|
122
|
+
def _prepare(self, instance_cls: type, collected: ta.Mapping[str, tuple[ta.Callable, None]]) -> MultiGuardFn:
|
123
|
+
return MultiGuardFn(
|
124
|
+
*[getattr(instance_cls, a) for a in collected],
|
125
|
+
strict=self._strict,
|
126
|
+
)
|
127
|
+
|
128
|
+
@abc.abstractmethod
|
129
|
+
def _bind(self, instance, owner):
|
130
|
+
raise NotImplementedError
|
131
|
+
|
132
|
+
def __get__(self, instance, owner=None):
|
133
|
+
if instance is None:
|
134
|
+
return self
|
135
|
+
|
136
|
+
if self._instance_cache:
|
137
|
+
try:
|
138
|
+
return instance.__dict__[self._name]
|
139
|
+
except KeyError:
|
140
|
+
pass
|
141
|
+
|
142
|
+
bound = self._bind(instance, owner)
|
143
|
+
|
144
|
+
if self._instance_cache:
|
145
|
+
instance.__dict__[self._name] = bound
|
146
|
+
|
147
|
+
return bound
|
148
|
+
|
149
|
+
def _call(self, *args, **kwargs):
|
150
|
+
instance, *rest = args
|
151
|
+
return self.__get__(instance)(*rest, **kwargs)
|
152
|
+
|
153
|
+
#
|
154
|
+
|
155
|
+
|
156
|
+
class GuardFnMethod(_BaseGuardFnMethod[P, T]):
|
157
|
+
def _bind(self, instance, owner):
|
158
|
+
return self._cache.get(type(instance)).__get__(instance, owner) # noqa
|
159
|
+
|
160
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> ta.Callable[[], T] | None:
|
161
|
+
return self._call(*args, **kwargs)
|
162
|
+
|
163
|
+
|
164
|
+
def method(
|
165
|
+
*,
|
166
|
+
strict: bool = False,
|
167
|
+
requires_override: bool = False,
|
168
|
+
instance_cache: bool = False,
|
169
|
+
) -> ta.Callable[[ta.Callable[P, T]], GuardFnMethod[P, T]]: # noqa
|
170
|
+
def inner(fn):
|
171
|
+
return GuardFnMethod(
|
172
|
+
strict=strict,
|
173
|
+
requires_override=requires_override,
|
174
|
+
instance_cache=instance_cache,
|
175
|
+
prototype=fn,
|
176
|
+
)
|
177
|
+
|
178
|
+
return inner
|
179
|
+
|
180
|
+
|
181
|
+
#
|
182
|
+
|
183
|
+
|
184
|
+
class DumbGuardFnMethod(_BaseGuardFnMethod[P, T]):
|
185
|
+
def _bind(self, instance, owner):
|
186
|
+
gf = self._cache.get(type(instance)).__get__(instance, owner) # noqa
|
187
|
+
x = self._prototype.__get__(instance, owner) # type: ignore
|
188
|
+
|
189
|
+
def inner(*args, **kwargs):
|
190
|
+
if (m := gf(*args, **kwargs)) is not None:
|
191
|
+
return m()
|
192
|
+
return x(*args, **kwargs)
|
193
|
+
|
194
|
+
return inner
|
195
|
+
|
196
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
|
197
|
+
return self._call(*args, **kwargs)
|
198
|
+
|
199
|
+
|
200
|
+
def dumb_method(
|
201
|
+
*,
|
202
|
+
strict: bool = False,
|
203
|
+
requires_override: bool = False,
|
204
|
+
instance_cache: bool = False,
|
205
|
+
) -> ta.Callable[[ta.Callable[P, T]], DumbGuardFnMethod[P, T]]: # noqa
|
206
|
+
def inner(fn):
|
207
|
+
return DumbGuardFnMethod(
|
208
|
+
strict=strict,
|
209
|
+
requires_override=requires_override,
|
210
|
+
instance_cache=instance_cache,
|
211
|
+
prototype=fn,
|
212
|
+
)
|
213
|
+
|
214
|
+
return inner
|
omlish/graphs/dot/rendering.py
CHANGED
omlish/lite/maybes.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ruff: noqa: UP007 UP045
|
2
2
|
import abc
|
3
3
|
import functools
|
4
|
+
import operator
|
4
5
|
import typing as ta
|
5
6
|
|
6
7
|
from .abstract import Abstract
|
@@ -208,3 +209,10 @@ class _EmptyMaybe(_Maybe[T]):
|
|
208
209
|
|
209
210
|
|
210
211
|
Maybe._empty = _EmptyMaybe() # noqa
|
212
|
+
|
213
|
+
|
214
|
+
##
|
215
|
+
|
216
|
+
|
217
|
+
setattr(Maybe, 'just', _JustMaybe) # noqa
|
218
|
+
setattr(Maybe, 'empty', functools.partial(operator.attrgetter('_empty'), Maybe))
|
omlish/sql/queries/rendering.py
CHANGED
omlish/text/parts.py
CHANGED
@@ -75,7 +75,7 @@ class PartTransform:
|
|
75
75
|
def __call__(self, part: Part | None) -> Part:
|
76
76
|
return self._transform(part)
|
77
77
|
|
78
|
-
@dispatch.method
|
78
|
+
@dispatch.method(instance_cache=True)
|
79
79
|
def _transform(self, part: Part | None) -> Part:
|
80
80
|
raise TypeError(part)
|
81
81
|
|
@@ -214,7 +214,7 @@ class PartRenderer:
|
|
214
214
|
def __call__(self, part: Part | None) -> None:
|
215
215
|
return self._render(part)
|
216
216
|
|
217
|
-
@dispatch.method
|
217
|
+
@dispatch.method()
|
218
218
|
def _render(self, part: Part | None) -> None:
|
219
219
|
raise TypeError(part)
|
220
220
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.omlish-manifests.json,sha256=FLw7xkPiSXuImZgqSP8BwrEib2R1doSzUPLUkc-QUIA,8410
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=UyBs9jXm7W7VwfekZgY2BWyGcs6fJ0_zJqOMdeCn8aY,3613
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ZNIMl1kwg3qdei4DiUrJPQe5M81S1e76N-GuNSwLBAE,8683
|
5
5
|
omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
|
@@ -64,14 +64,15 @@ omlish/codecs/funcs.py,sha256=or0Jogczuzk7csDTRl-HURMEjl8LXXqxxXYK45xcM5w,855
|
|
64
64
|
omlish/codecs/registry.py,sha256=y7gjhBY1tTTHZmaK4X02zL5HD_25AAiZ8k27Op69Ag0,4006
|
65
65
|
omlish/codecs/standard.py,sha256=eiZ4u9ep0XrA4Z_D1zJI0vmWyuN8HLrX4Se_r_Cq_ZM,60
|
66
66
|
omlish/codecs/text.py,sha256=P9-xpdiQE3nbI5CzEentf07FBHPzD7_SwOtUQUJ01So,5710
|
67
|
-
omlish/collections/__init__.py,sha256=
|
67
|
+
omlish/collections/__init__.py,sha256=cSNZ670-GaNW_sCazmLi41HPx5tfzMvkHCvPoyebTEY,2934
|
68
68
|
omlish/collections/abc.py,sha256=p9zhL5oNV5WPyWmMn34fWfkuxPQAjOtL7WQA-Xsyhwk,2628
|
69
|
+
omlish/collections/attrregistry.py,sha256=SPvIt8rT8nWvEBqf35I8wPgBU55m0u2ssSmNcYHm_FM,5563
|
69
70
|
omlish/collections/bimap.py,sha256=3szDCscPJlFRtkpyVQNWneg4s50mr6Rd0jdTzVEIcnE,1661
|
70
71
|
omlish/collections/coerce.py,sha256=tAls15v_7p5bUN33R7Zbko87KW5toWHl9fRialCqyNY,7030
|
71
72
|
omlish/collections/frozen.py,sha256=drarjcMFpwKhBM01b1Gh6XDcaRaUgpyuxEiqppaKRkU,4220
|
72
73
|
omlish/collections/hasheq.py,sha256=uHypfZlHhicQPvx9OOlpT9MSLwfc_mFil-WaxF9dTOo,3732
|
73
74
|
omlish/collections/identity.py,sha256=00UAYIjCRhyj73Es0jVNvOloXjRxHcjRxGQeWo75OEo,4834
|
74
|
-
omlish/collections/mappings.py,sha256=
|
75
|
+
omlish/collections/mappings.py,sha256=c3ojUN9Ca3oGfmMXSFkDQYou5J15obDfgjCvzq3Url4,3833
|
75
76
|
omlish/collections/multimaps.py,sha256=azuif-PeLGvLpCE9_XX5zYx7XtVbsulWq0owvEKNy_g,3897
|
76
77
|
omlish/collections/ordered.py,sha256=jBSj5CamdKJAezXM8GlRd7jjaRDk6BHIeOhlxcC9lJI,2468
|
77
78
|
omlish/collections/ranked.py,sha256=McB8C2UQfUvrbmxGTpBz1-EZuyCLkBFtktzncMdt8_Y,2287
|
@@ -217,7 +218,7 @@ omlish/dispatch/__init__.py,sha256=UwVT6SSk5HKk9xF9vc_UJD8BDSIQWSw98Ldx-G-6PC0,1
|
|
217
218
|
omlish/dispatch/dispatch.py,sha256=TzWihCt9Zr8wfIwVpKHVOOrYFVKpDXRevxYomtEfqYc,3176
|
218
219
|
omlish/dispatch/functions.py,sha256=cwNzGIg2ZIalEgn9I03cnJVbMTHjWloyDTaowlO3UPs,1524
|
219
220
|
omlish/dispatch/impls.py,sha256=3kyLw5yiYXWCN1DiqQbD1czMVrM8v1mpQ8NyD0tUrnk,1870
|
220
|
-
omlish/dispatch/methods.py,sha256=
|
221
|
+
omlish/dispatch/methods.py,sha256=aberuaB1ujTwhTdTyZQ2j4azNVkO54nEc28k5ZQ--J4,7337
|
221
222
|
omlish/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
222
223
|
omlish/docker/all.py,sha256=t5jBNZAzqCoB05-nwCuSZ6C3PBEBD6T3wsIJvIXJaRg,576
|
223
224
|
omlish/docker/cli.py,sha256=ws3ypayxdnp3nWeLww45jHG0Vwr5e4bUbLTqkpejAhc,2570
|
@@ -232,7 +233,7 @@ omlish/docker/timebomb.py,sha256=EnFt8pJeXkowF_F5NXnN0ogDmxUmVymV4h1CYPwyJr4,356
|
|
232
233
|
omlish/dom/__init__.py,sha256=RYkv9inuebWIKsRuPXr3j0njgLFKzIo-ujKc4JEp0wc,301
|
233
234
|
omlish/dom/building.py,sha256=VPMbGxv730dYjS_jlrrp0qiZhuGT8OheFamUAgtQdF4,1022
|
234
235
|
omlish/dom/content.py,sha256=1NkE1eb0ITfps-yJ-Lbtm6kGnvUmQy6HWo01gnvSkiU,2775
|
235
|
-
omlish/dom/rendering.py,sha256=
|
236
|
+
omlish/dom/rendering.py,sha256=zypSFpZO0pBfPY_ZJXeywovu0pbEtQzLYzn6TZfpRlk,4357
|
236
237
|
omlish/formats/__init__.py,sha256=T0AG1gFnqQ5JiHN0UPQjQ-7g5tnxMIG-mgOvMYExYAM,21
|
237
238
|
omlish/formats/cbor.py,sha256=o_Hbe4kthO9CeXK-FySrw0dHVlrdyTo2Y8PpGRDfZ3c,514
|
238
239
|
omlish/formats/cloudpickle.py,sha256=16si4yUp_pAdDWGECAWf6HLA2PwSANGGgDoMLGZUem8,579
|
@@ -287,6 +288,7 @@ omlish/formats/toml/writer.py,sha256=9NT8sRy3I9KubxFx56Qbislvrdtbd23rEuBT-GSdUYA
|
|
287
288
|
omlish/funcs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
288
289
|
omlish/funcs/builders.py,sha256=ZSBQS2xqriXp5x0t074EEZvuTmMp4Yue2YGBoTLAioo,4044
|
289
290
|
omlish/funcs/genmachine.py,sha256=BOxO1OTjxZ7ewv_WpqYkY8bwlGQIJIjwjvYMflEFa_M,2571
|
291
|
+
omlish/funcs/guard.py,sha256=vrsUtaGJj-eCOkfjxlHV9lw5qDLimiHOW4X0LINDKmk,5495
|
290
292
|
omlish/funcs/match.py,sha256=cBtG7kdpWdxvHwlte5CWlBxXSoJSV48joV4bwJJC3pk,6352
|
291
293
|
omlish/funcs/pairs.py,sha256=XhYTJdqooAJKeoGZmEaiKYeFRq5-Dj2_y92IdBl_C20,4371
|
292
294
|
omlish/funcs/pipes.py,sha256=E1dQZMBmgT2qautG1vEqy5v3QBsO2Nzryv33j4YAngA,2520
|
@@ -297,7 +299,7 @@ omlish/graphs/trees.py,sha256=r_kZw-83c1KXe7fida-CVWNGDX9quPTmhAjJ5I5uKRc,8198
|
|
297
299
|
omlish/graphs/dot/__init__.py,sha256=Y1MZRQBZkcYyG1Tn7K2FhL8aYbm4v4tk6f5g9AqEkUw,359
|
298
300
|
omlish/graphs/dot/items.py,sha256=GIzUqLHJPR4AVtF141uA8JnyybkRZx6mFYsNJHu_JVg,4087
|
299
301
|
omlish/graphs/dot/make.py,sha256=e-M1IEdh4kHEjJmBxpaEUPxvFLrm5uIXdGxjQZr2HRo,365
|
300
|
-
omlish/graphs/dot/rendering.py,sha256=
|
302
|
+
omlish/graphs/dot/rendering.py,sha256=SGSpwswdFqsjEnznQDyryIsXE8bzPXSUFAJHlB2uT2Y,3655
|
301
303
|
omlish/graphs/dot/utils.py,sha256=8cGKIdcM-w1q4ITUYyC0lnYwLqNWuH2OddmmbLxVgEo,806
|
302
304
|
omlish/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
303
305
|
omlish/http/all.py,sha256=ChV0KcPN8CKcwlQiWqYyMvmjHuH9qhBsd2kV7-HrFto,1409
|
@@ -478,7 +480,7 @@ omlish/lite/imports.py,sha256=GyEDKL-WuHtdOKIL-cc8aFd0-bHwZFDEjAB52ItabX0,1341
|
|
478
480
|
omlish/lite/inject.py,sha256=BQgjBj2mzJgMimLam-loSpQzcb31-8NYPVRQgHVv3cQ,29159
|
479
481
|
omlish/lite/json.py,sha256=m0Ce9eqUZG23-H7-oOp8n1sf4fzno5vtK4AK_4Vc-Mg,706
|
480
482
|
omlish/lite/marshal.py,sha256=oVqVwqTArFUj9lYhmKg_MVgnqlCAUvOnYgtU3bBu_bk,23020
|
481
|
-
omlish/lite/maybes.py,sha256=
|
483
|
+
omlish/lite/maybes.py,sha256=NCnMZaSbIfvOMqz69aYmmvZQDd0c61QjG3ju7uJc8t8,4531
|
482
484
|
omlish/lite/maysync.py,sha256=Otd-xqWaMzY9xBF5SiLKxu4kG_GaWGk8qTGFDAHXDm4,14803
|
483
485
|
omlish/lite/objects.py,sha256=HzN_4J6w6WDLKDrW8jSNUKgfAR5vUsB42rtSCu04oqQ,1921
|
484
486
|
omlish/lite/pycharm.py,sha256=fdSTwtdqGRL0P9IkCrDAPqQkJsegq1NfYyVG2N6cy4w,1174
|
@@ -730,7 +732,7 @@ omlish/sql/queries/names.py,sha256=25kPRYse_ivI17lMD9st04k7QQMOGf5plb4b8yZFpUI,2
|
|
730
732
|
omlish/sql/queries/ops.py,sha256=pDZ_2Jo_Fa8DDbtYkc6-9eehkWsZPI-jh-KFlubcY6Y,134
|
731
733
|
omlish/sql/queries/params.py,sha256=ocjaJbhv_5LWgxdjoZg8vyAWDZxsij4cKH8Lx4hXMT0,1261
|
732
734
|
omlish/sql/queries/relations.py,sha256=P0qBqNICyeig9sEZAYLZcTXcI1YFiBe6REm6jNhpHUI,2630
|
733
|
-
omlish/sql/queries/rendering.py,sha256=
|
735
|
+
omlish/sql/queries/rendering.py,sha256=Kc7GqLKnuzfeVv4MPTkjYb6-n4fTBLOKo4QjfPc-WBY,7800
|
734
736
|
omlish/sql/queries/selects.py,sha256=XNisb2draHURYhbZsTFw7DJQaN1Zfo2Znm-Ty0lHNTo,1773
|
735
737
|
omlish/sql/queries/std.py,sha256=FdJkXD7oiuj8mtVzvbsL1ZocEEAfaSdOsfTVB1YhtrE,699
|
736
738
|
omlish/sql/queries/stmts.py,sha256=pBqwD7dRlqMu6uh6vR3xaWOEgbZCcFWbOQ9ryYd17T4,441
|
@@ -808,7 +810,7 @@ omlish/text/indent.py,sha256=BWVVaHs_B1ppwHJJIxKCDG3iCutkYy5e1qr59Z_Suzg,1524
|
|
808
810
|
omlish/text/linecache.py,sha256=hRYlEhD63ZfA6_ZOTkQIcnON-3W56QMAhcG3vEJqj9M,1858
|
809
811
|
omlish/text/mangle.py,sha256=k7mYavVgxJ2ENV2wfjw3c9u3hqH5NeVpjoxYbyaYC0Y,2796
|
810
812
|
omlish/text/minja.py,sha256=7UKNalkWpTG_364OIo7p5ym--uiNPR2RFBW_W8rrO4I,9194
|
811
|
-
omlish/text/parts.py,sha256=
|
813
|
+
omlish/text/parts.py,sha256=MFi-ANxXlBiOMqW2y2S0BRg6xDwPYxSXSfrYPM3rtcE,6669
|
812
814
|
omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
|
813
815
|
omlish/text/templating.py,sha256=i-HU7W-GtKdnBhEG3mnSey5ig7vV0q02D3pVzMoOzJY,3318
|
814
816
|
omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -823,9 +825,9 @@ omlish/typedvalues/marshal.py,sha256=TWwqiGROaQwcxglGiBt_t5D9AvlWsy3ELm7do-nPeao
|
|
823
825
|
omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
|
824
826
|
omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
|
825
827
|
omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
|
826
|
-
omlish-0.0.0.
|
827
|
-
omlish-0.0.0.
|
828
|
-
omlish-0.0.0.
|
829
|
-
omlish-0.0.0.
|
830
|
-
omlish-0.0.0.
|
831
|
-
omlish-0.0.0.
|
828
|
+
omlish-0.0.0.dev453.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
829
|
+
omlish-0.0.0.dev453.dist-info/METADATA,sha256=2xNQ3KjE39xJl-eAkz-XOpj2tek1YFZnNCNmy_ZaYBk,19003
|
830
|
+
omlish-0.0.0.dev453.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
831
|
+
omlish-0.0.0.dev453.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
832
|
+
omlish-0.0.0.dev453.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
833
|
+
omlish-0.0.0.dev453.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|