omlish 0.0.0.dev318__py3-none-any.whl → 0.0.0.dev320__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 CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev318'
2
- __revision__ = 'b80bceb394abe03974e4312775224ac1dbcb5b22'
1
+ __version__ = '0.0.0.dev320'
2
+ __revision__ = '22973e588f6a8205d0cf900b83dcaaa9237fa441'
3
3
 
4
4
 
5
5
  #
@@ -4,6 +4,12 @@ import typing as _ta
4
4
  from .. import lang as _lang
5
5
 
6
6
 
7
+ from .bimap import ( # noqa
8
+ BiMap,
9
+
10
+ make_bi_map,
11
+ )
12
+
7
13
  from .coerce import ( # noqa
8
14
  abs_set,
9
15
  abs_set_of,
@@ -0,0 +1,89 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from .. import check
5
+ from .. import lang
6
+
7
+
8
+ K = ta.TypeVar('K')
9
+ V = ta.TypeVar('V')
10
+
11
+ K2 = ta.TypeVar('K2')
12
+ V2 = ta.TypeVar('V2')
13
+
14
+
15
+ ##
16
+
17
+
18
+ class BiMap(ta.Mapping[K, V], lang.Abstract):
19
+ @abc.abstractmethod
20
+ def inverse(self) -> 'BiMap[V, K]':
21
+ raise NotImplementedError
22
+
23
+
24
+ ##
25
+
26
+
27
+ class _BaseBiMapImpl(BiMap[K, V], lang.Abstract):
28
+ def __init__(
29
+ self,
30
+ dct: ta.Mapping[K, V],
31
+ inverse: BiMap[V, K],
32
+ ) -> None:
33
+ super().__init__()
34
+
35
+ self._dct = dct
36
+ self._inverse = inverse
37
+
38
+ def inverse(self) -> 'BiMap[V, K]':
39
+ return self._inverse
40
+
41
+ def __getitem__(self, key, /):
42
+ return self._dct[key]
43
+
44
+ def __len__(self) -> int:
45
+ return len(self._dct)
46
+
47
+ def __iter__(self):
48
+ return iter(self._dct)
49
+
50
+
51
+ class _BiMapImpl(_BaseBiMapImpl[K, V]):
52
+ def __init__(self, *args, **kwargs) -> None:
53
+ dct: dict[K, V] = {}
54
+ inv_dct: dict[V, K] = {}
55
+ for k, v in lang.yield_dict_init(*args, **kwargs):
56
+ check.not_in(k, dct)
57
+ check.not_in(v, dct)
58
+ dct[k] = v
59
+ inv_dct[v] = k
60
+
61
+ self._dct = dct
62
+ self._inv_dct = inv_dct
63
+
64
+ super().__init__(dct, _BiMapImpl._Inverse(inv_dct, self))
65
+
66
+ class _Inverse(_BaseBiMapImpl):
67
+ pass
68
+
69
+
70
+ ##
71
+
72
+
73
+ @ta.overload
74
+ def make_bi_map(dct: ta.Mapping[K, V]) -> BiMap[K, V]:
75
+ ...
76
+
77
+
78
+ @ta.overload
79
+ def make_bi_map(items: ta.Iterable[tuple[K, V]]) -> BiMap[K, V]:
80
+ ...
81
+
82
+
83
+ @ta.overload
84
+ def make_bi_map(**kwargs: str) -> BiMap[str, str]:
85
+ ...
86
+
87
+
88
+ def make_bi_map(*args, **kwargs):
89
+ return _BiMapImpl(*args, **kwargs)
@@ -29,6 +29,7 @@ class Method(ta.Generic[P, R]):
29
29
  func: ta.Callable,
30
30
  *,
31
31
  installable: bool = False,
32
+ requires_override: bool = False,
32
33
  ) -> None:
33
34
  super().__init__()
34
35
 
@@ -37,6 +38,7 @@ class Method(ta.Generic[P, R]):
37
38
 
38
39
  self._func = func
39
40
  self._installable = installable
41
+ self._requires_override = requires_override
40
42
 
41
43
  self._impls: ta.MutableMapping[ta.Callable, frozenset[type] | None] = weakref.WeakKeyDictionary()
42
44
 
@@ -97,33 +99,73 @@ class Method(ta.Generic[P, R]):
97
99
 
98
100
  return impl
99
101
 
102
+ def _is_impl(self, obj: ta.Any) -> bool:
103
+ try:
104
+ hash(obj)
105
+ except TypeError:
106
+ return False
107
+
108
+ return obj in self._impls
109
+
100
110
  def build_attr_dispatcher(self, instance_cls: type, owner_cls: type | None = None) -> Dispatcher[str]:
101
- disp: Dispatcher[str] = Dispatcher()
111
+ if owner_cls is None:
112
+ owner_cls = instance_cls
102
113
 
103
- mro_dct = lang.mro_dict(instance_cls, owner_cls)
104
- seen: ta.Mapping[ta.Any, str] = {}
105
- for nam, att in mro_dct.items():
106
- try:
107
- hash(att)
108
- except TypeError:
109
- continue
114
+ mro = instance_cls.__mro__[-2::-1]
115
+ try:
116
+ mro_pos = mro.index(owner_cls)
117
+ except ValueError:
118
+ raise TypeError(f'Owner class {owner_cls} not in mro of instance class {instance_cls}') from None
119
+
120
+ mro_dct: dict[str, list[tuple[type, ta.Any]]] = {}
121
+ for cur_cls in mro[:mro_pos + 1]:
122
+ for att, obj in cur_cls.__dict__.items():
123
+ if att not in mro_dct:
124
+ if not self._is_impl(obj):
125
+ continue
126
+
127
+ try:
128
+ lst = mro_dct[att]
129
+ except KeyError:
130
+ lst = mro_dct[att] = []
131
+ lst.append((cur_cls, obj))
132
+
133
+ #
110
134
 
111
- if att not in self._impls:
135
+ disp: Dispatcher[str] = Dispatcher()
136
+
137
+ seen: dict[ta.Any, str] = {}
138
+ for att, lst in mro_dct.items():
139
+ if not lst:
140
+ raise RuntimeError
141
+ _, obj = lst[-1]
142
+
143
+ if len(lst) > 1:
144
+ if self._requires_override and not lang.is_override(obj):
145
+ raise lang.RequiresOverrideError(
146
+ att,
147
+ instance_cls,
148
+ lst[-1][0],
149
+ lst[0][0],
150
+ )
151
+
152
+ if not self._is_impl(obj):
112
153
  continue
113
- cls_set = self._impls[att]
114
154
 
155
+ cls_set = self._impls[obj]
115
156
  if cls_set is None:
116
- cls_set = get_impl_func_cls_set(att, arg_offset=1)
117
- self._impls[att] = cls_set
157
+ cls_set = get_impl_func_cls_set(obj, arg_offset=1)
158
+ self._impls[obj] = cls_set
118
159
 
119
160
  try:
120
- ex_nam = seen[att]
161
+ ex_att = seen[obj]
121
162
  except KeyError:
122
163
  pass
123
164
  else:
124
- raise TypeError(f'Duplicate impl: {owner_cls} {instance_cls} {nam} {ex_nam}')
165
+ raise TypeError(f'Duplicate impl: {owner_cls} {instance_cls} {att} {ex_att}')
166
+ seen[obj] = att
125
167
 
126
- disp.register(nam, cls_set)
168
+ disp.register(att, cls_set)
127
169
 
128
170
  return disp
129
171
 
@@ -175,6 +217,13 @@ class Method(ta.Generic[P, R]):
175
217
  def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
176
218
  instance, *rest = args
177
219
  instance_cls = type(instance)
220
+
221
+ # if instance_cls is super:
222
+ # owner = instance.__self_class__.__mro__[instance.__self_class__.__mro__.index(instance.__thisclass__) + 1]
223
+ # att_disp = self.build_attr_dispatcher(instance.__self_class__, owner)
224
+ # func = self.build_dispatch_func(att_disp)
225
+ # return func.__get__(instance, instance.__thisclass__)(*rest, **kwargs)
226
+
178
227
  try:
179
228
  func = self._dispatch_func_cache[weakref.ref(instance_cls)]
180
229
  except KeyError:
@@ -186,19 +235,42 @@ class Method(ta.Generic[P, R]):
186
235
 
187
236
 
188
237
  @ta.overload
189
- def method(func: ta.Callable[P, R], /, *, installable: bool = False) -> Method[P, R]: # noqa
238
+ def method(
239
+ func: ta.Callable[P, R],
240
+ /,
241
+ *,
242
+ installable: bool = False,
243
+ requires_override: bool = False,
244
+ ) -> Method[P, R]: # noqa
190
245
  ...
191
246
 
192
247
 
193
248
  @ta.overload
194
- def method(func: None = None, /, *, installable: bool = False) -> ta.Callable[[ta.Callable[P, R]], Method[P, R]]: # noqa
249
+ def method(
250
+ func: None = None,
251
+ /,
252
+ *,
253
+ installable: bool = False,
254
+ requires_override: bool = False,
255
+ ) -> ta.Callable[[ta.Callable[P, R]], Method[P, R]]: # noqa
195
256
  ...
196
257
 
197
258
 
198
- def method(func=None, /, *, installable=False): # noqa
199
- kw = dict(installable=installable)
259
+ def method(
260
+ func=None,
261
+ /,
262
+ *,
263
+ installable=False,
264
+ requires_override=False,
265
+ ):
266
+ kw = dict(
267
+ installable=installable,
268
+ requires_override=requires_override,
269
+ )
270
+
200
271
  if func is None:
201
272
  return functools.partial(Method, **kw)
273
+
202
274
  return Method(func, **kw)
203
275
 
204
276
 
omlish/lang/__init__.py CHANGED
@@ -61,6 +61,12 @@ from .classes.abstract import ( # noqa
61
61
  unabstract_class,
62
62
  )
63
63
 
64
+ from .classes.namespaces import ( # noqa
65
+ GenericNamespaceMeta,
66
+ Namespace,
67
+ NamespaceMeta,
68
+ )
69
+
64
70
  from .classes.restrict import ( # noqa
65
71
  AnySensitive,
66
72
  Final,
@@ -79,7 +85,6 @@ from .classes.restrict import ( # noqa
79
85
  from .classes.simple import ( # noqa
80
86
  LazySingleton,
81
87
  Marker,
82
- Namespace,
83
88
  SimpleMetaDict,
84
89
  Singleton,
85
90
  )
@@ -252,6 +257,15 @@ from .outcomes import ( # noqa
252
257
  value,
253
258
  )
254
259
 
260
+ from .overrides import ( # noqa
261
+ needs_override,
262
+
263
+ is_override,
264
+
265
+ RequiresOverrideError,
266
+ RequiresOverride,
267
+ )
268
+
255
269
  from .params import ( # noqa
256
270
  ArgsParam,
257
271
  KwOnlyParam,
@@ -52,7 +52,11 @@ class Abstract(abc.ABC): # noqa
52
52
 
53
53
  super().__init_subclass__(**kwargs)
54
54
 
55
- if not _DISABLE_CHECKS and Abstract not in cls.__bases__:
55
+ if (
56
+ not _DISABLE_CHECKS and
57
+ Abstract not in cls.__bases__ and
58
+ abc.ABC not in cls.__bases__
59
+ ):
56
60
  ams = {a for a, o in cls.__dict__.items() if is_abstract_method(o)}
57
61
  seen = set(cls.__dict__)
58
62
  for b in cls.__bases__:
@@ -0,0 +1,126 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from .restrict import NotInstantiable
5
+
6
+
7
+ V = ta.TypeVar('V')
8
+
9
+
10
+ ##
11
+
12
+
13
+ class _NOT_SET: # noqa
14
+ def __new__(cls, *args, **kwargs): # noqa
15
+ raise TypeError
16
+
17
+
18
+ NamespaceCheckValue: ta.TypeAlias = type | tuple[type, ...] | ta.Callable[[ta.Any], bool]
19
+
20
+
21
+ class GenericNamespaceMeta(abc.ABCMeta, ta.Generic[V]):
22
+ __namespace_check_values__: NamespaceCheckValue | None = None
23
+ __namespace_case_insensitive__: bool = False
24
+
25
+ def __init_subclass__(
26
+ mcls,
27
+ *,
28
+ check_values: NamespaceCheckValue | None | type[_NOT_SET] = _NOT_SET,
29
+ case_insensitive: bool | type[_NOT_SET] = _NOT_SET,
30
+ **kwargs,
31
+ ):
32
+ super().__init_subclass__(**kwargs)
33
+
34
+ if check_values is not _NOT_SET:
35
+ mcls.__namespace_check_values__ = check_values
36
+ if case_insensitive is not _NOT_SET:
37
+ mcls.__namespace_case_insensitive__ = case_insensitive # type: ignore
38
+
39
+ __namespace_attrs__: ta.Mapping[str, V]
40
+ __namespace_values__: ta.Mapping[str, V]
41
+
42
+ def __new__(
43
+ mcls,
44
+ name,
45
+ bases,
46
+ namespace,
47
+ *,
48
+ check_values: NamespaceCheckValue | None | type[_NOT_SET] = _NOT_SET,
49
+ case_insensitive: bool | type[_NOT_SET] = _NOT_SET,
50
+ **kwargs,
51
+ ):
52
+ if bases:
53
+ for nc in (NotInstantiable,):
54
+ if nc not in bases:
55
+ bases += (nc,)
56
+
57
+ if check_values is _NOT_SET:
58
+ check_values = mcls.__namespace_check_values__
59
+ if case_insensitive is _NOT_SET:
60
+ case_insensitive = mcls.__namespace_case_insensitive__
61
+
62
+ cls = super().__new__(
63
+ mcls,
64
+ name,
65
+ bases,
66
+ namespace,
67
+ **kwargs,
68
+ )
69
+
70
+ cls.__namespace_check_values__ = check_values
71
+ cls.__namespace_case_insensitive__ = case_insensitive # type: ignore
72
+
73
+ if isinstance(check_values, (type, tuple)):
74
+ cvt = check_values
75
+
76
+ def _cv(o):
77
+ if not isinstance(o, cvt):
78
+ raise TypeError(o, cvt)
79
+ return True
80
+
81
+ check_values = _cv
82
+
83
+ a_dct: dict[str, V] = {}
84
+ v_dct: dict[str, V] = {}
85
+ for b_cls in cls.__mro__[-2::-1]:
86
+ # FIXME: must list() to avoid `RuntimeError: dictionary changed size during iteration`
87
+ for att in list(b_cls.__dict__):
88
+ if att.startswith('_') or att in a_dct:
89
+ continue
90
+
91
+ name = att
92
+ if case_insensitive:
93
+ name = att.lower()
94
+ if name in v_dct:
95
+ raise NameError(f'Ambiguous case-insensitive namespace attr: {name!r}, {att!r}')
96
+
97
+ obj = getattr(cls, att)
98
+ if check_values is not None and not check_values(obj):
99
+ raise ValueError(obj)
100
+
101
+ a_dct[att] = obj
102
+ v_dct[name] = obj
103
+
104
+ cls.__namespace_attrs__ = a_dct
105
+ cls.__namespace_values__ = v_dct
106
+
107
+ return cls
108
+
109
+ def __iter__(cls) -> ta.Iterator[tuple[str, V]]:
110
+ return iter(cls.__namespace_attrs__.items())
111
+
112
+ def __contains__(self, n: str) -> bool:
113
+ return n in self.__namespace_values__
114
+
115
+ def __getitem__(cls, n: str) -> V:
116
+ if cls.__namespace_case_insensitive__:
117
+ n = n.lower()
118
+ return cls.__namespace_values__[n]
119
+
120
+
121
+ class NamespaceMeta(GenericNamespaceMeta[ta.Any]):
122
+ pass
123
+
124
+
125
+ class Namespace(metaclass=NamespaceMeta):
126
+ pass
@@ -25,35 +25,6 @@ class SimpleMetaDict(dict):
25
25
  ##
26
26
 
27
27
 
28
- class _NamespaceMeta(abc.ABCMeta):
29
- def __new__(mcls, name, bases, namespace):
30
- if bases:
31
- for nc in (NotInstantiable,):
32
- if nc not in bases:
33
- bases += (nc,)
34
- return super().__new__(mcls, name, bases, namespace)
35
-
36
- def __iter__(cls) -> ta.Iterator[tuple[str, ta.Any]]:
37
- seen: set[str] = set()
38
- for bcls in reversed(cls.__mro__):
39
- for a in bcls.__dict__:
40
- if a in seen:
41
- continue
42
- seen.add(a)
43
- if not a.startswith('_'):
44
- yield (a, getattr(cls, a))
45
-
46
- def __getitem__(cls, n: str) -> ta.Any:
47
- return getattr(cls, n)
48
-
49
-
50
- class Namespace(metaclass=_NamespaceMeta):
51
- pass
52
-
53
-
54
- ##
55
-
56
-
57
28
  _MARKER_NAMESPACE_KEYS: set[str] | None = None
58
29
 
59
30
 
@@ -0,0 +1,82 @@
1
+ import types
2
+ import typing as ta
3
+
4
+ from .descriptors import unwrap_func
5
+
6
+
7
+ ##
8
+
9
+
10
+ class _EmptyClass:
11
+ pass
12
+
13
+
14
+ _OVERRIDE_NOT_NEEDED_ATTRS: ta.AbstractSet[str] = {
15
+ *_EmptyClass.__dict__,
16
+ }
17
+
18
+
19
+ def needs_override(attr: str, obj: ta.Any) -> bool:
20
+ if attr in _OVERRIDE_NOT_NEEDED_ATTRS:
21
+ return False
22
+
23
+ return True
24
+
25
+
26
+ ##
27
+
28
+
29
+ def is_override(obj: ta.Any) -> bool:
30
+ if isinstance(obj, types.FunctionType):
31
+ fn = unwrap_func(obj)
32
+ if getattr(fn, '__override__', False):
33
+ return True
34
+
35
+ return False
36
+
37
+
38
+ ##
39
+
40
+
41
+ class RequiresOverrideError(TypeError):
42
+ def __init__(
43
+ self,
44
+ att: str | None = None,
45
+ cls: type | None = None,
46
+ mro_cls: type | None = None,
47
+ owner_cls: type | None = None,
48
+ ) -> None:
49
+ super().__init__(' '.join([
50
+ 'Attribute',
51
+ *([f'{att!r}'] if att is not None else []),
52
+ *([f'on class {cls.__qualname__}'] if cls is not None else []),
53
+ *([f'from mro class {mro_cls.__qualname__}'] if mro_cls is not None and mro_cls is not cls else []),
54
+ f'is not marked as a @typing.override',
55
+ *([f'from owning class {owner_cls.__qualname__}'] if owner_cls is not None else []),
56
+ ]))
57
+
58
+ self.att = att
59
+ self.cls = cls
60
+ self.mro_cls = mro_cls
61
+ self.owner_cls = owner_cls
62
+
63
+
64
+ class RequiresOverride:
65
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
66
+ super().__init_subclass__(**kwargs)
67
+
68
+ req_ovr_dct: dict[str, type] = {}
69
+ for m_cls in reversed(cls.__mro__):
70
+ for a, o in m_cls.__dict__.items():
71
+ if a in req_ovr_dct and not is_override(o):
72
+ raise RequiresOverrideError(
73
+ a,
74
+ cls,
75
+ m_cls,
76
+ req_ovr_dct[a],
77
+ )
78
+
79
+ if RequiresOverride in m_cls.__bases__:
80
+ for a, o in m_cls.__dict__.items():
81
+ if needs_override(a, o):
82
+ req_ovr_dct.setdefault(a, m_cls)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev318
3
+ Version: 0.0.0.dev320
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=orgsRvtpHu8tdhaCvlP9v3P495OJopYYiHKjK68WtWg,8587
2
- omlish/__about__.py,sha256=kisuBtrw4R5wrzm5nluakJkzLD7HYXcYuB7zYWAgrQc,3478
2
+ omlish/__about__.py,sha256=FeukuYwaj2C76Mzk3hq5wOg3XQJAHeMSMrlYj3FUAow,3478
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -76,8 +76,9 @@ omlish/codecs/funcs.py,sha256=p4imNt7TobyZVXWC-WhntHVu9KfJrO4QwdtPRh-cVOk,850
76
76
  omlish/codecs/registry.py,sha256=2FnO5YP7ui1LzkguwESY0MP3WIdwgPTIJTM_4RyTOEg,3896
77
77
  omlish/codecs/standard.py,sha256=eiZ4u9ep0XrA4Z_D1zJI0vmWyuN8HLrX4Se_r_Cq_ZM,60
78
78
  omlish/codecs/text.py,sha256=JzrdwMpQPo2NBBg3K1EZszzQy5vEWmd82SIerJd4yeQ,5723
79
- omlish/collections/__init__.py,sha256=YHnllmObi8oL_q3h6SMjim7VaNaABmCGUSIiOh2cF2c,2333
79
+ omlish/collections/__init__.py,sha256=7r4qY9paGL-pC8ZNJn6taod9T2qAyMjIpcL7ptb8GaI,2394
80
80
  omlish/collections/abc.py,sha256=ikTJlJ5dhXjU6tlNsI0Wm0_7GaIEpe3mftpvdGY_nc8,2620
81
+ omlish/collections/bimap.py,sha256=8lPBCE7B99FgNZMFFYY1iWI_Q1D0whlbELRuJr5_eh0,1647
81
82
  omlish/collections/coerce.py,sha256=tAls15v_7p5bUN33R7Zbko87KW5toWHl9fRialCqyNY,7030
82
83
  omlish/collections/errors.py,sha256=shcS-NCnEUudF8qC_SmO2TQyjivKlS4TDjaz_faqQ0c,44
83
84
  omlish/collections/frozen.py,sha256=LMbAHYDENIQk1hvjCTvpnx66m1TalrHa4CSn8n_tsXQ,4142
@@ -225,7 +226,7 @@ omlish/dispatch/_dispatch3.py,sha256=9Zjd7bINAC3keiaBdssc4v5dY0-8OI6XooV2DR9U7Z0
225
226
  omlish/dispatch/dispatch.py,sha256=KA5l49AiGLRjp4J7RDJW9RiDp9WUD1ewR1AOPEF8g38,3062
226
227
  omlish/dispatch/functions.py,sha256=cwNzGIg2ZIalEgn9I03cnJVbMTHjWloyDTaowlO3UPs,1524
227
228
  omlish/dispatch/impls.py,sha256=K_okKvpZml4NkTHJmTVyMQSrIaIJcqTEgkreGwukaOw,1895
228
- omlish/dispatch/methods.py,sha256=CeGVwiUdeadzyOe0xQVY_jegyj0tdHLQZpaIlLkJNnY,7330
229
+ omlish/dispatch/methods.py,sha256=GdVsC-Zo3N-OorE0mr3lFI70dATkD2aWqZ8TvExiR5k,9297
229
230
  omlish/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
231
  omlish/docker/all.py,sha256=xXRgJgLGPwAtr7bDMJ_Dp9jTfOwfGvohNhc6LsoELJc,514
231
232
  omlish/docker/cli.py,sha256=gtb9kitVfGnd4cr587NsVVk8D5Ok5y5SAsqD_SwGrSA,2565
@@ -403,7 +404,7 @@ omlish/iterators/iterators.py,sha256=RxW35yQ5ed8vBQ22IqpDXFx-i5JiLQdp7-pkMZXhJJ8
403
404
  omlish/iterators/recipes.py,sha256=wOwOZg-zWG9Zc3wcAxJFSe2rtavVBYwZOfG09qYEx_4,472
404
405
  omlish/iterators/tools.py,sha256=c4hArZEVV8y9_dFfmRwakusv1cWJLT4MkTkGRjnGN5U,2556
405
406
  omlish/iterators/unique.py,sha256=Nw0pSaNEcHAkve0ugfLPvJcirDOn9ECyC5wIL8JlJKI,1395
406
- omlish/lang/__init__.py,sha256=Zs5YE5F7rq2cdEqK2e6QuamTQGGwLaM0OP_RNOmcT1A,5921
407
+ omlish/lang/__init__.py,sha256=FvYmM3q0Z2wYOq0m7DWiksMSYgszdxWrSHDHFetpW_0,6135
407
408
  omlish/lang/attrs.py,sha256=i7euRF81uNF8QDmUVXSK_BtqLGshaMi4VVdUnMjiMwg,5050
408
409
  omlish/lang/casing.py,sha256=cFUlbDdXLhwnWwcYx4qnM5c4zGX7hIRUfcjiZbxUD28,4636
409
410
  omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
@@ -419,6 +420,7 @@ omlish/lang/imports.py,sha256=y9W9Y-d_cQ35QCLuSIPoa6vnEqSErFCz8b-34IH128U,10552
419
420
  omlish/lang/iterables.py,sha256=StoGp9yaP3njdLKHoWYcEevO3eE8SHEPYl5_avZob24,2149
420
421
  omlish/lang/objects.py,sha256=nbxBHfQHVw0OG4qeSTP2GvIiFIcH2tbbitY8y-mYPPo,5959
421
422
  omlish/lang/outcomes.py,sha256=mpFy_VoM-b74L1aCFsjsZVUHx_icZ1AHMOKeVesjOp4,8628
423
+ omlish/lang/overrides.py,sha256=IBzK6ljfLX6TLgIyKTSjhqTLcuKRkQNVtEOnBLS4nuA,2095
422
424
  omlish/lang/params.py,sha256=sfbNoGrKCsAtubFufj_uh_WKshIgA8fqJ4PmLH1PH00,6639
423
425
  omlish/lang/recursion.py,sha256=1VfSqzKO-8Is3t9LKw0W4jwPfE0aBS70EUlbUxAx4eE,1900
424
426
  omlish/lang/resolving.py,sha256=ei9LDyJexsMMHB9z8diUkNmynWhd_da7h7TqrMYM6lA,1611
@@ -430,9 +432,10 @@ omlish/lang/cached/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
430
432
  omlish/lang/cached/function.py,sha256=tch6VlDljfUUFMP61RY0LYXYyNwj1Sy8CAQQQMHCypA,11344
431
433
  omlish/lang/cached/property.py,sha256=WHYyg4-6EA86TcNMfbXTjVhjEZPc0kngt9hfY3WN5w8,2768
432
434
  omlish/lang/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
433
- omlish/lang/classes/abstract.py,sha256=n4rDlDraUKxPF0GtOWEFZ6mEzEDmP7Z8LSI6Jww_thw,3715
435
+ omlish/lang/classes/abstract.py,sha256=A-Jg5X8o_WvFryN0Cm2TpVkrZoTT1SYKQnv_pXjZk7o,3808
436
+ omlish/lang/classes/namespaces.py,sha256=_FBLekx2gNLql1C1ZRlpBtxuLWbcdFEzBm8CrD5XeOA,3589
434
437
  omlish/lang/classes/restrict.py,sha256=nCsQuSFsKTwLhYfmwZr9af00qdVA8TuPQXaSJQNKzBI,3543
435
- omlish/lang/classes/simple.py,sha256=XQ8b86WvQA0qtSYqlbMOJS7tHgE8sv9onda33uQmbkM,3294
438
+ omlish/lang/classes/simple.py,sha256=2C7u8k0K75xzcr6DT8zYd8U-1Yr_Xq1pfF3a0J6wo3g,2538
436
439
  omlish/lang/classes/virtual.py,sha256=z0MYQD9Q5MkX8DzF325wDB4J9XoYbsB09jZ1omC62To,3366
437
440
  omlish/lifecycles/__init__.py,sha256=1FjYceXs-4fc-S-C9zFYmc2axHs4znnQHcJVHdY7a6E,578
438
441
  omlish/lifecycles/abstract.py,sha256=70CQyZy-c9a2o0ZJxPeUT7eYjWZTBrp2HpUBnrHdAOM,1109
@@ -853,9 +856,9 @@ omlish/typedvalues/holder.py,sha256=ZTnHiw-K38ciOBLEdwgrltr7Xp8jjEs_0Lp69DH-G-o,
853
856
  omlish/typedvalues/marshal.py,sha256=hWHRLcrGav7lvXJDtb9bNI0ickl4SKPQ6F4BbTpqw3A,4219
854
857
  omlish/typedvalues/reflect.py,sha256=Ih1YgU-srUjsvBn_P7C66f73_VCvcwqE3ffeBnZBgt4,674
855
858
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
856
- omlish-0.0.0.dev318.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
857
- omlish-0.0.0.dev318.dist-info/METADATA,sha256=-Nc1DXmiJNc5JokC60eHTE9VTgT6oMoXEf496J6i6UE,4416
858
- omlish-0.0.0.dev318.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
859
- omlish-0.0.0.dev318.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
860
- omlish-0.0.0.dev318.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
861
- omlish-0.0.0.dev318.dist-info/RECORD,,
859
+ omlish-0.0.0.dev320.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
860
+ omlish-0.0.0.dev320.dist-info/METADATA,sha256=vbJ5M90IBzxV3KWEV0QnEI-t7UtQCT6RI2XftEOlcZE,4416
861
+ omlish-0.0.0.dev320.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
862
+ omlish-0.0.0.dev320.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
863
+ omlish-0.0.0.dev320.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
864
+ omlish-0.0.0.dev320.dist-info/RECORD,,