omlish 0.0.0.dev1__py3-none-any.whl → 0.0.0.dev3__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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/__about__.py +2 -3
- omlish/argparse.py +8 -8
- omlish/asyncs/__init__.py +2 -2
- omlish/asyncs/anyio.py +64 -1
- omlish/asyncs/asyncs.py +1 -3
- omlish/asyncs/futures.py +16 -15
- omlish/c3.py +5 -5
- omlish/check.py +8 -8
- omlish/collections/__init__.py +98 -63
- omlish/collections/_abc.py +2 -0
- omlish/collections/_io_abc.py +4 -2
- omlish/collections/cache/__init__.py +1 -1
- omlish/collections/cache/descriptor.py +12 -12
- omlish/collections/cache/impl.py +27 -20
- omlish/collections/cache/types.py +1 -1
- omlish/collections/coerce.py +44 -44
- omlish/collections/frozen.py +9 -9
- omlish/collections/identity.py +4 -5
- omlish/collections/mappings.py +5 -5
- omlish/collections/ordered.py +8 -8
- omlish/collections/skiplist.py +7 -7
- omlish/collections/sorted.py +4 -4
- omlish/collections/treap.py +42 -17
- omlish/collections/treapmap.py +59 -7
- omlish/collections/unmodifiable.py +25 -24
- omlish/collections/utils.py +1 -1
- omlish/configs/flattening.py +8 -7
- omlish/configs/props.py +3 -3
- omlish/dataclasses/__init__.py +1 -1
- omlish/dataclasses/impl/__init__.py +18 -0
- omlish/dataclasses/impl/api.py +15 -24
- omlish/dataclasses/impl/as_.py +4 -4
- omlish/dataclasses/impl/exceptions.py +1 -1
- omlish/dataclasses/impl/fields.py +8 -8
- omlish/dataclasses/impl/frozen.py +2 -2
- omlish/dataclasses/impl/init.py +6 -6
- omlish/dataclasses/impl/internals.py +16 -1
- omlish/dataclasses/impl/main.py +4 -4
- omlish/dataclasses/impl/metaclass.py +2 -2
- omlish/dataclasses/impl/metadata.py +1 -1
- omlish/dataclasses/impl/order.py +2 -2
- omlish/dataclasses/impl/params.py +4 -38
- omlish/dataclasses/impl/reflect.py +1 -7
- omlish/dataclasses/impl/replace.py +1 -1
- omlish/dataclasses/impl/repr.py +24 -6
- omlish/dataclasses/impl/simple.py +2 -2
- omlish/dataclasses/impl/slots.py +2 -2
- omlish/dataclasses/impl/utils.py +7 -7
- omlish/defs.py +13 -17
- omlish/diag/procfs.py +334 -0
- omlish/diag/ps.py +47 -0
- omlish/{replserver → diag/replserver}/console.py +26 -28
- omlish/{replserver → diag/replserver}/server.py +12 -12
- omlish/dispatch/dispatch.py +14 -16
- omlish/dispatch/functions.py +1 -1
- omlish/dispatch/methods.py +6 -7
- omlish/docker.py +8 -6
- omlish/dynamic.py +13 -13
- omlish/fnpairs.py +311 -0
- omlish/graphs/dot/items.py +1 -1
- omlish/graphs/trees.py +25 -31
- omlish/inject/__init__.py +7 -7
- omlish/inject/elements.py +2 -2
- omlish/inject/exceptions.py +8 -8
- omlish/inject/impl/elements.py +4 -4
- omlish/inject/impl/injector.py +6 -6
- omlish/inject/impl/inspect.py +3 -3
- omlish/inject/impl/scopes.py +9 -9
- omlish/inject/injector.py +1 -1
- omlish/inject/providers.py +2 -2
- omlish/inject/proxy.py +5 -5
- omlish/iterators.py +62 -26
- omlish/json.py +7 -6
- omlish/lang/__init__.py +172 -112
- omlish/lang/cached.py +15 -10
- omlish/lang/classes/__init__.py +35 -24
- omlish/lang/classes/abstract.py +3 -3
- omlish/lang/classes/restrict.py +14 -14
- omlish/lang/classes/simple.py +2 -2
- omlish/lang/classes/virtual.py +5 -5
- omlish/lang/clsdct.py +2 -2
- omlish/lang/cmp.py +2 -2
- omlish/lang/contextmanagers.py +31 -25
- omlish/lang/datetimes.py +1 -1
- omlish/lang/descriptors.py +51 -6
- omlish/lang/exceptions.py +2 -0
- omlish/lang/functions.py +101 -35
- omlish/lang/imports.py +25 -30
- omlish/lang/iterables.py +2 -2
- omlish/lang/maybes.py +2 -1
- omlish/lang/objects.py +17 -11
- omlish/lang/resolving.py +1 -1
- omlish/lang/strings.py +1 -1
- omlish/lang/timeouts.py +53 -0
- omlish/lang/typing.py +5 -5
- omlish/libc.py +15 -11
- omlish/logs/_abc.py +5 -1
- omlish/logs/filters.py +2 -0
- omlish/logs/formatters.py +6 -2
- omlish/logs/utils.py +1 -1
- omlish/marshal/base.py +9 -9
- omlish/marshal/dataclasses.py +2 -2
- omlish/marshal/enums.py +2 -2
- omlish/marshal/exceptions.py +1 -1
- omlish/marshal/factories.py +10 -10
- omlish/marshal/global_.py +10 -4
- omlish/marshal/iterables.py +2 -2
- omlish/marshal/mappings.py +2 -2
- omlish/marshal/objects.py +1 -2
- omlish/marshal/optionals.py +4 -4
- omlish/marshal/polymorphism.py +4 -4
- omlish/marshal/registries.py +3 -3
- omlish/marshal/standard.py +6 -6
- omlish/marshal/utils.py +3 -3
- omlish/marshal/values.py +1 -1
- omlish/math.py +9 -9
- omlish/os.py +13 -4
- omlish/reflect.py +5 -15
- omlish/sql/__init__.py +0 -0
- omlish/sql/_abc.py +65 -0
- omlish/sql/dbs.py +90 -0
- omlish/stats.py +7 -8
- omlish/term.py +1 -1
- omlish/testing/pydevd.py +30 -12
- omlish/testing/pytest/inject/__init__.py +7 -0
- omlish/testing/pytest/inject/harness.py +24 -2
- omlish/testing/pytest/plugins/__init__.py +1 -1
- omlish/testing/pytest/plugins/pydevd.py +12 -0
- omlish/testing/pytest/plugins/switches.py +3 -3
- omlish/testing/testing.py +5 -5
- omlish/text/delimit.py +3 -6
- omlish/text/parts.py +3 -3
- omlish-0.0.0.dev3.dist-info/METADATA +31 -0
- omlish-0.0.0.dev3.dist-info/RECORD +191 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/WHEEL +1 -1
- omlish/lang/classes/test/test_abstract.py +0 -89
- omlish/lang/classes/test/test_restrict.py +0 -71
- omlish/lang/classes/test/test_simple.py +0 -58
- omlish/lang/classes/test/test_virtual.py +0 -72
- omlish/testing/pytest/plugins/pycharm.py +0 -54
- omlish-0.0.0.dev1.dist-info/METADATA +0 -17
- omlish-0.0.0.dev1.dist-info/RECORD +0 -187
- /omlish/{lang/classes/test → diag}/__init__.py +0 -0
- /omlish/{replserver → diag/replserver}/__init__.py +0 -0
- /omlish/{replserver → diag/replserver}/__main__.py +0 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/top_level.txt +0 -0
omlish/collections/treap.py
CHANGED
|
@@ -16,6 +16,8 @@ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEM
|
|
|
16
16
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
17
17
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
18
18
|
"""
|
|
19
|
+
# ruff: noqa: SLF001
|
|
20
|
+
|
|
19
21
|
import typing as ta
|
|
20
22
|
|
|
21
23
|
|
|
@@ -41,6 +43,9 @@ class TreapNode(ta.Generic[T]):
|
|
|
41
43
|
self._left = _left
|
|
42
44
|
self._right = _right
|
|
43
45
|
|
|
46
|
+
def __repr__(self) -> str:
|
|
47
|
+
return f'TreapNode(value={self._value!r}, priority={self._priority!r})'
|
|
48
|
+
|
|
44
49
|
@property
|
|
45
50
|
def value(self) -> T:
|
|
46
51
|
return self._value
|
|
@@ -65,7 +70,7 @@ class TreapNode(ta.Generic[T]):
|
|
|
65
70
|
yield from self._right
|
|
66
71
|
|
|
67
72
|
|
|
68
|
-
def find(n:
|
|
73
|
+
def find(n: TreapNode[T] | None, v: T, c: Comparer[T]) -> TreapNode[T] | None:
|
|
69
74
|
while True:
|
|
70
75
|
if n is None:
|
|
71
76
|
return None
|
|
@@ -78,12 +83,32 @@ def find(n: ta.Optional[TreapNode[T]], v: T, c: Comparer[T]) -> ta.Optional[Trea
|
|
|
78
83
|
n = n._left # noqa
|
|
79
84
|
|
|
80
85
|
|
|
86
|
+
def place(n: TreapNode[T] | None, v: T, c: Comparer[T], *, desc: bool = False) -> list[TreapNode[T]]:
|
|
87
|
+
ret: list[TreapNode[T]] = []
|
|
88
|
+
while True:
|
|
89
|
+
if n is None:
|
|
90
|
+
break
|
|
91
|
+
diff = c(n._value, v) # noqa
|
|
92
|
+
if diff == 0:
|
|
93
|
+
ret.append(n)
|
|
94
|
+
break
|
|
95
|
+
elif diff < 0:
|
|
96
|
+
if desc:
|
|
97
|
+
ret.append(n)
|
|
98
|
+
n = n._right # noqa
|
|
99
|
+
else:
|
|
100
|
+
if not desc:
|
|
101
|
+
ret.append(n)
|
|
102
|
+
n = n._left # noqa
|
|
103
|
+
return ret
|
|
104
|
+
|
|
105
|
+
|
|
81
106
|
def union(
|
|
82
|
-
n:
|
|
83
|
-
other:
|
|
107
|
+
n: TreapNode[T] | None,
|
|
108
|
+
other: TreapNode[T] | None,
|
|
84
109
|
c: Comparer[T],
|
|
85
110
|
overwrite: bool,
|
|
86
|
-
) ->
|
|
111
|
+
) -> TreapNode[T] | None:
|
|
87
112
|
if n is None:
|
|
88
113
|
return other
|
|
89
114
|
if other is None:
|
|
@@ -100,13 +125,13 @@ def union(
|
|
|
100
125
|
|
|
101
126
|
|
|
102
127
|
def split(
|
|
103
|
-
n:
|
|
128
|
+
n: TreapNode[T] | None,
|
|
104
129
|
v: T,
|
|
105
130
|
c: Comparer[T],
|
|
106
131
|
) -> tuple[
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
132
|
+
TreapNode[T] | None,
|
|
133
|
+
TreapNode[T] | None,
|
|
134
|
+
TreapNode[T] | None,
|
|
110
135
|
]:
|
|
111
136
|
tmp: TreapNode[T] = TreapNode(_value=None, _priority=0, _left=None, _right=None) # type: ignore
|
|
112
137
|
leftp, rightp = [tmp, 'l'], [tmp, 'r']
|
|
@@ -120,7 +145,7 @@ def split(
|
|
|
120
145
|
else:
|
|
121
146
|
raise ValueError(p)
|
|
122
147
|
|
|
123
|
-
cur:
|
|
148
|
+
cur: TreapNode[T] | None = n
|
|
124
149
|
while True:
|
|
125
150
|
if cur is None:
|
|
126
151
|
setp(leftp, None)
|
|
@@ -146,10 +171,10 @@ def split(
|
|
|
146
171
|
|
|
147
172
|
|
|
148
173
|
def intersect(
|
|
149
|
-
n:
|
|
150
|
-
other:
|
|
174
|
+
n: TreapNode[T] | None,
|
|
175
|
+
other: TreapNode[T] | None,
|
|
151
176
|
c: Comparer[T],
|
|
152
|
-
) ->
|
|
177
|
+
) -> TreapNode[T] | None:
|
|
153
178
|
if n is None or other is None:
|
|
154
179
|
return None
|
|
155
180
|
|
|
@@ -167,12 +192,12 @@ def intersect(
|
|
|
167
192
|
return TreapNode(_value=n._value, _priority=n._priority, _left=left, _right=right)
|
|
168
193
|
|
|
169
194
|
|
|
170
|
-
def delete(n:
|
|
195
|
+
def delete(n: TreapNode[T] | None, v: T, c: Comparer[T]) -> TreapNode[T] | None:
|
|
171
196
|
left, _, right = split(n, v, c)
|
|
172
197
|
return _join(left, right)
|
|
173
198
|
|
|
174
199
|
|
|
175
|
-
def diff(n:
|
|
200
|
+
def diff(n: TreapNode[T] | None, other: TreapNode[T] | None, c: Comparer[T]) -> TreapNode[T] | None:
|
|
176
201
|
if n is None or other is None:
|
|
177
202
|
return n
|
|
178
203
|
|
|
@@ -190,8 +215,8 @@ def diff(n: ta.Optional[TreapNode[T]], other: ta.Optional[TreapNode[T]], c: Comp
|
|
|
190
215
|
return _join(left, right)
|
|
191
216
|
|
|
192
217
|
|
|
193
|
-
def _join(n:
|
|
194
|
-
result:
|
|
218
|
+
def _join(n: TreapNode[T] | None, other: TreapNode[T] | None) -> TreapNode[T] | None:
|
|
219
|
+
result: TreapNode[T] | None = None
|
|
195
220
|
resultp: list[ta.Any] = [None, None]
|
|
196
221
|
|
|
197
222
|
def setresultp(o):
|
|
@@ -206,7 +231,7 @@ def _join(n: ta.Optional[TreapNode[T]], other: ta.Optional[TreapNode[T]]) -> ta.
|
|
|
206
231
|
else:
|
|
207
232
|
raise ValueError(resultp)
|
|
208
233
|
|
|
209
|
-
cur:
|
|
234
|
+
cur: TreapNode[T] | None = n
|
|
210
235
|
while True:
|
|
211
236
|
if cur is None:
|
|
212
237
|
setresultp(other)
|
omlish/collections/treapmap.py
CHANGED
|
@@ -16,6 +16,7 @@ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEM
|
|
|
16
16
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
17
17
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
18
18
|
"""
|
|
19
|
+
import abc
|
|
19
20
|
import random
|
|
20
21
|
import typing as ta
|
|
21
22
|
|
|
@@ -33,7 +34,7 @@ class TreapMap(PersistentMap[K, V]):
|
|
|
33
34
|
def __init__(
|
|
34
35
|
self,
|
|
35
36
|
*,
|
|
36
|
-
_n:
|
|
37
|
+
_n: treap.TreapNode[tuple[K, V]] | None,
|
|
37
38
|
_c: treap.Comparer[tuple[K, V]],
|
|
38
39
|
) -> None:
|
|
39
40
|
super().__init__()
|
|
@@ -74,13 +75,38 @@ class TreapMap(PersistentMap[K, V]):
|
|
|
74
75
|
i = TreapMapIterator(
|
|
75
76
|
_st=[],
|
|
76
77
|
_n=self._n,
|
|
77
|
-
_b=False,
|
|
78
78
|
)
|
|
79
79
|
while (n := i._n) is not None and n.left is not None: # noqa
|
|
80
80
|
i._st.append(n) # noqa
|
|
81
81
|
i._n = n.left # noqa
|
|
82
82
|
return i
|
|
83
83
|
|
|
84
|
+
def iterate_from(self, k: K) -> 'TreapMapIterator[K, V]':
|
|
85
|
+
lst = treap.place(self._n, (k, None), self._c) # type: ignore
|
|
86
|
+
i = TreapMapIterator(
|
|
87
|
+
_st=lst,
|
|
88
|
+
_n=lst.pop(),
|
|
89
|
+
)
|
|
90
|
+
return i
|
|
91
|
+
|
|
92
|
+
def reverse_iterate(self) -> 'TreapMapReverseIterator[K, V]':
|
|
93
|
+
i = TreapMapReverseIterator(
|
|
94
|
+
_st=[],
|
|
95
|
+
_n=self._n,
|
|
96
|
+
)
|
|
97
|
+
while (n := i._n) is not None and n.right is not None: # noqa
|
|
98
|
+
i._st.append(n) # noqa
|
|
99
|
+
i._n = n.right # noqa
|
|
100
|
+
return i
|
|
101
|
+
|
|
102
|
+
def reverse_iterate_from(self, k: K) -> 'TreapMapReverseIterator[K, V]':
|
|
103
|
+
lst = treap.place(self._n, (k, None), self._c, desc=True) # type: ignore
|
|
104
|
+
i = TreapMapReverseIterator(
|
|
105
|
+
_st=lst,
|
|
106
|
+
_n=lst.pop(),
|
|
107
|
+
)
|
|
108
|
+
return i
|
|
109
|
+
|
|
84
110
|
def with_(self, k: K, v: V) -> 'TreapMap[K, V]':
|
|
85
111
|
node = treap.TreapNode(
|
|
86
112
|
_value=(k, v),
|
|
@@ -108,25 +134,31 @@ def new_treap_map(cmp: ta.Callable[[tuple[K, V], tuple[K, V]], int]) -> Persiste
|
|
|
108
134
|
return TreapMap(_n=None, _c=cmp)
|
|
109
135
|
|
|
110
136
|
|
|
111
|
-
class
|
|
112
|
-
__slots__ = ('_st', '_n'
|
|
137
|
+
class BaseTreapMapIterator(abc.ABC, ta.Generic[K, V]):
|
|
138
|
+
__slots__ = ('_st', '_n')
|
|
113
139
|
|
|
114
140
|
def __init__(
|
|
115
141
|
self,
|
|
116
142
|
*,
|
|
117
143
|
_st: list[treap.TreapNode[tuple[K, V]]],
|
|
118
|
-
_n:
|
|
119
|
-
_b: bool,
|
|
144
|
+
_n: treap.TreapNode[tuple[K, V]] | None,
|
|
120
145
|
) -> None:
|
|
121
146
|
super().__init__()
|
|
122
147
|
|
|
123
148
|
self._st = _st
|
|
124
149
|
self._n = _n
|
|
125
|
-
self._b = _b
|
|
126
150
|
|
|
127
151
|
def has_next(self) -> bool:
|
|
128
152
|
return self._n is not None
|
|
129
153
|
|
|
154
|
+
@abc.abstractmethod
|
|
155
|
+
def next(self) -> tuple[K, V]:
|
|
156
|
+
raise NotImplementedError
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class TreapMapIterator(BaseTreapMapIterator[K, V]):
|
|
160
|
+
__slots__ = BaseTreapMapIterator.__slots__
|
|
161
|
+
|
|
130
162
|
def next(self) -> tuple[K, V]:
|
|
131
163
|
n = self._n
|
|
132
164
|
if n is None:
|
|
@@ -142,3 +174,23 @@ class TreapMapIterator(ta.Generic[K, V]):
|
|
|
142
174
|
else:
|
|
143
175
|
self._n = None
|
|
144
176
|
return n.value
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class TreapMapReverseIterator(BaseTreapMapIterator[K, V]):
|
|
180
|
+
__slots__ = BaseTreapMapIterator.__slots__
|
|
181
|
+
|
|
182
|
+
def next(self) -> tuple[K, V]:
|
|
183
|
+
n = self._n
|
|
184
|
+
if n is None:
|
|
185
|
+
raise StopIteration
|
|
186
|
+
if n.left is not None:
|
|
187
|
+
self._n = n.left
|
|
188
|
+
while self._n.right is not None:
|
|
189
|
+
self._st.append(self._n)
|
|
190
|
+
self._n = self._n.right
|
|
191
|
+
elif len(self._st) > 0:
|
|
192
|
+
self._n = self._st[-1]
|
|
193
|
+
self._st.pop()
|
|
194
|
+
else:
|
|
195
|
+
self._n = None
|
|
196
|
+
return n.value
|
|
@@ -22,34 +22,34 @@ class UnmodifiableSequence(ta.Sequence[T], Unmodifiable, lang.Final):
|
|
|
22
22
|
self._target = target
|
|
23
23
|
|
|
24
24
|
def __repr__(self) -> str:
|
|
25
|
-
return '
|
|
25
|
+
return f'{type(self).__name__}({self._target!r})'
|
|
26
26
|
|
|
27
|
-
def __contains__(self, x:
|
|
27
|
+
def __contains__(self, x: ta.Any) -> bool:
|
|
28
28
|
return x in self._target
|
|
29
29
|
|
|
30
30
|
def __eq__(self, o: object) -> bool:
|
|
31
31
|
return self._target == o
|
|
32
32
|
|
|
33
|
-
def __ge__(self, other:
|
|
34
|
-
return self._target >= other
|
|
33
|
+
def __ge__(self, other: ta.Any) -> bool:
|
|
34
|
+
return self._target >= other
|
|
35
35
|
|
|
36
|
-
def __getitem__(self, i:
|
|
36
|
+
def __getitem__(self, i: int | slice) -> T: # type: ignore
|
|
37
37
|
return self._target[i] # type: ignore
|
|
38
38
|
|
|
39
|
-
def __gt__(self, other:
|
|
40
|
-
return self._target > other
|
|
39
|
+
def __gt__(self, other: ta.Any) -> bool:
|
|
40
|
+
return self._target > other
|
|
41
41
|
|
|
42
42
|
def __iter__(self) -> ta.Iterator[T]:
|
|
43
43
|
return iter(self._target)
|
|
44
44
|
|
|
45
|
-
def __le__(self, other:
|
|
46
|
-
return self._target <= other
|
|
45
|
+
def __le__(self, other: ta.Any) -> bool:
|
|
46
|
+
return self._target <= other
|
|
47
47
|
|
|
48
48
|
def __len__(self) -> int:
|
|
49
49
|
return len(self._target)
|
|
50
50
|
|
|
51
|
-
def __lt__(self, other:
|
|
52
|
-
return self._target < other
|
|
51
|
+
def __lt__(self, other: ta.Any) -> bool:
|
|
52
|
+
return self._target < other
|
|
53
53
|
|
|
54
54
|
def __ne__(self, o: object) -> bool:
|
|
55
55
|
return self._target != o
|
|
@@ -74,12 +74,12 @@ class UnmodifiableSet(ta.AbstractSet[T], Unmodifiable, lang.Final):
|
|
|
74
74
|
self._target = target
|
|
75
75
|
|
|
76
76
|
def __repr__(self) -> str:
|
|
77
|
-
return '
|
|
77
|
+
return f'{type(self).__name__}({self._target!r})'
|
|
78
78
|
|
|
79
79
|
def __and__(self, s: ta.AbstractSet[ta.Any]) -> ta.AbstractSet[T]:
|
|
80
80
|
return self._target & s
|
|
81
81
|
|
|
82
|
-
def __contains__(self, x:
|
|
82
|
+
def __contains__(self, x: ta.Any) -> bool:
|
|
83
83
|
return x in self._target
|
|
84
84
|
|
|
85
85
|
def __eq__(self, o: object) -> bool:
|
|
@@ -120,6 +120,7 @@ class UnmodifiableSet(ta.AbstractSet[T], Unmodifiable, lang.Final):
|
|
|
120
120
|
|
|
121
121
|
|
|
122
122
|
class UnmodifiableMapping(ta.Mapping[K, V], Unmodifiable, lang.Final):
|
|
123
|
+
# Could be a MappingProxyType but isn't for consistency with the others.
|
|
123
124
|
|
|
124
125
|
def __init__(self, target: ta.Mapping[K, V]) -> None:
|
|
125
126
|
super().__init__()
|
|
@@ -129,39 +130,39 @@ class UnmodifiableMapping(ta.Mapping[K, V], Unmodifiable, lang.Final):
|
|
|
129
130
|
self._target = target
|
|
130
131
|
|
|
131
132
|
def __repr__(self) -> str:
|
|
132
|
-
return '
|
|
133
|
+
return f'{type(self).__name__}({self._target!r})'
|
|
133
134
|
|
|
134
|
-
def __contains__(self, o:
|
|
135
|
+
def __contains__(self, o: ta.Any) -> bool:
|
|
135
136
|
return o in self._target
|
|
136
137
|
|
|
137
138
|
def __eq__(self, o: object) -> bool:
|
|
138
139
|
return self._target == o
|
|
139
140
|
|
|
140
|
-
def __ge__(self, other:
|
|
141
|
-
return self._target >= other
|
|
141
|
+
def __ge__(self, other: ta.Any) -> bool:
|
|
142
|
+
return self._target >= other
|
|
142
143
|
|
|
143
144
|
def __getitem__(self, k: K) -> V:
|
|
144
145
|
return self._target[k]
|
|
145
146
|
|
|
146
|
-
def __gt__(self, other:
|
|
147
|
-
return self._target > other
|
|
147
|
+
def __gt__(self, other: ta.Any) -> bool:
|
|
148
|
+
return self._target > other
|
|
148
149
|
|
|
149
150
|
def __iter__(self) -> ta.Iterator[T]:
|
|
150
151
|
return iter(self._target) # type: ignore
|
|
151
152
|
|
|
152
|
-
def __le__(self, other:
|
|
153
|
-
return self._target <= other
|
|
153
|
+
def __le__(self, other: ta.Any) -> bool:
|
|
154
|
+
return self._target <= other
|
|
154
155
|
|
|
155
156
|
def __len__(self) -> int:
|
|
156
157
|
return len(self._target)
|
|
157
158
|
|
|
158
|
-
def __lt__(self, other:
|
|
159
|
-
return self._target < other
|
|
159
|
+
def __lt__(self, other: ta.Any) -> bool:
|
|
160
|
+
return self._target < other
|
|
160
161
|
|
|
161
162
|
def __ne__(self, o: object) -> bool:
|
|
162
163
|
return self._target != o
|
|
163
164
|
|
|
164
|
-
def get(self, k: K, default=None) ->
|
|
165
|
+
def get(self, k: K, default=None) -> V | None: # type: ignore
|
|
165
166
|
return self._target.get(k)
|
|
166
167
|
|
|
167
168
|
def items(self) -> ta.ItemsView[K, V]:
|
omlish/collections/utils.py
CHANGED
|
@@ -18,7 +18,7 @@ def mut_toposort(data: dict[T, set[T]]) -> ta.Iterator[set[T]]:
|
|
|
18
18
|
extra_items_in_deps = functools.reduce(set.union, data.values()) - set(data.keys())
|
|
19
19
|
data.update({item: set() for item in extra_items_in_deps})
|
|
20
20
|
while True:
|
|
21
|
-
ordered =
|
|
21
|
+
ordered = {item for item, dep in data.items() if not dep}
|
|
22
22
|
if not ordered:
|
|
23
23
|
break
|
|
24
24
|
yield ordered
|
omlish/configs/flattening.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import abc
|
|
2
|
+
import itertools
|
|
2
3
|
import typing as ta
|
|
3
4
|
|
|
4
5
|
from .. import check
|
|
@@ -34,10 +35,10 @@ class Flattening:
|
|
|
34
35
|
self._index_close = check.not_empty(index_close)
|
|
35
36
|
|
|
36
37
|
def flatten(self, unflattened: StrMap) -> StrMap:
|
|
37
|
-
def rec(prefix:
|
|
38
|
+
def rec(prefix: list[str], value: ta.Any) -> None:
|
|
38
39
|
if isinstance(value, dict):
|
|
39
40
|
for k, v in value.items():
|
|
40
|
-
rec(prefix
|
|
41
|
+
rec([*prefix, k], v)
|
|
41
42
|
elif isinstance(value, list):
|
|
42
43
|
check.not_empty(prefix)
|
|
43
44
|
for i, v in enumerate(value):
|
|
@@ -48,7 +49,7 @@ class Flattening:
|
|
|
48
49
|
raise KeyError(k)
|
|
49
50
|
ret[k] = value
|
|
50
51
|
|
|
51
|
-
ret:
|
|
52
|
+
ret: dict[str, ta.Any] = {}
|
|
52
53
|
rec([], unflattened)
|
|
53
54
|
return ret
|
|
54
55
|
|
|
@@ -83,7 +84,7 @@ class Flattening:
|
|
|
83
84
|
def __init__(self) -> None:
|
|
84
85
|
super().__init__()
|
|
85
86
|
|
|
86
|
-
self._dict:
|
|
87
|
+
self._dict: dict[str, ta.Any] = {}
|
|
87
88
|
|
|
88
89
|
def get(self, key: str) -> ta.Any:
|
|
89
90
|
return self._dict.get(key, _MISSING)
|
|
@@ -100,7 +101,7 @@ class Flattening:
|
|
|
100
101
|
def __init__(self) -> None:
|
|
101
102
|
super().__init__()
|
|
102
103
|
|
|
103
|
-
self._list:
|
|
104
|
+
self._list: list[ta.Any] = []
|
|
104
105
|
|
|
105
106
|
def get(self, key: int) -> ta.Any:
|
|
106
107
|
check.arg(key >= 0)
|
|
@@ -119,7 +120,7 @@ class Flattening:
|
|
|
119
120
|
def unflatten(self, flattened: StrMap) -> StrMap:
|
|
120
121
|
root = Flattening.UnflattenDict()
|
|
121
122
|
|
|
122
|
-
def split_keys(fkey: str) -> ta.Iterable[
|
|
123
|
+
def split_keys(fkey: str) -> ta.Iterable[str | int]:
|
|
123
124
|
for part in fkey.split(self._delimiter):
|
|
124
125
|
if self._index_open in part:
|
|
125
126
|
check.state(part.endswith(self._index_close))
|
|
@@ -135,7 +136,7 @@ class Flattening:
|
|
|
135
136
|
for fk, v in flattened.items():
|
|
136
137
|
node: Flattening.UnflattenNode = root
|
|
137
138
|
fks = list(split_keys(fk))
|
|
138
|
-
for key, nkey in
|
|
139
|
+
for key, nkey in itertools.pairwise(fks):
|
|
139
140
|
if isinstance(nkey, str):
|
|
140
141
|
node = node.setdefault(key, Flattening.UnflattenDict)
|
|
141
142
|
elif isinstance(nkey, int):
|
omlish/configs/props.py
CHANGED
|
@@ -19,8 +19,8 @@ def escape(token: str) -> str:
|
|
|
19
19
|
return _ESCAPE_PATTERN.sub(r'\\\1', token)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def parse_line(line: str) ->
|
|
23
|
-
if line and not
|
|
22
|
+
def parse_line(line: str) -> tuple[str, str] | None:
|
|
23
|
+
if line and not line.startswith(('#', '!')):
|
|
24
24
|
match = _SEPARATOR_PATTERN.search(line)
|
|
25
25
|
if match:
|
|
26
26
|
return normalize(line[:match.start()]), normalize(line[match.end():])
|
|
@@ -54,7 +54,7 @@ def coalesce_lines(lines: ta.Iterable[str]) -> ta.Generator[str, None, None]:
|
|
|
54
54
|
pass
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def parse_lines(lines: ta.Iterable[str]) ->
|
|
57
|
+
def parse_lines(lines: ta.Iterable[str]) -> dict[str, str]:
|
|
58
58
|
props = {}
|
|
59
59
|
for line in coalesce_lines(lines):
|
|
60
60
|
kv_pair = parse_line(line)
|
omlish/dataclasses/__init__.py
CHANGED
|
@@ -3,4 +3,22 @@ TODO:
|
|
|
3
3
|
- metaclass:
|
|
4
4
|
- cleanup confer
|
|
5
5
|
- descriptors - check_type/validators don't handle setters lol
|
|
6
|
+
- deep_frozen?
|
|
7
|
+
- field:
|
|
8
|
+
- frozen
|
|
9
|
+
- pickle/transient
|
|
10
|
+
- mangled
|
|
11
|
+
- doc
|
|
12
|
+
- derive
|
|
13
|
+
- check_type
|
|
14
|
+
- class
|
|
15
|
+
- strict_eq
|
|
16
|
+
- allow_setattr
|
|
17
|
+
- mangler
|
|
18
|
+
- observable
|
|
19
|
+
- c/py gen
|
|
20
|
+
- iterable
|
|
21
|
+
- proto/jsonschema gen
|
|
22
|
+
- enums
|
|
23
|
+
- nodal
|
|
6
24
|
"""
|
omlish/dataclasses/impl/api.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import collections.abc
|
|
2
|
+
import contextlib
|
|
2
3
|
import dataclasses as dc
|
|
3
4
|
import keyword
|
|
4
5
|
import sys
|
|
@@ -12,30 +13,28 @@ from .main import process_class
|
|
|
12
13
|
from .metadata import METADATA_ATTR
|
|
13
14
|
from .metadata import Metadata
|
|
14
15
|
from .params import FieldExtras
|
|
15
|
-
from .params import Params12
|
|
16
16
|
from .params import ParamsExtras
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
MISSING = dc.MISSING
|
|
20
20
|
|
|
21
|
-
IS_12 = sys.version_info[1] >= 12
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
def field(
|
|
22
|
+
def field( # noqa
|
|
25
23
|
default=MISSING,
|
|
26
24
|
*,
|
|
27
25
|
default_factory=MISSING,
|
|
28
26
|
init=True,
|
|
29
|
-
repr=True,
|
|
30
|
-
hash=None,
|
|
27
|
+
repr=True, # noqa
|
|
28
|
+
hash=None, # noqa
|
|
31
29
|
compare=True,
|
|
32
30
|
metadata=None,
|
|
33
31
|
kw_only=MISSING,
|
|
34
32
|
|
|
35
|
-
coerce: ta.
|
|
36
|
-
check: ta.
|
|
37
|
-
check_type:
|
|
33
|
+
coerce: ta.Callable[[ta.Any], ta.Any] | None = None,
|
|
34
|
+
check: ta.Callable[[ta.Any], bool] | None = None,
|
|
35
|
+
check_type: bool | None = None,
|
|
38
36
|
override: bool = False,
|
|
37
|
+
repr_fn: ta.Callable[[ta.Any], str | None] | None = None
|
|
39
38
|
): # -> dc.Field
|
|
40
39
|
if default is not MISSING and default_factory is not MISSING:
|
|
41
40
|
raise ValueError('cannot specify both default and default_factory')
|
|
@@ -45,6 +44,7 @@ def field(
|
|
|
45
44
|
check=check,
|
|
46
45
|
check_type=check_type,
|
|
47
46
|
override=override,
|
|
47
|
+
repr_fn=repr_fn,
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
md: ta.Mapping = {FieldExtras: fx}
|
|
@@ -67,12 +67,12 @@ def _strip_missing_values(d):
|
|
|
67
67
|
return {k: v for k, v in d.items() if v is not MISSING}
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
def dataclass(
|
|
70
|
+
def dataclass( # noqa
|
|
71
71
|
cls=None,
|
|
72
72
|
/,
|
|
73
73
|
*,
|
|
74
74
|
init=True,
|
|
75
|
-
repr=True,
|
|
75
|
+
repr=True, # noqa
|
|
76
76
|
eq=True,
|
|
77
77
|
order=False,
|
|
78
78
|
unsafe_hash=False,
|
|
@@ -96,8 +96,6 @@ def dataclass(
|
|
|
96
96
|
order=order,
|
|
97
97
|
unsafe_hash=unsafe_hash,
|
|
98
98
|
frozen=frozen,
|
|
99
|
-
)
|
|
100
|
-
p12kw = dict(
|
|
101
99
|
match_args=match_args,
|
|
102
100
|
kw_only=kw_only,
|
|
103
101
|
slots=slots,
|
|
@@ -118,11 +116,6 @@ def dataclass(
|
|
|
118
116
|
ParamsExtras: pex,
|
|
119
117
|
}
|
|
120
118
|
|
|
121
|
-
if IS_12:
|
|
122
|
-
pkw.update(p12kw)
|
|
123
|
-
else:
|
|
124
|
-
mmd[Params12] = Params12(**p12kw)
|
|
125
|
-
|
|
126
119
|
md: Metadata = mmd
|
|
127
120
|
cmds = []
|
|
128
121
|
if metadata is not None:
|
|
@@ -143,14 +136,14 @@ def dataclass(
|
|
|
143
136
|
return wrap(cls)
|
|
144
137
|
|
|
145
138
|
|
|
146
|
-
def make_dataclass(
|
|
139
|
+
def make_dataclass( # noqa
|
|
147
140
|
cls_name,
|
|
148
141
|
fields,
|
|
149
142
|
*,
|
|
150
143
|
bases=(),
|
|
151
144
|
namespace=None,
|
|
152
145
|
init=True,
|
|
153
|
-
repr=True,
|
|
146
|
+
repr=True, # noqa
|
|
154
147
|
eq=True,
|
|
155
148
|
order=False,
|
|
156
149
|
unsafe_hash=False,
|
|
@@ -203,10 +196,8 @@ def make_dataclass(
|
|
|
203
196
|
try:
|
|
204
197
|
module = sys._getframemodulename(1) or '__main__' # type: ignore # noqa
|
|
205
198
|
except AttributeError:
|
|
206
|
-
|
|
199
|
+
with contextlib.suppress(AttributeError, ValueError):
|
|
207
200
|
module = sys._getframe(1).f_globals.get('__name__', '__main__') # noqa
|
|
208
|
-
except (AttributeError, ValueError):
|
|
209
|
-
pass
|
|
210
201
|
if module is not None:
|
|
211
202
|
cls.__module__ = module
|
|
212
203
|
|
|
@@ -233,7 +224,7 @@ class _ExtraParamsKwargs:
|
|
|
233
224
|
pass
|
|
234
225
|
|
|
235
226
|
|
|
236
|
-
def extra_params(
|
|
227
|
+
def extra_params( # noqa
|
|
237
228
|
*,
|
|
238
229
|
reorder=MISSING,
|
|
239
230
|
cache_hash=MISSING,
|
omlish/dataclasses/impl/as_.py
CHANGED
|
@@ -5,9 +5,9 @@ from .internals import is_dataclass_instance
|
|
|
5
5
|
from .internals import ATOMIC_TYPES
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def asdict(obj, *, dict_factory=dict):
|
|
8
|
+
def asdict(obj, *, dict_factory=dict): # noqa
|
|
9
9
|
if not is_dataclass_instance(obj): # noqa
|
|
10
|
-
raise TypeError(
|
|
10
|
+
raise TypeError('asdict() should be called on dataclass instances')
|
|
11
11
|
return _asdict_inner(obj, dict_factory)
|
|
12
12
|
|
|
13
13
|
|
|
@@ -40,9 +40,9 @@ def _asdict_inner(obj, dict_factory):
|
|
|
40
40
|
return copy.deepcopy(obj)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def astuple(obj, *, tuple_factory=tuple):
|
|
43
|
+
def astuple(obj, *, tuple_factory=tuple): # noqa
|
|
44
44
|
if not is_dataclass_instance(obj):
|
|
45
|
-
raise TypeError(
|
|
45
|
+
raise TypeError('astuple() should be called on dataclass instances')
|
|
46
46
|
return _astuple_inner(obj, tuple_factory)
|
|
47
47
|
|
|
48
48
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class
|
|
1
|
+
class CheckError(Exception):
|
|
2
2
|
pass
|