omlish 0.0.0.dev265__py3-none-any.whl → 0.0.0.dev267__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 (36) hide show
  1. omlish/__about__.py +5 -5
  2. omlish/collections/__init__.py +5 -0
  3. omlish/collections/abc.py +24 -0
  4. omlish/collections/cache/descriptor.py +3 -0
  5. omlish/collections/cache/impl.py +3 -0
  6. omlish/collections/cache/types.py +3 -0
  7. omlish/collections/coerce.py +2 -1
  8. omlish/collections/frozen.py +3 -0
  9. omlish/collections/hasheq.py +3 -0
  10. omlish/collections/identity.py +3 -0
  11. omlish/collections/kv/__init__.py +51 -0
  12. omlish/collections/kv/base.py +55 -0
  13. omlish/collections/kv/capabilities.py +46 -0
  14. omlish/collections/kv/filtered.py +101 -0
  15. omlish/collections/kv/mappings.py +76 -0
  16. omlish/collections/kv/transformed.py +126 -0
  17. omlish/collections/kv/wrappers.py +99 -0
  18. omlish/collections/mappings.py +3 -0
  19. omlish/collections/ordered.py +3 -0
  20. omlish/collections/persistent/persistent.py +3 -0
  21. omlish/collections/persistent/treap.py +5 -1
  22. omlish/collections/persistent/treapmap.py +3 -0
  23. omlish/collections/sorted/sorted.py +3 -0
  24. omlish/collections/unmodifiable.py +3 -0
  25. omlish/dataclasses/impl/init.py +1 -1
  26. omlish/dispatch/methods.py +1 -1
  27. omlish/lang/__init__.py +5 -1
  28. omlish/lang/classes/restrict.py +0 -12
  29. omlish/lang/functions.py +58 -1
  30. omlish/lang/objects.py +27 -5
  31. {omlish-0.0.0.dev265.dist-info → omlish-0.0.0.dev267.dist-info}/METADATA +7 -7
  32. {omlish-0.0.0.dev265.dist-info → omlish-0.0.0.dev267.dist-info}/RECORD +36 -29
  33. {omlish-0.0.0.dev265.dist-info → omlish-0.0.0.dev267.dist-info}/WHEEL +0 -0
  34. {omlish-0.0.0.dev265.dist-info → omlish-0.0.0.dev267.dist-info}/entry_points.txt +0 -0
  35. {omlish-0.0.0.dev265.dist-info → omlish-0.0.0.dev267.dist-info}/licenses/LICENSE +0 -0
  36. {omlish-0.0.0.dev265.dist-info → omlish-0.0.0.dev267.dist-info}/top_level.txt +0 -0
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev265'
2
- __revision__ = 'f83c70eb0c46f33c859473df28f39340c4f9899b'
1
+ __version__ = '0.0.0.dev267'
2
+ __revision__ = '9dca65827e8e4dae7ca1296a78c7a4d88a946259'
3
3
 
4
4
 
5
5
  #
@@ -99,15 +99,15 @@ class Project(ProjectBase):
99
99
  'aiosqlite ~= 0.21',
100
100
  'asyncpg ~= 0.30',
101
101
 
102
- 'apsw ~= 3.47',
102
+ 'apsw ~= 3.49',
103
103
 
104
- 'sqlean.py ~= 3.45',
104
+ 'sqlean.py ~= 3.47',
105
105
 
106
106
  'duckdb ~= 1.2',
107
107
  ],
108
108
 
109
109
  'testing': [
110
- 'pytest ~= 8.0',
110
+ 'pytest ~= 8.3',
111
111
  ],
112
112
  }
113
113
 
@@ -57,6 +57,11 @@ from .identity import ( # noqa
57
57
  IdentityWeakSet,
58
58
  )
59
59
 
60
+ if _ta.TYPE_CHECKING:
61
+ from . import kv
62
+ else:
63
+ kv = _lang.proxy_import('.kv', __package__)
64
+
60
65
  from .mappings import ( # noqa
61
66
  MissingDict,
62
67
  TypeMap,
omlish/collections/abc.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # ruff: noqa: ANN204
2
2
 
3
+
3
4
  class Hashable:
4
5
  def __hash__(self): ...
5
6
 
@@ -156,3 +157,26 @@ class MutableMapping(Mapping):
156
157
 
157
158
 
158
159
  # endregion
160
+
161
+
162
+ # region Views
163
+
164
+
165
+ class MappingView(Sized):
166
+ @property
167
+ def _mapping(self): ... # noqa
168
+
169
+
170
+ class KeysView(MappingView, Set):
171
+ pass
172
+
173
+
174
+ class ValuesView(MappingView, Collection):
175
+ pass
176
+
177
+
178
+ class ItemsView(MappingView, Set):
179
+ pass
180
+
181
+
182
+ # endregion
@@ -15,6 +15,9 @@ C = ta.TypeVar('C', bound=ta.Callable)
15
15
  CC: ta.TypeAlias = ta.Callable[[C], C]
16
16
 
17
17
 
18
+ ##
19
+
20
+
18
21
  class Scope(enum.Enum):
19
22
  INSTANCE = 'INSTANCE'
20
23
  CLASS = 'CLASS'
@@ -30,6 +30,9 @@ V2 = ta.TypeVar('V2')
30
30
  log = logging.getLogger(__name__)
31
31
 
32
32
 
33
+ ##
34
+
35
+
33
36
  class SKIP(lang.Marker):
34
37
  pass
35
38
 
@@ -6,6 +6,9 @@ K = ta.TypeVar('K')
6
6
  V = ta.TypeVar('V')
7
7
 
8
8
 
9
+ ##
10
+
11
+
9
12
  class OverweightError(Exception):
10
13
  pass
11
14
 
@@ -12,7 +12,8 @@ K2 = ta.TypeVar('K2')
12
12
  V = ta.TypeVar('V')
13
13
  V2 = ta.TypeVar('V2')
14
14
 
15
- _map = map
15
+
16
+ ##
16
17
 
17
18
 
18
19
  def _unpack_fn(fn):
@@ -11,6 +11,9 @@ K = ta.TypeVar('K')
11
11
  V = ta.TypeVar('V')
12
12
 
13
13
 
14
+ ##
15
+
16
+
14
17
  class Frozen(ta.Hashable, abc.ABC):
15
18
  pass
16
19
 
@@ -16,6 +16,9 @@ K2 = ta.TypeVar('K2')
16
16
  V2 = ta.TypeVar('V2')
17
17
 
18
18
 
19
+ ##
20
+
21
+
19
22
  class HashEq(lang.Abstract, ta.Generic[K]):
20
23
  @abc.abstractmethod
21
24
  def hash(self, k: K) -> int:
@@ -11,6 +11,9 @@ K = ta.TypeVar('K')
11
11
  V = ta.TypeVar('V')
12
12
 
13
13
 
14
+ ##
15
+
16
+
14
17
  class IdentityWrapper(ta.Generic[T]):
15
18
  def __init__(self, value: T) -> None:
16
19
  super().__init__()
@@ -0,0 +1,51 @@
1
+ from .base import ( # noqa
2
+ Kv,
3
+ MutableKv,
4
+ )
5
+
6
+ from .capabilities import ( # noqa
7
+ Closeable,
8
+ close,
9
+ closing,
10
+
11
+ Flushable,
12
+ flush,
13
+ )
14
+
15
+ from .filtered import ( # noqa
16
+ KeyFilteredKv,
17
+ KeyFilteredMutableKv,
18
+
19
+ ValueFilteredKeyError,
20
+ ValueFilteredKv,
21
+ ValueFilteredMutableKv,
22
+ )
23
+
24
+ from .mappings import ( # noqa
25
+ MappingKv,
26
+ MappingMutableKv,
27
+
28
+ KvMapping,
29
+ KvMutableMapping,
30
+ )
31
+
32
+ from .transformed import ( # noqa
33
+ KeyTransformedKv,
34
+ KeyTransformedMutableKey,
35
+
36
+ ValueTransformedKv,
37
+ ValueTransformedMutableKv,
38
+ )
39
+
40
+ from .wrappers import ( # noqa
41
+ WrapperKv,
42
+
43
+ underlying,
44
+ underlying_of,
45
+
46
+ SimpleWrapperKv,
47
+ SimpleWrapperMutableKv,
48
+
49
+ UnmodifiableError,
50
+ UnmodifiableKv,
51
+ )
@@ -0,0 +1,55 @@
1
+ """
2
+ TODO:
3
+ - further decomp?
4
+ - Sized + Iterable?
5
+ - COM-style QueryInterface? :|
6
+ - OpKv
7
+ - table ala guava - (row key, column key) keys, sparse storage
8
+ - router
9
+ - value thunker idiom - for key-iterable-only storage, transform Kv[K, V], to Kv[K, ta.Callable[[], V]]
10
+ - zict classes
11
+ - AsyncBuffer
12
+ - Buffer
13
+ - Cache
14
+ - File
15
+ - Func
16
+ - LMDB
17
+ - LRU
18
+ - Sieve
19
+ - Zip
20
+ """
21
+ import abc
22
+ import typing as ta
23
+
24
+ from ... import lang
25
+
26
+
27
+ K = ta.TypeVar('K')
28
+ V = ta.TypeVar('V')
29
+
30
+
31
+ ##
32
+
33
+
34
+ class Kv(lang.Abstract, ta.Generic[K, V]):
35
+ @abc.abstractmethod
36
+ def __getitem__(self, k: K, /) -> V:
37
+ raise NotImplementedError
38
+
39
+ @abc.abstractmethod
40
+ def __len__(self) -> int:
41
+ raise NotImplementedError
42
+
43
+ @abc.abstractmethod
44
+ def items(self) -> ta.Iterator[tuple[K, V]]:
45
+ raise NotImplementedError
46
+
47
+
48
+ class MutableKv(Kv[K, V], lang.Abstract): # noqa
49
+ @abc.abstractmethod
50
+ def __setitem__(self, k: K, v: V, /) -> None:
51
+ raise NotImplementedError
52
+
53
+ @abc.abstractmethod
54
+ def __delitem__(self, k: K, /) -> None:
55
+ raise NotImplementedError
@@ -0,0 +1,46 @@
1
+ import abc
2
+ import contextlib
3
+ import typing as ta
4
+
5
+ from ... import lang
6
+ from .base import Kv
7
+ from .wrappers import underlying_of
8
+
9
+
10
+ KvT = ta.TypeVar('KvT', bound=Kv)
11
+
12
+
13
+ ##
14
+
15
+
16
+ class Closeable(lang.Abstract):
17
+ @abc.abstractmethod
18
+ def close(self) -> None:
19
+ pass
20
+
21
+
22
+ def close(root: Kv) -> None:
23
+ for c in underlying_of(root, Closeable): # type: ignore[type-abstract]
24
+ c.close()
25
+
26
+
27
+ @contextlib.contextmanager
28
+ def closing(kv: KvT) -> ta.Iterator[KvT]:
29
+ try:
30
+ yield kv
31
+ finally:
32
+ close(kv)
33
+
34
+
35
+ ##
36
+
37
+
38
+ class Flushable(lang.Abstract):
39
+ @abc.abstractmethod
40
+ def flush(self) -> None:
41
+ pass
42
+
43
+
44
+ def flush(root: Kv) -> None:
45
+ for c in underlying_of(root, Flushable): # type: ignore[type-abstract]
46
+ c.flush()
@@ -0,0 +1,101 @@
1
+ import typing as ta
2
+
3
+ from ... import lang
4
+ from .base import Kv
5
+ from .base import MutableKv
6
+ from .wrappers import SimpleWrapperKv
7
+ from .wrappers import SimpleWrapperMutableKv
8
+
9
+
10
+ K = ta.TypeVar('K')
11
+ V = ta.TypeVar('V')
12
+
13
+
14
+ ##
15
+
16
+
17
+ class KeyFilteredKv(SimpleWrapperKv[K, V]):
18
+ def __init__(
19
+ self,
20
+ u: Kv[K, V],
21
+ fn: ta.Callable[[K], bool],
22
+ ) -> None:
23
+ super().__init__(u)
24
+
25
+ self._fn = fn
26
+
27
+ def __getitem__(self, k: K, /) -> V:
28
+ if not self._fn(k):
29
+ raise KeyError(k)
30
+ return self._u[k]
31
+
32
+ def __len__(self) -> int:
33
+ return lang.ilen(self.items())
34
+
35
+ def items(self) -> ta.Iterator[tuple[K, V]]:
36
+ fn = self._fn
37
+ return filter(lambda t: fn(t[0]), self._u.items())
38
+
39
+
40
+ class KeyFilteredMutableKv(KeyFilteredKv[K, V], SimpleWrapperMutableKv[K, V]):
41
+ def __init__(
42
+ self,
43
+ u: MutableKv[K, V],
44
+ fn: ta.Callable[[K], bool],
45
+ ) -> None:
46
+ super().__init__(u, fn)
47
+
48
+ def __setitem__(self, k: K, v: V, /) -> None:
49
+ if not self._fn(k):
50
+ raise KeyError(k)
51
+ self._u[k] = v
52
+
53
+ def __delitem__(self, k: K, /) -> None:
54
+ if not self._fn(k):
55
+ raise KeyError(k)
56
+ del self._u[k]
57
+
58
+
59
+ ##
60
+
61
+
62
+ class ValueFilteredKeyError(KeyError):
63
+ pass
64
+
65
+
66
+ class ValueFilteredKv(SimpleWrapperKv[K, V]):
67
+ def __init__(
68
+ self,
69
+ u: Kv[K, V],
70
+ fn: ta.Callable[[V], bool],
71
+ ) -> None:
72
+ super().__init__(u)
73
+
74
+ self._fn = fn
75
+
76
+ def __getitem__(self, k: K, /) -> V:
77
+ v = self._u[k]
78
+ if not self._fn(v):
79
+ raise ValueFilteredKeyError(k)
80
+ return v
81
+
82
+ def __len__(self) -> int:
83
+ return lang.ilen(self.items())
84
+
85
+ def items(self) -> ta.Iterator[tuple[K, V]]:
86
+ fn = self._fn
87
+ return ((k, v) for k, v in self._u.items() if fn(v))
88
+
89
+
90
+ class ValueFilteredMutableKv(ValueFilteredKv[K, V], SimpleWrapperMutableKv[K, V]):
91
+ def __init__(
92
+ self,
93
+ u: MutableKv[K, V],
94
+ fn: ta.Callable[[V], bool],
95
+ ) -> None:
96
+ super().__init__(u, fn)
97
+
98
+ def __setitem__(self, k: K, v: V, /) -> None:
99
+ if not self._fn(v):
100
+ raise ValueFilteredKeyError(k)
101
+ self._u[k] = v
@@ -0,0 +1,76 @@
1
+ import typing as ta
2
+
3
+ from .base import Kv
4
+ from .base import MutableKv
5
+
6
+
7
+ K = ta.TypeVar('K')
8
+ V = ta.TypeVar('V')
9
+
10
+
11
+ ##
12
+
13
+
14
+ class MappingKv(Kv[K, V]):
15
+ def __init__(self, m: ta.Mapping[K, V]) -> None:
16
+ super().__init__()
17
+
18
+ self._m = m
19
+
20
+ def __getitem__(self, k: K, /) -> V:
21
+ return self._m[k]
22
+
23
+ def __len__(self) -> int:
24
+ return len(self._m)
25
+
26
+ def items(self) -> ta.Iterator[tuple[K, V]]:
27
+ return iter(self._m.items())
28
+
29
+
30
+ class MappingMutableKv(MappingKv[K, V], MutableKv[K, V]):
31
+ def __init__(self, m: ta.MutableMapping[K, V]) -> None:
32
+ super().__init__(m)
33
+
34
+ _m: ta.MutableMapping[K, V]
35
+
36
+ def __setitem__(self, k: K, v: V, /) -> None:
37
+ self._m[k] = v
38
+
39
+ def __delitem__(self, k: K, /) -> None:
40
+ del self._m[k]
41
+
42
+
43
+ ##
44
+
45
+
46
+ class KvMapping(ta.Mapping[K, V]):
47
+ def __init__(self, kv: Kv[K, V]) -> None:
48
+ super().__init__()
49
+
50
+ self._kv = kv
51
+
52
+ def __getitem__(self, key: K, /) -> V:
53
+ return self._kv[key]
54
+
55
+ def __len__(self) -> int:
56
+ return len(self._kv)
57
+
58
+ # FIXME: ItemsView
59
+ def items(self) -> ta.Iterator[tuple[K, V]]: # type: ignore[override]
60
+ return iter(self._kv.items())
61
+
62
+ def __iter__(self) -> ta.Iterator[K]:
63
+ return (k for k, v in self.items())
64
+
65
+
66
+ class KvMutableMapping(KvMapping[K, V], ta.MutableMapping[K, V]):
67
+ def __init__(self, kv: MutableKv[K, V]) -> None:
68
+ super().__init__(kv)
69
+
70
+ _kv: MutableKv[K, V]
71
+
72
+ def __setitem__(self, key: K, value: V, /) -> None:
73
+ self._kv[key] = value
74
+
75
+ def __delitem__(self, key: K, /) -> None:
76
+ del self._kv[key]
@@ -0,0 +1,126 @@
1
+ import typing as ta
2
+
3
+ from ... import check
4
+ from .base import Kv
5
+ from .base import MutableKv
6
+ from .wrappers import WrapperKv
7
+
8
+
9
+ K = ta.TypeVar('K')
10
+ V = ta.TypeVar('V')
11
+
12
+ # 'Above' the wrapper
13
+ KA = ta.TypeVar('KA')
14
+ VA = ta.TypeVar('VA')
15
+
16
+ # 'Below' the wrapper
17
+ KB = ta.TypeVar('KB')
18
+ VB = ta.TypeVar('VB')
19
+
20
+
21
+ ##
22
+
23
+
24
+ class KeyTransformedKv(WrapperKv[KA, V], ta.Generic[KA, KB, V]):
25
+ def __init__(
26
+ self,
27
+ u: Kv[KB, V],
28
+ *,
29
+ a_to_b: ta.Callable[[KA], KB] | None = None,
30
+ b_to_a: ta.Callable[[KB], KA] | None = None,
31
+ ) -> None:
32
+ super().__init__()
33
+
34
+ self._u = u
35
+ self._a_to_b = a_to_b
36
+ self._b_to_a = b_to_a
37
+
38
+ def underlying(self) -> ta.Sequence[Kv]:
39
+ return [self._u]
40
+
41
+ def __getitem__(self, k: KA, /) -> V:
42
+ fn = check.not_none(self._a_to_b)
43
+ return self._u[fn(k)]
44
+
45
+ def __len__(self) -> int:
46
+ return len(self._u)
47
+
48
+ def items(self) -> ta.Iterator[tuple[KA, V]]:
49
+ fn = check.not_none(self._b_to_a)
50
+ return ((fn(k), v) for k, v in self._u.items())
51
+
52
+
53
+ class KeyTransformedMutableKey(KeyTransformedKv[KA, KB, V], MutableKv[KA, V], ta.Generic[KA, KB, V]):
54
+ def __init__(
55
+ self,
56
+ u: MutableKv[KB, V],
57
+ *,
58
+ a_to_b: ta.Callable[[KA], KB] | None = None,
59
+ b_to_a: ta.Callable[[KB], KA] | None = None,
60
+ ) -> None:
61
+ super().__init__(
62
+ u,
63
+ a_to_b=a_to_b,
64
+ b_to_a=b_to_a,
65
+ )
66
+
67
+ _u: MutableKv[KB, V]
68
+
69
+ def __setitem__(self, k: KA, v: V, /) -> None:
70
+ fn = check.not_none(self._a_to_b)
71
+ self._u[fn(k)] = v
72
+
73
+ def __delitem__(self, k: KA, /) -> None:
74
+ fn = check.not_none(self._a_to_b)
75
+ del self._u[fn(k)]
76
+
77
+
78
+ ##
79
+
80
+
81
+ class ValueTransformedKv(WrapperKv[K, VA], ta.Generic[K, VA, VB]):
82
+ def __init__(
83
+ self,
84
+ u: Kv[K, VB],
85
+ b_to_a: ta.Callable[[VB], VA] | None = None,
86
+ ) -> None:
87
+ super().__init__()
88
+
89
+ self._u = u
90
+ self._b_to_a = b_to_a
91
+
92
+ def underlying(self) -> ta.Sequence[Kv]:
93
+ return [self._u]
94
+
95
+ def __getitem__(self, k: K, /) -> VA:
96
+ fn = check.not_none(self._b_to_a)
97
+ return fn(self._u[k])
98
+
99
+ def __len__(self) -> int:
100
+ return len(self._u)
101
+
102
+ def items(self) -> ta.Iterator[tuple[K, VA]]:
103
+ fn = check.not_none(self._b_to_a)
104
+ return ((k, fn(v)) for k, v in self._u.items())
105
+
106
+
107
+ class ValueTransformedMutableKv(ValueTransformedKv[K, VA, VB], MutableKv[K, VA], ta.Generic[K, VA, VB]):
108
+ def __init__(
109
+ self,
110
+ u: MutableKv[K, VB],
111
+ *,
112
+ b_to_a: ta.Callable[[VB], VA] | None = None,
113
+ a_to_b: ta.Callable[[VA], VB] | None = None,
114
+ ) -> None:
115
+ super().__init__(u, b_to_a)
116
+
117
+ self._a_to_b = a_to_b
118
+
119
+ _u: MutableKv[K, VB]
120
+
121
+ def __setitem__(self, k: K, v: VA, /) -> None:
122
+ fn = check.not_none(self._a_to_b)
123
+ self._u[k] = fn(v)
124
+
125
+ def __delitem__(self, k: K, /) -> None:
126
+ del self._u[k]
@@ -0,0 +1,99 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from ... import lang
5
+ from .base import Kv
6
+ from .base import MutableKv
7
+
8
+
9
+ K = ta.TypeVar('K')
10
+ V = ta.TypeVar('V')
11
+
12
+ T = ta.TypeVar('T')
13
+
14
+
15
+ ##
16
+
17
+
18
+ class WrapperKv(Kv[K, V], lang.Abstract):
19
+ @abc.abstractmethod
20
+ def underlying(self) -> ta.Iterable[Kv]:
21
+ raise NotImplementedError
22
+
23
+
24
+ ##
25
+
26
+
27
+ def underlying(
28
+ root: Kv,
29
+ *,
30
+ leaves_only: bool = False,
31
+ filter: ta.Callable[[Kv], bool] | None = None, # noqa
32
+ ) -> ta.Iterator[Kv]:
33
+ def rec(c):
34
+ if isinstance(c, WrapperKv):
35
+ if not leaves_only:
36
+ yield c
37
+ for n in c.underlying():
38
+ yield from rec(n)
39
+ else:
40
+ yield c
41
+
42
+ for u in rec(root):
43
+ if filter is not None and not filter(u):
44
+ continue
45
+ yield u
46
+
47
+
48
+ def underlying_of(root: Kv, cls: type[T]) -> ta.Iterator[T]:
49
+ return underlying(root, filter=lambda c: isinstance(c, cls)) # type: ignore[return-value]
50
+
51
+
52
+ ##
53
+
54
+
55
+ class SimpleWrapperKv(WrapperKv[K, V]):
56
+ def __init__(self, u: Kv[K, V]) -> None:
57
+ super().__init__()
58
+
59
+ self._u = u
60
+
61
+ def underlying(self) -> ta.Sequence[Kv]:
62
+ return [self._u]
63
+
64
+ def __getitem__(self, k: K, /) -> V:
65
+ return self._u[k]
66
+
67
+ def __len__(self) -> int:
68
+ return len(self._u)
69
+
70
+ def items(self) -> ta.Iterator[tuple[K, V]]:
71
+ return self._u.items()
72
+
73
+
74
+ class SimpleWrapperMutableKv(SimpleWrapperKv[K, V], MutableKv[K, V]):
75
+ def __init__(self, u: MutableKv[K, V]) -> None:
76
+ super().__init__(u)
77
+
78
+ _u: MutableKv[K, V]
79
+
80
+ def __setitem__(self, k: K, v: V, /) -> None:
81
+ self._u[k] = v
82
+
83
+ def __delitem__(self, k: K, /) -> None:
84
+ del self._u[k]
85
+
86
+
87
+ ##
88
+
89
+
90
+ class UnmodifiableError(Exception):
91
+ pass
92
+
93
+
94
+ class UnmodifiableKv(SimpleWrapperKv[K, V], MutableKv[K, V]):
95
+ def __setitem__(self, k: K, v: V, /) -> None:
96
+ raise UnmodifiableError
97
+
98
+ def __delitem__(self, k: K, /) -> None:
99
+ raise UnmodifiableError
@@ -7,6 +7,9 @@ K = ta.TypeVar('K')
7
7
  V = ta.TypeVar('V')
8
8
 
9
9
 
10
+ ##
11
+
12
+
10
13
  def multikey_dict(dct: ta.Mapping[ta.Iterable[K] | K, V], *, deep: bool = False) -> dict[K, V]:
11
14
  ret = {}
12
15
  for k, v in dct.items():
@@ -4,6 +4,9 @@ import typing as ta
4
4
  T = ta.TypeVar('T')
5
5
 
6
6
 
7
+ ##
8
+
9
+
7
10
  class OrderedSet(ta.MutableSet[T]):
8
11
  def __init__(self, iterable: ta.Iterable[T] | None = None) -> None:
9
12
  super().__init__()
@@ -6,6 +6,9 @@ K = ta.TypeVar('K')
6
6
  V = ta.TypeVar('V')
7
7
 
8
8
 
9
+ ##
10
+
11
+
9
12
  class PersistentMap(ta.Generic[K, V], abc.ABC):
10
13
  @abc.abstractmethod
11
14
  def __len__(self) -> int:
@@ -21,7 +21,11 @@ import typing as ta
21
21
 
22
22
 
23
23
  T = ta.TypeVar('T')
24
- Comparer = ta.Callable[[T, T], int]
24
+
25
+ Comparer: ta.TypeAlias = ta.Callable[[T, T], int]
26
+
27
+
28
+ ##
25
29
 
26
30
 
27
31
  class TreapNode(ta.Generic[T]):
@@ -28,6 +28,9 @@ K = ta.TypeVar('K')
28
28
  V = ta.TypeVar('V')
29
29
 
30
30
 
31
+ ##
32
+
33
+
31
34
  class TreapMap(PersistentMap[K, V]):
32
35
  __slots__ = ('_n', '_c')
33
36
 
@@ -10,6 +10,9 @@ K = ta.TypeVar('K')
10
10
  V = ta.TypeVar('V')
11
11
 
12
12
 
13
+ ##
14
+
15
+
13
16
  class SortedCollection(lang.Abstract, ta.Collection[T]):
14
17
  Comparator = ta.Callable[[U, U], int]
15
18
 
@@ -8,6 +8,9 @@ K = ta.TypeVar('K')
8
8
  V = ta.TypeVar('V')
9
9
 
10
10
 
11
+ ##
12
+
13
+
11
14
  class Unmodifiable(lang.Abstract):
12
15
  pass
13
16
 
@@ -147,7 +147,7 @@ class InitBuilder:
147
147
  body_lines.append(f'if not {cn}({cas}): __dataclass_raise_validation_error__({self._self_name}, {cn})')
148
148
 
149
149
  inits = self._info.merged_metadata.get(Init, [])
150
- mro_dct = lang.build_mro_dict(self._info.cls)
150
+ mro_dct = lang.mro_dict(self._info.cls)
151
151
  mro_v_ids = set(map(id, mro_dct.values()))
152
152
  props_by_fget_id = {id(v.fget): v for v in mro_dct.values() if isinstance(v, property) and v.fget is not None}
153
153
  for i, obj in enumerate(inits):
@@ -78,7 +78,7 @@ class Method:
78
78
  def build_attr_dispatcher(self, instance_cls: type, owner_cls: type | None = None) -> Dispatcher[str]:
79
79
  disp: Dispatcher[str] = Dispatcher()
80
80
 
81
- mro_dct = lang.build_mro_dict(instance_cls, owner_cls)
81
+ mro_dct = lang.mro_dict(instance_cls, owner_cls)
82
82
  seen: ta.Mapping[ta.Any, str] = {}
83
83
  for nam, att in mro_dct.items():
84
84
  try:
omlish/lang/__init__.py CHANGED
@@ -140,6 +140,8 @@ from .functions import ( # noqa
140
140
  isinstance_of,
141
141
  issubclass_of,
142
142
  maybe_call,
143
+ new_function,
144
+ new_function_kwargs,
143
145
  opt_coalesce,
144
146
  opt_fn,
145
147
  opt_kw,
@@ -147,6 +149,7 @@ from .functions import ( # noqa
147
149
  raise_,
148
150
  raising,
149
151
  recurse,
152
+ strict_constant,
150
153
  try_,
151
154
  void,
152
155
  )
@@ -202,10 +205,11 @@ from .objects import ( # noqa
202
205
  anon_object,
203
206
  arg_repr,
204
207
  attr_repr,
205
- build_mro_dict,
206
208
  can_weakref,
207
209
  deep_subclasses,
208
210
  dir_dict,
211
+ mro_dict,
212
+ mro_owner_dict,
209
213
  new_type,
210
214
  opt_repr,
211
215
  super_meta,
@@ -3,7 +3,6 @@ import functools
3
3
  import typing as ta
4
4
 
5
5
  from .abstract import Abstract
6
- from .abstract import is_abstract
7
6
 
8
7
 
9
8
  ##
@@ -25,7 +24,6 @@ class Final(Abstract):
25
24
  def __init_subclass__(cls, **kwargs: ta.Any) -> None:
26
25
  super().__init_subclass__(**kwargs)
27
26
 
28
- abstracts: set[ta.Any] = set()
29
27
  for base in cls.__bases__:
30
28
  if base is Abstract:
31
29
  raise FinalTypeError(base)
@@ -33,16 +31,6 @@ class Final(Abstract):
33
31
  continue
34
32
  elif Final in base.__mro__:
35
33
  raise FinalTypeError(base)
36
- else:
37
- abstracts.update(getattr(base, '__abstractmethods__', []))
38
-
39
- for a in abstracts:
40
- try:
41
- v = cls.__dict__[a]
42
- except KeyError:
43
- raise FinalTypeError(a) from None
44
- if is_abstract(v):
45
- raise FinalTypeError(a)
46
34
 
47
35
 
48
36
  ##
omlish/lang/functions.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import dataclasses as dc
2
2
  import functools
3
3
  import time
4
+ import types
4
5
  import typing as ta
5
6
 
6
7
 
@@ -92,16 +93,29 @@ def opt_fn(fn: ta.Callable[[F], T]) -> ta.Callable[[F | None], T | None]:
92
93
  return inner
93
94
 
94
95
 
95
- class constant(ta.Generic[T]): # noqa
96
+ ##
97
+
98
+
99
+ class _constant(ta.Generic[T]): # noqa
96
100
  def __init__(self, obj: T) -> None:
97
101
  super().__init__()
98
102
 
99
103
  self._obj = obj
100
104
 
105
+
106
+ class constant(_constant[T]): # noqa
107
+ def __call__(self, *args: ta.Any, **kwargs: ta.Any) -> T:
108
+ return self._obj
109
+
110
+
111
+ class strict_constant(_constant[T]): # noqa
101
112
  def __call__(self) -> T:
102
113
  return self._obj
103
114
 
104
115
 
116
+ ##
117
+
118
+
105
119
  def is_none(o: ta.Any) -> bool:
106
120
  return o is None
107
121
 
@@ -226,3 +240,46 @@ def opt_coalesce(*vs: T | None) -> T | None:
226
240
 
227
241
  def opt_kw(**kwargs: ta.Any) -> dict[str, ta.Any]:
228
242
  return {k: v for k, v in kwargs.items() if v is not None}
243
+
244
+
245
+ ##
246
+
247
+
248
+ def new_function(
249
+ # a code object
250
+ code: types.CodeType,
251
+
252
+ # the globals dictionary
253
+ globals: dict, # noqa
254
+
255
+ # a string that overrides the name from the code object
256
+ name: str | None = None,
257
+
258
+ # a tuple that specifies the default argument values
259
+ argdefs: tuple | None = None,
260
+
261
+ # a tuple that supplies the bindings for free variables
262
+ closure: tuple | None = None,
263
+
264
+ # # a dictionary that specifies the default keyword argument values
265
+ # kwdefaults: dict | None = None,
266
+ ) -> types.FunctionType:
267
+ return types.FunctionType(
268
+ code=code,
269
+ globals=globals,
270
+ name=name,
271
+ argdefs=argdefs,
272
+ closure=closure,
273
+ # kwdefaults=kwdefaults,
274
+ )
275
+
276
+
277
+ def new_function_kwargs(f: types.FunctionType) -> dict[str, ta.Any]:
278
+ return dict(
279
+ code=f.__code__,
280
+ globals=f.__globals__, # noqa
281
+ name=f.__name__,
282
+ argdefs=f.__defaults__,
283
+ closure=f.__closure__,
284
+ # kwdefaults=f.__kwdefaults__,
285
+ )
omlish/lang/objects.py CHANGED
@@ -117,12 +117,13 @@ def deep_subclasses(
117
117
  todo.extend(reversed(cur.__subclasses__()))
118
118
 
119
119
 
120
- def build_mro_dict(
120
+ def mro_owner_dict(
121
121
  instance_cls: type,
122
122
  owner_cls: type | None = None,
123
123
  *,
124
124
  bottom_up_key_order: bool = False,
125
- ) -> ta.Mapping[str, ta.Any]:
125
+ sort_keys: bool = False,
126
+ ) -> ta.Mapping[str, tuple[type, ta.Any]]:
126
127
  if owner_cls is None:
127
128
  owner_cls = instance_cls
128
129
 
@@ -132,20 +133,41 @@ def build_mro_dict(
132
133
  except ValueError:
133
134
  raise TypeError(f'Owner class {owner_cls} not in mro of instance class {instance_cls}') from None
134
135
 
135
- dct: dict[str, ta.Any] = {}
136
+ dct: dict[str, tuple[type, ta.Any]] = {}
136
137
  if not bottom_up_key_order:
137
138
  for cur_cls in mro[:pos + 1][::-1]:
138
139
  for k, v in cur_cls.__dict__.items():
139
140
  if k not in dct:
140
- dct[k] = v
141
+ dct[k] = (cur_cls, v)
141
142
 
142
143
  else:
143
144
  for cur_cls in mro[:pos + 1]:
144
- dct.update(cur_cls.__dict__)
145
+ dct.update({k: (cur_cls, v) for k, v in cur_cls.__dict__.items()})
146
+
147
+ if sort_keys:
148
+ dct = dict(sorted(dct.items(), key=lambda t: t[0]))
145
149
 
146
150
  return dct
147
151
 
148
152
 
153
+ def mro_dict(
154
+ instance_cls: type,
155
+ owner_cls: type | None = None,
156
+ *,
157
+ bottom_up_key_order: bool = False,
158
+ sort_keys: bool = False,
159
+ ) -> ta.Mapping[str, ta.Any]:
160
+ return {
161
+ k: v
162
+ for k, (o, v) in mro_owner_dict(
163
+ instance_cls,
164
+ owner_cls,
165
+ bottom_up_key_order=bottom_up_key_order,
166
+ sort_keys=sort_keys,
167
+ ).items()
168
+ }
169
+
170
+
149
171
  def dir_dict(o: ta.Any) -> dict[str, ta.Any]:
150
172
  return {
151
173
  a: getattr(o, a)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev265
3
+ Version: 0.0.0.dev267
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -39,10 +39,10 @@ Requires-Dist: pymysql~=1.1; extra == "all"
39
39
  Requires-Dist: aiomysql~=0.2; extra == "all"
40
40
  Requires-Dist: aiosqlite~=0.21; extra == "all"
41
41
  Requires-Dist: asyncpg~=0.30; extra == "all"
42
- Requires-Dist: apsw~=3.47; extra == "all"
43
- Requires-Dist: sqlean.py~=3.45; extra == "all"
42
+ Requires-Dist: apsw~=3.49; extra == "all"
43
+ Requires-Dist: sqlean.py~=3.47; extra == "all"
44
44
  Requires-Dist: duckdb~=1.2; extra == "all"
45
- Requires-Dist: pytest~=8.0; extra == "all"
45
+ Requires-Dist: pytest~=8.3; extra == "all"
46
46
  Requires-Dist: anyio~=4.9; extra == "all"
47
47
  Requires-Dist: sniffio~=1.3; extra == "all"
48
48
  Requires-Dist: asttokens~=3.0; extra == "all"
@@ -85,11 +85,11 @@ Requires-Dist: pymysql~=1.1; extra == "sqldrivers"
85
85
  Requires-Dist: aiomysql~=0.2; extra == "sqldrivers"
86
86
  Requires-Dist: aiosqlite~=0.21; extra == "sqldrivers"
87
87
  Requires-Dist: asyncpg~=0.30; extra == "sqldrivers"
88
- Requires-Dist: apsw~=3.47; extra == "sqldrivers"
89
- Requires-Dist: sqlean.py~=3.45; extra == "sqldrivers"
88
+ Requires-Dist: apsw~=3.49; extra == "sqldrivers"
89
+ Requires-Dist: sqlean.py~=3.47; extra == "sqldrivers"
90
90
  Requires-Dist: duckdb~=1.2; extra == "sqldrivers"
91
91
  Provides-Extra: testing
92
- Requires-Dist: pytest~=8.0; extra == "testing"
92
+ Requires-Dist: pytest~=8.3; extra == "testing"
93
93
  Provides-Extra: plus
94
94
  Requires-Dist: anyio~=4.9; extra == "plus"
95
95
  Requires-Dist: sniffio~=1.3; extra == "plus"
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=x26AIwDzScUvnX-p4xlq6Zc5QYrAo0Vmgf1qHc1KL_M,8253
2
- omlish/__about__.py,sha256=mUc6xs3AcgIXA_LmHEaA24dsIsYHNDRy7m0iT9wQ9og,3380
2
+ omlish/__about__.py,sha256=ka6y6PMiRUbqY3l0xTavDrpeKm2OK0Im3dJU_twVSEY,3380
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
@@ -143,29 +143,36 @@ omlish/codecs/funcs.py,sha256=p4imNt7TobyZVXWC-WhntHVu9KfJrO4QwdtPRh-cVOk,850
143
143
  omlish/codecs/registry.py,sha256=2FnO5YP7ui1LzkguwESY0MP3WIdwgPTIJTM_4RyTOEg,3896
144
144
  omlish/codecs/standard.py,sha256=eiZ4u9ep0XrA4Z_D1zJI0vmWyuN8HLrX4Se_r_Cq_ZM,60
145
145
  omlish/codecs/text.py,sha256=JzrdwMpQPo2NBBg3K1EZszzQy5vEWmd82SIerJd4yeQ,5723
146
- omlish/collections/__init__.py,sha256=fAGCii4OttPRee9q4AD-IfQpdsmoCdgPwYUMPgnJwCs,2140
147
- omlish/collections/abc.py,sha256=sP7BpTVhx6s6C59mTFeosBi4rHOWC6tbFBYbxdZmvh0,2365
148
- omlish/collections/coerce.py,sha256=g68ROb_-5HgH-vI8612mU2S0FZ8-wp2ZHK5_Zy_kVC0,7037
146
+ omlish/collections/__init__.py,sha256=vWVm-M5WsX8S9xw9q67Jv4FKCE1GW6JMUNrUVq5pxWU,2238
147
+ omlish/collections/abc.py,sha256=ikTJlJ5dhXjU6tlNsI0Wm0_7GaIEpe3mftpvdGY_nc8,2620
148
+ omlish/collections/coerce.py,sha256=tAls15v_7p5bUN33R7Zbko87KW5toWHl9fRialCqyNY,7030
149
149
  omlish/collections/exceptions.py,sha256=shcS-NCnEUudF8qC_SmO2TQyjivKlS4TDjaz_faqQ0c,44
150
- omlish/collections/frozen.py,sha256=jQppK1pyQ3e_aAvw8OEKfnr7b0OB4RI5Qr1g9xXTZaQ,4137
151
- omlish/collections/hasheq.py,sha256=SQdVICLZWKkYu4vUXrfmWBXO3i-jx01iM9IInDWkKfU,3664
152
- omlish/collections/identity.py,sha256=1kdiByfzKHGQZgUg1vkwILt8oPPQgerGh0_HbLDdqKw,2835
153
- omlish/collections/mappings.py,sha256=fCHQatlAstiZkWZiyIlOw637Yep7ce79EPPbJcWHHUA,2784
154
- omlish/collections/ordered.py,sha256=tUAl99XHbSbzn7Hdh99jUBl27NcC2J7ZTI67slTMe5M,2333
150
+ omlish/collections/frozen.py,sha256=LMbAHYDENIQk1hvjCTvpnx66m1TalrHa4CSn8n_tsXQ,4142
151
+ omlish/collections/hasheq.py,sha256=swOBPEnU_C0SU3VqWJX9mr0BfZLD0A-4Ke9Vahj3fE4,3669
152
+ omlish/collections/identity.py,sha256=32c1w-90OjwP9FlD-66yp4h_Y7cLfTmEUgp-MQdL8T8,2840
153
+ omlish/collections/mappings.py,sha256=u0UrB550nBM_RNXQV0YnBTbRZEWrplZe9ZxcCN3H65M,2789
154
+ omlish/collections/ordered.py,sha256=7zTbrAt12rf6i33XHkQERKar258fJacaw_WbtGEBgWo,2338
155
155
  omlish/collections/ranked.py,sha256=rg6DL36oOUiG5JQEAkGnT8b6f9mSndQlIovtt8GQj_w,2229
156
- omlish/collections/unmodifiable.py,sha256=-zys__n6L7liWzhmHAIvfxprq7cUE5HoR3foGvXc_7I,4748
156
+ omlish/collections/unmodifiable.py,sha256=X7kKhPFdZF4m28SfLDxZL-riWlhbZffdPv35aTP30YM,4753
157
157
  omlish/collections/utils.py,sha256=Q0lHhNDokVxdOvApmu1QX5fABYwbn1ATiIwp194Ur_E,2889
158
158
  omlish/collections/cache/__init__.py,sha256=D1gO71VcwxFTZP9gAc9isHfg_TEdalwhsJcgGLvS9hg,233
159
- omlish/collections/cache/descriptor.py,sha256=aa-OOChFAJLMPHjuc8YPCvVsE0INntPxxXoq-kl4jtg,5021
160
- omlish/collections/cache/impl.py,sha256=ySRU9UJG7jH9VPvuXdwZQ_rSqrleY-1mtie5Ml738wY,14755
161
- omlish/collections/cache/types.py,sha256=yNjwd6CGyTJQdxN2CQxFqqBAlcs1Z7vvNV-aU1K7p8E,685
159
+ omlish/collections/cache/descriptor.py,sha256=F9aRsF-xOUcNMzTwIWrUpKTjop1Z-oItQqJDwVaR0FU,5026
160
+ omlish/collections/cache/impl.py,sha256=Y18OcAsNL6dIWuk89UlZBpqq0iBU-P4VDio6eis43Us,14760
161
+ omlish/collections/cache/types.py,sha256=uND_qOk8bVVmdhrOhjx9QHYqs2jq53NThEqQAl3Nepw,690
162
+ omlish/collections/kv/__init__.py,sha256=qPuE8bmbyOkT_qVGH5owSp0SbC9xI_p_LS0tP7S7QSw,751
163
+ omlish/collections/kv/base.py,sha256=QDAwnWQFnyfWoZB0rlSTvfO-m-YED9MBi5nojDt8n-g,1085
164
+ omlish/collections/kv/capabilities.py,sha256=ZINohQKPuUGJNbUnwm6CExMoCKrOcftrUWzFF0xlSww,752
165
+ omlish/collections/kv/filtered.py,sha256=EJS885-skKEilRy9noblTUU_4RY04jIYet9OMDQwQPo,2266
166
+ omlish/collections/kv/mappings.py,sha256=Y67h6mY4MpBfOUXZCyW_Gi7xuiAzTq7KzB4qIldqG10,1615
167
+ omlish/collections/kv/transformed.py,sha256=2ge9RTqTCA6ftWn4twgFjHokg4zNzHnKCh9cclblHE0,3046
168
+ omlish/collections/kv/wrappers.py,sha256=nUtoiArK1Fu2TgxFrqZU69bEoAxKJ_nA7qMeeihIz3U,1985
162
169
  omlish/collections/persistent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
163
- omlish/collections/persistent/persistent.py,sha256=KG471s0bhhReQrjlmX0xaN9HeAIcrtT264ddZCxsExo,875
164
- omlish/collections/persistent/treap.py,sha256=A09ZPacGyJlyRB-Wi4TNj3tE0w-RpFNliPgpDaa6Vwg,7719
165
- omlish/collections/persistent/treapmap.py,sha256=TxOM-ZRF5PK2xe5wRIhESNt7DGh9b_MeZfE7HLkCOs4,5804
170
+ omlish/collections/persistent/persistent.py,sha256=6CuzeZjZMqBLflU-CuWu32SrtZXFrJOV-H_UUuYoTkg,880
171
+ omlish/collections/persistent/treap.py,sha256=o7vhnn8kHde_Plk0sojlJZkkKwp8hpj2IekhcvbYqHs,7739
172
+ omlish/collections/persistent/treapmap.py,sha256=dBCZHouClUhvUBnSR5k97AAu09EQVRWdUOwwc1CHPmg,5809
166
173
  omlish/collections/sorted/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
174
  omlish/collections/sorted/skiplist.py,sha256=tybcD8OslDBCc86Z1qKb4GRkbhMY26qorPzPIeqFmKk,6031
168
- omlish/collections/sorted/sorted.py,sha256=euHJan3FqTYSCJGsVcYYRV-yhAAQ5_htnjymnNoVHRE,3319
175
+ omlish/collections/sorted/sorted.py,sha256=UhjJce7ulO_FUB6dFOhKpEg9Bcgxr2m6VXeCNtbLjSM,3324
169
176
  omlish/concurrent/__init__.py,sha256=9p-s8MvBEYDqHIoYU3OYoe-Nni22QdkW7nhZGEukJTM,197
170
177
  omlish/concurrent/executors.py,sha256=mF-rjJWzNFxwB1-_H7rHuwoImpl4FtNM6W3wcqM3NEE,1291
171
178
  omlish/concurrent/futures.py,sha256=870tx8ELI8THvMnTrQoYIlEFKO9hM4KUrlehckJqKBU,4238
@@ -207,7 +214,7 @@ omlish/dataclasses/impl/exceptions.py,sha256=-vqxZmfXVflymVuiM553XTlJProse5HEMkt
207
214
  omlish/dataclasses/impl/fields.py,sha256=jM2Rvu6DQOfRUrZBMOeJMda-CT5JKXQvJKzoIU_LFxc,6897
208
215
  omlish/dataclasses/impl/frozen.py,sha256=x87DSM8FIMZ3c_BIUE8NooCkExFjPsabeqIueEP5qKs,2988
209
216
  omlish/dataclasses/impl/hashing.py,sha256=0Gr6XIRkKy4pr-mdHblIlQCy3mBxycjMqJk3oZDw43s,3215
210
- omlish/dataclasses/impl/init.py,sha256=drt_-697uw2xp0FGj9AYlMbiuSfYRNV3-8JxTPzkP_w,6415
217
+ omlish/dataclasses/impl/init.py,sha256=CUM8Gnx171D3NO6FN4mlrIBoTcYiDqj_tqE9_NKKicg,6409
211
218
  omlish/dataclasses/impl/internals.py,sha256=UvZYjrLT1S8ntyxJ_vRPIkPOF00K8HatGAygErgoXTU,2990
212
219
  omlish/dataclasses/impl/main.py,sha256=LyWr8IBfoL-bBfweR4OqJgi842REDw20WRYcGSYNfMg,2577
213
220
  omlish/dataclasses/impl/metaclass.py,sha256=Mfr_6_TR_inpH2GIkOtQDKSEwF4mhY-cnUiNBYpO25s,5252
@@ -245,7 +252,7 @@ omlish/dispatch/_dispatch3.py,sha256=9Zjd7bINAC3keiaBdssc4v5dY0-8OI6XooV2DR9U7Z0
245
252
  omlish/dispatch/dispatch.py,sha256=KA5l49AiGLRjp4J7RDJW9RiDp9WUD1ewR1AOPEF8g38,3062
246
253
  omlish/dispatch/functions.py,sha256=8Qvj62XKn9SKfiqoVQdBD3wVRE4JUWpZDqs0oouuDIw,1519
247
254
  omlish/dispatch/impls.py,sha256=JP67zSvDWG4XFOmKPrhWHxRV9WnyAPAsjQHvbmEJh4c,2136
248
- omlish/dispatch/methods.py,sha256=dr8xQo-zVRckIo_V2Wp8Reqor3NE6APuzomUfsSBGdk,5498
255
+ omlish/dispatch/methods.py,sha256=oFtKljPnTMG0DVUBdEkf81-0RzEbgHhS4J_63HYJfKU,5492
249
256
  omlish/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
257
  omlish/docker/all.py,sha256=xXRgJgLGPwAtr7bDMJ_Dp9jTfOwfGvohNhc6LsoELJc,514
251
258
  omlish/docker/cli.py,sha256=gtb9kitVfGnd4cr587NsVVk8D5Ok5y5SAsqD_SwGrSA,2565
@@ -408,7 +415,7 @@ omlish/iterators/iterators.py,sha256=iTQQwBE6Wzoy36dnbPIws17zbjE3zNN4KwVw4Fzh-gY
408
415
  omlish/iterators/recipes.py,sha256=53mkexitMhkwXQZbL6DrhpT0WePQ_56uXd5Jaw3DfzI,467
409
416
  omlish/iterators/tools.py,sha256=Pi4ybXytUXVZ3xwK89xpPImQfYYId9p1vIFQvVqVLqA,2551
410
417
  omlish/iterators/unique.py,sha256=0jAX3kwzVfRNhe0Tmh7kVP_Q2WBIn8POo_O-rgFV0rQ,1390
411
- omlish/lang/__init__.py,sha256=aSU-1zjUxrLH-3FPpogKIxPBfOMiCzC9TOKRBajo1fA,5093
418
+ omlish/lang/__init__.py,sha256=ZRoUfTeSvMWFvXPeHwhncOkopoIDQ8Rml1zM4hp07Fc,5171
412
419
  omlish/lang/attrs.py,sha256=fofCKN0X8TMu1yGqHpLpNLih9r9HWl3D3Vn3b6O791w,3891
413
420
  omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
414
421
  omlish/lang/collections.py,sha256=aGi0j6VzVe2nz4l357Y4RD5_XNl8OJbmM5qM6BclrrY,1895
@@ -417,12 +424,12 @@ omlish/lang/contextmanagers.py,sha256=UPH6daYwSP9cH5AfSVsJyEHk1UURMGhVPM5ZRhp_Hv
417
424
  omlish/lang/datetimes.py,sha256=ehI_DhQRM-bDxAavnp470XcekbbXc4Gdw9y1KpHDJT0,223
418
425
  omlish/lang/descriptors.py,sha256=zBtgO9LjdSTGHNUgiIqswh78WOVoGH6KzS0NbgB1Wls,6572
419
426
  omlish/lang/exceptions.py,sha256=qJBo3NU1mOWWm-NhQUHCY5feYXR3arZVyEHinLsmRH4,47
420
- omlish/lang/functions.py,sha256=RbUt10UjDj95CvdCDtEC5F_xrEmbsPk1YPKjIg4S5Jc,4508
427
+ omlish/lang/functions.py,sha256=kSdVUJZmRcncMdU43rcQLZ5E2NMcRz6X6pppwLNHiWk,5762
421
428
  omlish/lang/generators.py,sha256=5LX17j-Ej3QXhwBgZvRTm_dq3n9veC4IOUcVmvSu2vU,5243
422
429
  omlish/lang/imports.py,sha256=Gdl6xCF89xiMOE1yDmdvKWamLq8HX-XPianO58Jdpmw,9218
423
430
  omlish/lang/iterables.py,sha256=HOjcxOwyI5bBApDLsxRAGGhTTmw7fdZl2kEckxRVl-0,1994
424
431
  omlish/lang/maybes.py,sha256=dAgrUoAhCgyrHRqa73CkaGnpXwGc-o9n-NIThrNXnbU,3416
425
- omlish/lang/objects.py,sha256=WlpOJv7kN7GiIquzcd4VEKjRlHmGAKt7yYnHaQL-2QQ,5297
432
+ omlish/lang/objects.py,sha256=5SFF6bf7QQpp1Hju01ITWRsM9q2J3hlePqprPDmfXdI,5910
426
433
  omlish/lang/outcomes.py,sha256=mpFy_VoM-b74L1aCFsjsZVUHx_icZ1AHMOKeVesjOp4,8628
427
434
  omlish/lang/params.py,sha256=QmNVBfJsfxjDG5ilDPgHV7sK4UwRztkSQdLTo0umb8I,6648
428
435
  omlish/lang/resolving.py,sha256=OuN2mDTPNyBUbcrswtvFKtj4xgH4H4WglgqSKv3MTy0,1606
@@ -435,7 +442,7 @@ omlish/lang/cached/function.py,sha256=3AeTVfpzovMMWbnjFuT5mM7kT1dBuk7fa66FOJKikY
435
442
  omlish/lang/cached/property.py,sha256=kzbao_35PlszdK_9oJBWrMmFFlVK_Xhx7YczHhTJ6cc,2764
436
443
  omlish/lang/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
437
444
  omlish/lang/classes/abstract.py,sha256=bIcuAetV_aChhpSURypmjjcqP07xi20uVYPKh1kvQNU,3710
438
- omlish/lang/classes/restrict.py,sha256=QvM-GqXvO8vpCONkcr0QpgVPfzZmgDo7o8d9kUwOzlo,3941
445
+ omlish/lang/classes/restrict.py,sha256=nCsQuSFsKTwLhYfmwZr9af00qdVA8TuPQXaSJQNKzBI,3543
439
446
  omlish/lang/classes/simple.py,sha256=XQ8b86WvQA0qtSYqlbMOJS7tHgE8sv9onda33uQmbkM,3294
440
447
  omlish/lang/classes/virtual.py,sha256=z0MYQD9Q5MkX8DzF325wDB4J9XoYbsB09jZ1omC62To,3366
441
448
  omlish/lifecycles/__init__.py,sha256=1FjYceXs-4fc-S-C9zFYmc2axHs4znnQHcJVHdY7a6E,578
@@ -768,9 +775,9 @@ omlish/text/parts.py,sha256=Q9NvoyEGQKIWgiPD4D_Qc66cWAuyEKE033dT9m7c3Wk,6662
768
775
  omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
769
776
  omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
770
777
  omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
771
- omlish-0.0.0.dev265.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
772
- omlish-0.0.0.dev265.dist-info/METADATA,sha256=bfiaKjcUegKuHHiSKfGvlXXvdg9KKeuO3T_2-rfv6p8,4198
773
- omlish-0.0.0.dev265.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
774
- omlish-0.0.0.dev265.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
775
- omlish-0.0.0.dev265.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
776
- omlish-0.0.0.dev265.dist-info/RECORD,,
778
+ omlish-0.0.0.dev267.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
779
+ omlish-0.0.0.dev267.dist-info/METADATA,sha256=An6CgJ82eAUmeEV7QAbzuOZ3-1aVeUJgyCzald60rNM,4198
780
+ omlish-0.0.0.dev267.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
781
+ omlish-0.0.0.dev267.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
782
+ omlish-0.0.0.dev267.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
783
+ omlish-0.0.0.dev267.dist-info/RECORD,,