omlish 0.0.0.dev244__py3-none-any.whl → 0.0.0.dev245__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.dev244'
2
- __revision__ = 'e7768b1afd9f43a5f1534c2840691f48c0a89efb'
1
+ __version__ = '0.0.0.dev245'
2
+ __revision__ = 'c3979ac75a1b25b3c679bc0310afb6364c124c4c'
3
3
 
4
4
 
5
5
  #
omlish/cached.py CHANGED
@@ -9,11 +9,12 @@ builtins and thus not distinguish it from a normal property.
9
9
  def p(self) -> str: ...
10
10
 
11
11
  """
12
- from .lang.cached import _CachedProperty # noqa
13
- from .lang.cached import cached_function as _cached_function
12
+ from .lang.cached.function import cached_function as _cached_function
13
+ from .lang.cached.property import cached_property as _cached_property
14
+
14
15
 
15
16
  function = _cached_function
16
17
 
17
18
  property = property # noqa
18
19
 
19
- globals()['property'] = _CachedProperty # noqa
20
+ globals()['property'] = _cached_property # noqa
omlish/lang/__init__.py CHANGED
@@ -1,39 +1,63 @@
1
- from .cached import ( # noqa
1
+ from .attrs import ( # noqa
2
+ AttrOps,
3
+ STD_ATTR_OPS,
4
+ StdAttrOps,
5
+ TRANSIENT_ATTR_OPS,
6
+ TransientAttrOps,
7
+ TransientDict,
8
+ transient_delattr,
9
+ transient_getattr,
10
+ transient_setattr,
11
+ )
12
+
13
+ from .cached.function import ( # noqa
2
14
  cached_function,
3
- cached_property,
4
15
  static_init,
5
16
  )
6
17
 
7
- from .classes import ( # noqa
18
+ from .cached.property import ( # noqa
19
+ cached_property,
20
+ )
21
+
22
+ from .classes.abstract import ( # noqa
8
23
  Abstract,
9
24
  AbstractTypeError,
25
+ get_abstract_methods,
26
+ is_abstract,
27
+ is_abstract_class,
28
+ is_abstract_method,
29
+ make_abstract,
30
+ unabstract_class,
31
+ )
32
+
33
+ from .classes.restrict import ( # noqa
10
34
  AnySensitive,
11
- Callable,
12
- Descriptor,
13
35
  Final,
14
36
  FinalTypeError,
15
- LazySingleton,
16
- Marker,
17
- Namespace,
18
37
  NoBool,
19
38
  NotInstantiable,
20
39
  NotPicklable,
21
40
  PackageSealed,
22
- Picklable,
23
41
  SENSITIVE_ATTR,
24
42
  Sealed,
25
43
  SealedError,
26
44
  Sensitive,
45
+ no_bool,
46
+ )
47
+
48
+ from .classes.simple import ( # noqa
49
+ LazySingleton,
50
+ Marker,
51
+ Namespace,
27
52
  SimpleMetaDict,
28
53
  Singleton,
54
+ )
55
+
56
+ from .classes.virtual import ( # noqa
57
+ Callable,
58
+ Descriptor,
59
+ Picklable,
29
60
  Virtual,
30
- get_abstract_methods,
31
- is_abstract,
32
- is_abstract_class,
33
- is_abstract_method,
34
- make_abstract,
35
- no_bool,
36
- unabstract_class,
37
61
  virtual_check,
38
62
  )
39
63
 
omlish/lang/attrs.py ADDED
@@ -0,0 +1,132 @@
1
+ import abc
2
+ import collections.abc
3
+ import typing as ta
4
+
5
+
6
+ ##
7
+
8
+
9
+ class AttrOps(abc.ABC):
10
+ class NOT_SET: # noqa
11
+ def __new__(cls, *args, **kwargs): # noqa
12
+ raise TypeError
13
+
14
+ @abc.abstractmethod
15
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = NOT_SET) -> ta.Any:
16
+ raise NotImplementedError
17
+
18
+ @abc.abstractmethod
19
+ def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
20
+ raise NotImplementedError
21
+
22
+ @abc.abstractmethod
23
+ def delattr(self, obj: ta.Any, name: str) -> None:
24
+ raise NotImplementedError
25
+
26
+
27
+ ##
28
+
29
+
30
+ class StdAttrOps(AttrOps):
31
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
32
+ if default is AttrOps.NOT_SET:
33
+ return getattr(obj, name)
34
+ else:
35
+ return getattr(obj, name, default)
36
+
37
+ def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
38
+ setattr(obj, name, value)
39
+
40
+ def delattr(self, obj: ta.Any, name: str) -> None:
41
+ delattr(obj, name)
42
+
43
+
44
+ STD_ATTR_OPS = StdAttrOps()
45
+
46
+
47
+ ##
48
+
49
+
50
+ class TransientDict(collections.abc.MutableMapping):
51
+ def __init__(self) -> None:
52
+ super().__init__()
53
+
54
+ self._dct: dict = {}
55
+
56
+ def __reduce__(self):
57
+ return (TransientDict, ())
58
+
59
+ def __getitem__(self, item):
60
+ return self._dct[item]
61
+
62
+ def __setitem__(self, key, value):
63
+ self._dct[key] = value
64
+
65
+ def __delitem__(self, key):
66
+ del self._dct[key]
67
+
68
+ def __len__(self):
69
+ return len(self._dct)
70
+
71
+ def __iter__(self):
72
+ return iter(self._dct)
73
+
74
+ def clear(self):
75
+ self._dct.clear()
76
+
77
+ def items(self):
78
+ return self._dct.items()
79
+
80
+ def keys(self):
81
+ return self._dct.keys()
82
+
83
+ def values(self):
84
+ return self._dct.values()
85
+
86
+ def __contains__(self, key, /):
87
+ return super().__contains__(key)
88
+
89
+ def __eq__(self, other, /):
90
+ raise TypeError(self)
91
+
92
+
93
+ #
94
+
95
+
96
+ _TRANSIENT_DICT_ATTR = '__transient_dict__'
97
+
98
+
99
+ def _get_object_transient_dict(obj: ta.Any) -> TransientDict:
100
+ try:
101
+ return obj.__dict__[_TRANSIENT_DICT_ATTR]
102
+ except KeyError:
103
+ return obj.__dict__.setdefault(_TRANSIENT_DICT_ATTR, TransientDict())
104
+
105
+
106
+ class TransientAttrOps(AttrOps):
107
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
108
+ td = _get_object_transient_dict(obj)
109
+ try:
110
+ return td[name]
111
+ except KeyError:
112
+ if default is not AttrOps.NOT_SET:
113
+ return default
114
+ raise AttributeError(name) from None
115
+
116
+ def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
117
+ td = _get_object_transient_dict(obj)
118
+ td[name] = value
119
+
120
+ def delattr(self, obj: ta.Any, name: str) -> None:
121
+ td = _get_object_transient_dict(obj)
122
+ try:
123
+ del td[name]
124
+ except KeyError:
125
+ raise AttributeError(name) from None
126
+
127
+
128
+ TRANSIENT_ATTR_OPS = TransientAttrOps()
129
+
130
+ transient_getattr = TRANSIENT_ATTR_OPS.getattr
131
+ transient_setattr = TRANSIENT_ATTR_OPS.setattr
132
+ transient_delattr = TRANSIENT_ATTR_OPS.delattr
File without changes
@@ -2,37 +2,42 @@
2
2
  TODO:
3
3
  - integrate / expose with collections.cache
4
4
  - weakrefs (selectable by arg)
5
- - locks
5
+ - more rigorous descriptor pickling
6
+ - must support free functions (which have no instance nor owner)
7
+ - 'staticmethod' or effective equiv - which must resolve to the shared instance
8
+ - and must be transient?
6
9
  """
7
10
  import dataclasses as dc
8
11
  import functools
9
12
  import inspect
10
13
  import typing as ta
11
14
 
12
- from .contextmanagers import DefaultLockable
13
- from .contextmanagers import default_lock
14
- from .descriptors import unwrap_func
15
- from .descriptors import unwrap_func_with_partials
15
+ from ..classes.abstract import Abstract
16
+ from ..contextmanagers import DefaultLockable
17
+ from ..contextmanagers import default_lock
18
+ from ..descriptors import unwrap_func
19
+ from ..descriptors import unwrap_func_with_partials
16
20
 
17
21
 
18
22
  P = ta.ParamSpec('P')
19
23
  T = ta.TypeVar('T')
20
24
  CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
21
25
 
22
- _IGNORE = object()
26
+
27
+ ##
23
28
 
24
29
 
25
- def _nullary_cache_keyer():
30
+ def _nullary_cache_key_maker():
26
31
  return ()
27
32
 
28
33
 
29
- def _simple_cache_keyer(*args, **kwargs):
34
+ def _simple_cache_key_maker(*args, **kwargs):
30
35
  return (args, tuple(sorted(kwargs.items())))
31
36
 
32
37
 
33
- def _make_cache_keyer(fn, *, simple=False, bound=False):
38
+ def _make_cache_key_maker(fn, *, simple=False, bound=False):
34
39
  if simple:
35
- return _simple_cache_keyer
40
+ return _simple_cache_key_maker
36
41
 
37
42
  fn, partials = unwrap_func_with_partials(fn)
38
43
 
@@ -42,7 +47,7 @@ def _make_cache_keyer(fn, *, simple=False, bound=False):
42
47
  sig = inspect.signature(fn)
43
48
  sig_params = list(sig.parameters.values())[1 if bound else 0:]
44
49
  if not sig_params:
45
- return _nullary_cache_keyer
50
+ return _nullary_cache_key_maker
46
51
 
47
52
  ns = {}
48
53
  src_params = []
@@ -92,19 +97,23 @@ def _make_cache_keyer(fn, *, simple=False, bound=False):
92
97
  return kfn
93
98
 
94
99
 
95
- class _CachedFunction(ta.Generic[T]):
100
+ ##
101
+
102
+
103
+ class _CachedFunction(ta.Generic[T], Abstract):
96
104
  @dc.dataclass(frozen=True)
97
105
  class Opts:
98
106
  map_maker: ta.Callable[[], ta.MutableMapping] = dict
99
107
  simple_key: bool = False
100
108
  lock: DefaultLockable = None
109
+ transient: bool = False
101
110
 
102
111
  def __init__(
103
112
  self,
104
113
  fn: ta.Callable[P, T],
105
114
  *,
106
115
  opts: Opts = Opts(),
107
- keyer: ta.Callable[..., tuple] | None = None,
116
+ key_maker: ta.Callable[..., tuple] | None = None,
108
117
  values: ta.MutableMapping | None = None,
109
118
  value_fn: ta.Callable[P, T] | None = None,
110
119
  ) -> None:
@@ -112,7 +121,7 @@ class _CachedFunction(ta.Generic[T]):
112
121
 
113
122
  self._fn = (fn,)
114
123
  self._opts = opts
115
- self._keyer = keyer if keyer is not None else _make_cache_keyer(fn, simple=opts.simple_key)
124
+ self._key_maker = key_maker if key_maker is not None else _make_cache_key_maker(fn, simple=opts.simple_key)
116
125
 
117
126
  self._lock = default_lock(opts.lock, False)() if opts.lock is not None else None
118
127
  self._values = values if values is not None else opts.map_maker()
@@ -134,7 +143,7 @@ class _CachedFunction(ta.Generic[T]):
134
143
  raise TypeError
135
144
 
136
145
  def __call__(self, *args, **kwargs) -> T:
137
- k = self._keyer(*args, **kwargs)
146
+ k = self._key_maker(*args, **kwargs)
138
147
 
139
148
  try:
140
149
  return self._values[k]
@@ -157,11 +166,42 @@ class _CachedFunction(ta.Generic[T]):
157
166
  return value
158
167
 
159
168
 
160
- class _CachedFunctionDescriptor(_CachedFunction[T]):
169
+ #
170
+
171
+
172
+ class _FreeCachedFunction(_CachedFunction[T]):
173
+ @classmethod
174
+ def _unpickle(
175
+ cls,
176
+ fn,
177
+ opts,
178
+ values,
179
+ ):
180
+ return cls(
181
+ fn,
182
+ opts=opts,
183
+ values=values,
184
+ )
185
+
186
+ def __reduce__(self):
187
+ return (
188
+ _FreeCachedFunction._unpickle,
189
+ (
190
+ self._fn,
191
+ self._opts,
192
+ self._values if not self._opts.transient else None,
193
+ ),
194
+ )
195
+
196
+
197
+ #
198
+
199
+
200
+ class _DescriptorCachedFunction(_CachedFunction[T]):
161
201
  def __init__(
162
202
  self,
163
203
  fn: ta.Callable[P, T],
164
- scope: ta.Any,
204
+ scope: ta.Any, # classmethod | None
165
205
  *,
166
206
  instance: ta.Any = None,
167
207
  owner: ta.Any = None,
@@ -174,9 +214,61 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
174
214
  self._instance = instance
175
215
  self._owner = owner
176
216
  self._name = name if name is not None else unwrap_func(fn).__name__
177
- self._bound_keyer = None
217
+ self._bound_key_maker = None
178
218
 
179
- def __get__(self, instance, owner=None):
219
+ @classmethod
220
+ def _unpickle(
221
+ cls,
222
+ scope,
223
+ instance,
224
+ owner,
225
+ name,
226
+ values,
227
+ ):
228
+ if scope is not None:
229
+ raise NotImplementedError
230
+
231
+ if instance is None:
232
+ raise RuntimeError
233
+ obj = type(instance)
234
+
235
+ desc: _DescriptorCachedFunction = object.__getattribute__(obj, name)
236
+ if not isinstance(desc, cls):
237
+ raise TypeError(desc)
238
+ if (desc._instance is not None or desc._owner is not None):
239
+ raise RuntimeError
240
+
241
+ return desc._bind(
242
+ instance,
243
+ owner,
244
+ values=values,
245
+ )
246
+
247
+ def __reduce__(self):
248
+ if self._scope is not None:
249
+ raise NotImplementedError
250
+
251
+ if not (self._instance is not None or self._owner is not None):
252
+ raise RuntimeError
253
+
254
+ return (
255
+ _DescriptorCachedFunction._unpickle,
256
+ (
257
+ self._scope,
258
+ self._instance,
259
+ self._owner,
260
+ self._name,
261
+ self._values if not self._opts.transient else None,
262
+ ),
263
+ )
264
+
265
+ def _bind(
266
+ self,
267
+ instance,
268
+ owner=None,
269
+ *,
270
+ values: ta.MutableMapping | None = None,
271
+ ):
180
272
  scope = self._scope
181
273
  if owner is self._owner and (instance is self._instance or scope is classmethod):
182
274
  return self
@@ -184,8 +276,8 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
184
276
  fn, = self._fn
185
277
  name = self._name
186
278
  bound_fn = fn.__get__(instance, owner)
187
- if self._bound_keyer is None:
188
- self._bound_keyer = _make_cache_keyer(fn, simple=self._opts.simple_key, bound=True)
279
+ if self._bound_key_maker is None:
280
+ self._bound_key_maker = _make_cache_key_maker(fn, simple=self._opts.simple_key, bound=True)
189
281
 
190
282
  bound = self.__class__(
191
283
  fn,
@@ -194,8 +286,9 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
194
286
  instance=instance,
195
287
  owner=owner,
196
288
  name=name,
197
- keyer=self._bound_keyer,
198
- # values=None if scope is classmethod else self._values,
289
+ key_maker=self._bound_key_maker,
290
+ # values=None if scope is classmethod else self._values, # FIXME: ?
291
+ values=values,
199
292
  value_fn=bound_fn,
200
293
  )
201
294
 
@@ -206,76 +299,24 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
206
299
 
207
300
  return bound
208
301
 
302
+ def __get__(self, instance, owner=None):
303
+ return self._bind(instance, owner)
304
+
305
+
306
+ #
307
+
209
308
 
210
309
  def cached_function(fn=None, **kwargs): # noqa
211
310
  if fn is None:
212
311
  return functools.partial(cached_function, **kwargs)
213
312
  opts = _CachedFunction.Opts(**kwargs)
214
313
  if isinstance(fn, staticmethod):
215
- return _CachedFunction(fn, opts=opts, value_fn=unwrap_func(fn))
314
+ return _FreeCachedFunction(fn, opts=opts, value_fn=unwrap_func(fn))
216
315
  scope = classmethod if isinstance(fn, classmethod) else None
217
- return _CachedFunctionDescriptor(fn, scope, opts=opts)
316
+ return _DescriptorCachedFunction(fn, scope, opts=opts)
218
317
 
219
318
 
220
319
  def static_init(fn: CallableT) -> CallableT:
221
320
  fn = cached_function(fn)
222
321
  fn()
223
322
  return fn
224
-
225
-
226
- ##
227
-
228
-
229
- class _CachedProperty(property):
230
- def __init__(
231
- self,
232
- fn,
233
- *,
234
- name=None,
235
- ignore_if=lambda _: False,
236
- clear_on_init=False,
237
- ):
238
- if isinstance(fn, property):
239
- fn = fn.fget
240
- super().__init__(fn)
241
- self._fn = fn
242
- self._ignore_if = ignore_if
243
- self._name = name
244
- self._clear_on_init = clear_on_init
245
-
246
- def __set_name__(self, owner, name):
247
- if self._name is None:
248
- self._name = name
249
-
250
- def __get__(self, instance, owner=None):
251
- if instance is None:
252
- return self
253
- if self._name is None:
254
- raise TypeError(self)
255
-
256
- try:
257
- return instance.__dict__[self._name]
258
- except KeyError:
259
- pass
260
-
261
- value = self._fn.__get__(instance, owner)()
262
- if value is _IGNORE:
263
- return None
264
- instance.__dict__[self._name] = value
265
- return value
266
-
267
- def __set__(self, instance, value):
268
- if self._ignore_if(value):
269
- return
270
- if instance.__dict__[self._name] == value:
271
- return
272
- raise TypeError(self._name)
273
-
274
- def __delete__(self, instance):
275
- raise TypeError
276
-
277
-
278
- def cached_property(fn=None, **kwargs): # noqa
279
- if fn is None:
280
- return functools.partial(cached_property, **kwargs)
281
- return _CachedProperty(fn, **kwargs)
@@ -0,0 +1,118 @@
1
+ import abc
2
+ import functools
3
+ import typing as ta
4
+
5
+ from ..attrs import transient_getattr
6
+ from ..attrs import transient_setattr
7
+ from ..classes.abstract import Abstract
8
+
9
+
10
+ _IGNORE = object()
11
+
12
+
13
+ ##
14
+
15
+
16
+ class _CachedProperty(property, Abstract):
17
+ def __init__(
18
+ self,
19
+ fn,
20
+ *,
21
+ name=None,
22
+ ignore_if=lambda _: False,
23
+ ):
24
+ if isinstance(fn, property):
25
+ fn = fn.fget
26
+
27
+ super().__init__(fn)
28
+
29
+ self._fn = fn
30
+ self._ignore_if = ignore_if
31
+
32
+ self._name = name
33
+
34
+ def __set_name__(self, owner, name):
35
+ if self._name is None:
36
+ self._name = name
37
+
38
+ @abc.abstractmethod
39
+ def _instance_get(self, instance: ta.Any) -> tuple[ta.Any, bool]:
40
+ raise NotImplementedError
41
+
42
+ @abc.abstractmethod
43
+ def _instance_set(self, instance: ta.Any, value: ta.Any) -> None:
44
+ raise NotImplementedError
45
+
46
+ def __get__(self, instance, owner=None):
47
+ if instance is None:
48
+ return self
49
+ if self._name is None:
50
+ raise TypeError(self)
51
+
52
+ value, ok = self._instance_get(instance)
53
+ if ok:
54
+ return value
55
+
56
+ value = self._fn.__get__(instance, owner)()
57
+ if value is _IGNORE:
58
+ return None
59
+
60
+ self._instance_set(instance, value)
61
+ return value
62
+
63
+ def __set__(self, instance, value):
64
+ if self._ignore_if(value):
65
+ return
66
+
67
+ ev, ok = self._instance_get(instance)
68
+ if ok and ev == value:
69
+ return
70
+
71
+ raise TypeError(self._name)
72
+
73
+ def __delete__(self, instance):
74
+ raise TypeError
75
+
76
+
77
+ #
78
+
79
+
80
+ class _DictCachedProperty(_CachedProperty):
81
+ def _instance_get(self, instance: ta.Any) -> tuple[ta.Any, bool]:
82
+ try:
83
+ value = instance.__dict__[self._name]
84
+ except KeyError:
85
+ return None, False
86
+ else:
87
+ return value, True
88
+
89
+ def _instance_set(self, instance: ta.Any, value: ta.Any) -> None:
90
+ instance.__dict__[self._name] = value
91
+
92
+
93
+ #
94
+
95
+
96
+ class _TransientCachedProperty(_CachedProperty):
97
+ def _instance_get(self, instance: ta.Any) -> tuple[ta.Any, bool]:
98
+ try:
99
+ value = transient_getattr(instance, self._name)
100
+ except AttributeError:
101
+ return None, False
102
+ else:
103
+ return value, True
104
+
105
+ def _instance_set(self, instance: ta.Any, value: ta.Any) -> None:
106
+ transient_setattr(instance, self._name, value)
107
+
108
+
109
+ #
110
+
111
+
112
+ def cached_property(fn=None, *, transient=False, **kwargs): # noqa
113
+ if fn is None:
114
+ return functools.partial(cached_property, transient=transient, **kwargs)
115
+ if transient:
116
+ return _TransientCachedProperty(fn, **kwargs)
117
+ else:
118
+ return _DictCachedProperty(fn, **kwargs)
@@ -1,41 +0,0 @@
1
- from .abstract import ( # noqa
2
- Abstract,
3
- AbstractTypeError,
4
- get_abstract_methods,
5
- is_abstract,
6
- is_abstract_class,
7
- is_abstract_method,
8
- make_abstract,
9
- unabstract_class,
10
- )
11
-
12
- from .restrict import ( # noqa
13
- AnySensitive,
14
- Final,
15
- FinalTypeError,
16
- NoBool,
17
- NotInstantiable,
18
- NotPicklable,
19
- PackageSealed,
20
- SENSITIVE_ATTR,
21
- Sealed,
22
- SealedError,
23
- Sensitive,
24
- no_bool,
25
- )
26
-
27
- from .simple import ( # noqa
28
- LazySingleton,
29
- Marker,
30
- Namespace,
31
- SimpleMetaDict,
32
- Singleton,
33
- )
34
-
35
- from .virtual import ( # noqa
36
- Callable,
37
- Descriptor,
38
- Picklable,
39
- Virtual,
40
- virtual_check,
41
- )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omlish
3
- Version: 0.0.0.dev244
3
+ Version: 0.0.0.dev245
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,8 +1,8 @@
1
1
  omlish/.manifests.json,sha256=vQTAIvR8OblSq-uP2GUfnbei0RnmAnM5j0T1-OToh9E,8253
2
- omlish/__about__.py,sha256=I6B5uZQiJsqsRd0Vxt8abjKC5YXkiwOJFtBfeWlVYAM,3380
2
+ omlish/__about__.py,sha256=igneh_Z18EcRdtPlDRmK5tHmRK3NpxQPFoUopKrrNtw,3380
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
5
- omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
5
+ omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
6
6
  omlish/check.py,sha256=THqm6jD1a0skAO5EC8SOVg58yq96Vk5wcuruBkCYxyU,2016
7
7
  omlish/datetimes.py,sha256=HajeM1kBvwlTa-uR1TTZHmZ3zTPnnUr1uGGQhiO1XQ0,2152
8
8
  omlish/defs.py,sha256=9uUjJuVIbCBL3g14fyzAp-9gH935MFofvlfOGwcBIaM,4913
@@ -399,8 +399,8 @@ omlish/iterators/iterators.py,sha256=ghI4dO6WPyyFOLTIIMaHQ_IOy2xXaFpGPqveZ5YGIBU
399
399
  omlish/iterators/recipes.py,sha256=53mkexitMhkwXQZbL6DrhpT0WePQ_56uXd5Jaw3DfzI,467
400
400
  omlish/iterators/tools.py,sha256=Pi4ybXytUXVZ3xwK89xpPImQfYYId9p1vIFQvVqVLqA,2551
401
401
  omlish/iterators/unique.py,sha256=0jAX3kwzVfRNhe0Tmh7kVP_Q2WBIn8POo_O-rgFV0rQ,1390
402
- omlish/lang/__init__.py,sha256=T_hx_ygi-IqmeDPQ-uto2U4ZuAUDs-agOSAsF6WWLVI,4193
403
- omlish/lang/cached.py,sha256=tQaqMu1LID0q4NSTk5vPXsgxIBWSFAmjs5AhQoEHoCQ,7833
402
+ omlish/lang/__init__.py,sha256=0LNdzzVTKiDEmjCzT9wUPbimcAu21KYe-EwD4xDgtRM,4592
403
+ omlish/lang/attrs.py,sha256=vGYdGnS7ZAbSz0ZSZkkZKHCK1tKoNjZY0JdzFraHiUw,3105
404
404
  omlish/lang/clsdct.py,sha256=sJYadm-fwzti-gsi98knR5qQUxriBmOqQE_qz3RopNk,1743
405
405
  omlish/lang/cmp.py,sha256=5vbzWWbqdzDmNKAGL19z6ZfUKe5Ci49e-Oegf9f4BsE,1346
406
406
  omlish/lang/contextmanagers.py,sha256=UPH6daYwSP9cH5AfSVsJyEHk1UURMGhVPM5ZRhp_Hvw,7576
@@ -418,7 +418,10 @@ omlish/lang/resources.py,sha256=N64KeVE-rYMxqBBRp91qzgVqpOVR2uX7k1WlS_bo5hM,2681
418
418
  omlish/lang/strings.py,sha256=egdv8PxLNG40-5V93agP5j2rBUDIsahCx048zV7uEbU,4690
419
419
  omlish/lang/sys.py,sha256=UoZz_PJYVKLQAKqYxxn-LHz1okK_38I__maZgnXMcxU,406
420
420
  omlish/lang/typing.py,sha256=Zdad9Zv0sa-hIaUXPrzPidT7sDVpRcussAI7D-j-I1c,3296
421
- omlish/lang/classes/__init__.py,sha256=HY9UD3Tg8_sH59emZUKgP1Kb8-8r0GCw5hUOumxwKlM,658
421
+ omlish/lang/cached/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
422
+ omlish/lang/cached/function.py,sha256=k3jRNuDtFh9Mk97oonC7nq5XRros2qmRJVWviMFrx74,8728
423
+ omlish/lang/cached/property.py,sha256=kzbao_35PlszdK_9oJBWrMmFFlVK_Xhx7YczHhTJ6cc,2764
424
+ omlish/lang/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
422
425
  omlish/lang/classes/abstract.py,sha256=bIcuAetV_aChhpSURypmjjcqP07xi20uVYPKh1kvQNU,3710
423
426
  omlish/lang/classes/restrict.py,sha256=QvM-GqXvO8vpCONkcr0QpgVPfzZmgDo7o8d9kUwOzlo,3941
424
427
  omlish/lang/classes/simple.py,sha256=XQ8b86WvQA0qtSYqlbMOJS7tHgE8sv9onda33uQmbkM,3294
@@ -729,9 +732,9 @@ omlish/text/mangle.py,sha256=kfzFLfvepH-chl1P89_mdc5vC4FSqyPA2aVtgzuB8IY,1133
729
732
  omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
730
733
  omlish/text/parts.py,sha256=JkNZpyR2tv2CNcTaWJJhpQ9E4F0yPR8P_YfDbZfMtwQ,6182
731
734
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
732
- omlish-0.0.0.dev244.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
733
- omlish-0.0.0.dev244.dist-info/METADATA,sha256=7T41OvUEW2aOLkXNGyFicYfwqbooZHctPFTfjF0XpnQ,4176
734
- omlish-0.0.0.dev244.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
735
- omlish-0.0.0.dev244.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
736
- omlish-0.0.0.dev244.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
737
- omlish-0.0.0.dev244.dist-info/RECORD,,
735
+ omlish-0.0.0.dev245.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
736
+ omlish-0.0.0.dev245.dist-info/METADATA,sha256=JjIb3VY1vdwMkndkHrbTmD72X00OMiCJVwBpn07rc88,4176
737
+ omlish-0.0.0.dev245.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
738
+ omlish-0.0.0.dev245.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
739
+ omlish-0.0.0.dev245.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
740
+ omlish-0.0.0.dev245.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5