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.

Files changed (147) hide show
  1. omlish/__about__.py +2 -3
  2. omlish/argparse.py +8 -8
  3. omlish/asyncs/__init__.py +2 -2
  4. omlish/asyncs/anyio.py +64 -1
  5. omlish/asyncs/asyncs.py +1 -3
  6. omlish/asyncs/futures.py +16 -15
  7. omlish/c3.py +5 -5
  8. omlish/check.py +8 -8
  9. omlish/collections/__init__.py +98 -63
  10. omlish/collections/_abc.py +2 -0
  11. omlish/collections/_io_abc.py +4 -2
  12. omlish/collections/cache/__init__.py +1 -1
  13. omlish/collections/cache/descriptor.py +12 -12
  14. omlish/collections/cache/impl.py +27 -20
  15. omlish/collections/cache/types.py +1 -1
  16. omlish/collections/coerce.py +44 -44
  17. omlish/collections/frozen.py +9 -9
  18. omlish/collections/identity.py +4 -5
  19. omlish/collections/mappings.py +5 -5
  20. omlish/collections/ordered.py +8 -8
  21. omlish/collections/skiplist.py +7 -7
  22. omlish/collections/sorted.py +4 -4
  23. omlish/collections/treap.py +42 -17
  24. omlish/collections/treapmap.py +59 -7
  25. omlish/collections/unmodifiable.py +25 -24
  26. omlish/collections/utils.py +1 -1
  27. omlish/configs/flattening.py +8 -7
  28. omlish/configs/props.py +3 -3
  29. omlish/dataclasses/__init__.py +1 -1
  30. omlish/dataclasses/impl/__init__.py +18 -0
  31. omlish/dataclasses/impl/api.py +15 -24
  32. omlish/dataclasses/impl/as_.py +4 -4
  33. omlish/dataclasses/impl/exceptions.py +1 -1
  34. omlish/dataclasses/impl/fields.py +8 -8
  35. omlish/dataclasses/impl/frozen.py +2 -2
  36. omlish/dataclasses/impl/init.py +6 -6
  37. omlish/dataclasses/impl/internals.py +16 -1
  38. omlish/dataclasses/impl/main.py +4 -4
  39. omlish/dataclasses/impl/metaclass.py +2 -2
  40. omlish/dataclasses/impl/metadata.py +1 -1
  41. omlish/dataclasses/impl/order.py +2 -2
  42. omlish/dataclasses/impl/params.py +4 -38
  43. omlish/dataclasses/impl/reflect.py +1 -7
  44. omlish/dataclasses/impl/replace.py +1 -1
  45. omlish/dataclasses/impl/repr.py +24 -6
  46. omlish/dataclasses/impl/simple.py +2 -2
  47. omlish/dataclasses/impl/slots.py +2 -2
  48. omlish/dataclasses/impl/utils.py +7 -7
  49. omlish/defs.py +13 -17
  50. omlish/diag/procfs.py +334 -0
  51. omlish/diag/ps.py +47 -0
  52. omlish/{replserver → diag/replserver}/console.py +26 -28
  53. omlish/{replserver → diag/replserver}/server.py +12 -12
  54. omlish/dispatch/dispatch.py +14 -16
  55. omlish/dispatch/functions.py +1 -1
  56. omlish/dispatch/methods.py +6 -7
  57. omlish/docker.py +8 -6
  58. omlish/dynamic.py +13 -13
  59. omlish/fnpairs.py +311 -0
  60. omlish/graphs/dot/items.py +1 -1
  61. omlish/graphs/trees.py +25 -31
  62. omlish/inject/__init__.py +7 -7
  63. omlish/inject/elements.py +2 -2
  64. omlish/inject/exceptions.py +8 -8
  65. omlish/inject/impl/elements.py +4 -4
  66. omlish/inject/impl/injector.py +6 -6
  67. omlish/inject/impl/inspect.py +3 -3
  68. omlish/inject/impl/scopes.py +9 -9
  69. omlish/inject/injector.py +1 -1
  70. omlish/inject/providers.py +2 -2
  71. omlish/inject/proxy.py +5 -5
  72. omlish/iterators.py +62 -26
  73. omlish/json.py +7 -6
  74. omlish/lang/__init__.py +172 -112
  75. omlish/lang/cached.py +15 -10
  76. omlish/lang/classes/__init__.py +35 -24
  77. omlish/lang/classes/abstract.py +3 -3
  78. omlish/lang/classes/restrict.py +14 -14
  79. omlish/lang/classes/simple.py +2 -2
  80. omlish/lang/classes/virtual.py +5 -5
  81. omlish/lang/clsdct.py +2 -2
  82. omlish/lang/cmp.py +2 -2
  83. omlish/lang/contextmanagers.py +31 -25
  84. omlish/lang/datetimes.py +1 -1
  85. omlish/lang/descriptors.py +51 -6
  86. omlish/lang/exceptions.py +2 -0
  87. omlish/lang/functions.py +101 -35
  88. omlish/lang/imports.py +25 -30
  89. omlish/lang/iterables.py +2 -2
  90. omlish/lang/maybes.py +2 -1
  91. omlish/lang/objects.py +17 -11
  92. omlish/lang/resolving.py +1 -1
  93. omlish/lang/strings.py +1 -1
  94. omlish/lang/timeouts.py +53 -0
  95. omlish/lang/typing.py +5 -5
  96. omlish/libc.py +15 -11
  97. omlish/logs/_abc.py +5 -1
  98. omlish/logs/filters.py +2 -0
  99. omlish/logs/formatters.py +6 -2
  100. omlish/logs/utils.py +1 -1
  101. omlish/marshal/base.py +9 -9
  102. omlish/marshal/dataclasses.py +2 -2
  103. omlish/marshal/enums.py +2 -2
  104. omlish/marshal/exceptions.py +1 -1
  105. omlish/marshal/factories.py +10 -10
  106. omlish/marshal/global_.py +10 -4
  107. omlish/marshal/iterables.py +2 -2
  108. omlish/marshal/mappings.py +2 -2
  109. omlish/marshal/objects.py +1 -2
  110. omlish/marshal/optionals.py +4 -4
  111. omlish/marshal/polymorphism.py +4 -4
  112. omlish/marshal/registries.py +3 -3
  113. omlish/marshal/standard.py +6 -6
  114. omlish/marshal/utils.py +3 -3
  115. omlish/marshal/values.py +1 -1
  116. omlish/math.py +9 -9
  117. omlish/os.py +13 -4
  118. omlish/reflect.py +5 -15
  119. omlish/sql/__init__.py +0 -0
  120. omlish/sql/_abc.py +65 -0
  121. omlish/sql/dbs.py +90 -0
  122. omlish/stats.py +7 -8
  123. omlish/term.py +1 -1
  124. omlish/testing/pydevd.py +30 -12
  125. omlish/testing/pytest/inject/__init__.py +7 -0
  126. omlish/testing/pytest/inject/harness.py +24 -2
  127. omlish/testing/pytest/plugins/__init__.py +1 -1
  128. omlish/testing/pytest/plugins/pydevd.py +12 -0
  129. omlish/testing/pytest/plugins/switches.py +3 -3
  130. omlish/testing/testing.py +5 -5
  131. omlish/text/delimit.py +3 -6
  132. omlish/text/parts.py +3 -3
  133. omlish-0.0.0.dev3.dist-info/METADATA +31 -0
  134. omlish-0.0.0.dev3.dist-info/RECORD +191 -0
  135. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/WHEEL +1 -1
  136. omlish/lang/classes/test/test_abstract.py +0 -89
  137. omlish/lang/classes/test/test_restrict.py +0 -71
  138. omlish/lang/classes/test/test_simple.py +0 -58
  139. omlish/lang/classes/test/test_virtual.py +0 -72
  140. omlish/testing/pytest/plugins/pycharm.py +0 -54
  141. omlish-0.0.0.dev1.dist-info/METADATA +0 -17
  142. omlish-0.0.0.dev1.dist-info/RECORD +0 -187
  143. /omlish/{lang/classes/test → diag}/__init__.py +0 -0
  144. /omlish/{replserver → diag/replserver}/__init__.py +0 -0
  145. /omlish/{replserver → diag/replserver}/__main__.py +0 -0
  146. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/LICENSE +0 -0
  147. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/top_level.txt +0 -0
@@ -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: ta.Optional[TreapNode[T]], v: T, c: Comparer[T]) -> ta.Optional[TreapNode[T]]:
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: ta.Optional[TreapNode[T]],
83
- other: ta.Optional[TreapNode[T]],
107
+ n: TreapNode[T] | None,
108
+ other: TreapNode[T] | None,
84
109
  c: Comparer[T],
85
110
  overwrite: bool,
86
- ) -> ta.Optional[TreapNode[T]]:
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: ta.Optional[TreapNode[T]],
128
+ n: TreapNode[T] | None,
104
129
  v: T,
105
130
  c: Comparer[T],
106
131
  ) -> tuple[
107
- ta.Optional[TreapNode[T]],
108
- ta.Optional[TreapNode[T]],
109
- ta.Optional[TreapNode[T]],
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: ta.Optional[TreapNode[T]] = n
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: ta.Optional[TreapNode[T]],
150
- other: ta.Optional[TreapNode[T]],
174
+ n: TreapNode[T] | None,
175
+ other: TreapNode[T] | None,
151
176
  c: Comparer[T],
152
- ) -> ta.Optional[TreapNode[T]]:
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: ta.Optional[TreapNode[T]], v: T, c: Comparer[T]) -> ta.Optional[TreapNode[T]]:
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: ta.Optional[TreapNode[T]], other: ta.Optional[TreapNode[T]], c: Comparer[T]) -> ta.Optional[TreapNode[T]]:
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: ta.Optional[TreapNode[T]], other: ta.Optional[TreapNode[T]]) -> ta.Optional[TreapNode[T]]:
194
- result: ta.Optional[TreapNode[T]] = None
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: ta.Optional[TreapNode[T]] = n
234
+ cur: TreapNode[T] | None = n
210
235
  while True:
211
236
  if cur is None:
212
237
  setresultp(other)
@@ -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: ta.Optional[treap.TreapNode[tuple[K, V]]],
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 TreapMapIterator(ta.Generic[K, V]):
112
- __slots__ = ('_st', '_n', '_b')
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: ta.Optional[treap.TreapNode[tuple[K, V]]],
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 '%s(%r)' % (type(self).__name__, self._target)
25
+ return f'{type(self).__name__}({self._target!r})'
26
26
 
27
- def __contains__(self, x: object) -> bool:
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: object) -> bool:
34
- return self._target >= other # type: ignore
33
+ def __ge__(self, other: ta.Any) -> bool:
34
+ return self._target >= other
35
35
 
36
- def __getitem__(self, i: ta.Union[int, slice]) -> T: # type: ignore
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: object) -> bool:
40
- return self._target > other # type: ignore
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: object) -> bool:
46
- return self._target <= other # type: ignore
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: object) -> bool:
52
- return self._target < other # type: ignore
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 '%s(%r)' % (type(self).__name__, self._target)
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: object) -> bool:
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 '%s(%r)' % (type(self).__name__, self._target)
133
+ return f'{type(self).__name__}({self._target!r})'
133
134
 
134
- def __contains__(self, o: object) -> bool:
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: object) -> bool:
141
- return self._target >= other # type: ignore
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: object) -> bool:
147
- return self._target > other # type: ignore
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: object) -> bool:
153
- return self._target <= other # type: ignore
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: object) -> bool:
159
- return self._target < other # type: ignore
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) -> ta.Optional[V]: # type: ignore
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]:
@@ -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 = set(item for item, dep in data.items() if not dep)
21
+ ordered = {item for item, dep in data.items() if not dep}
22
22
  if not ordered:
23
23
  break
24
24
  yield ordered
@@ -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: ta.List[str], value: ta.Any) -> None:
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 + [k], v)
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: ta.Dict[str, ta.Any] = {}
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: ta.Dict[str, ta.Any] = {}
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: ta.List[ta.Any] = []
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[ta.Union[str, int]]:
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 zip(fks, fks[1:]):
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) -> ta.Optional[ta.Tuple[str, str]]:
23
- if line and not (line.startswith('#') or line.startswith('!')):
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]) -> ta.Dict[str, 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)
@@ -54,7 +54,7 @@ globals()['make_dataclass'] = xmake_dataclass
54
54
 
55
55
 
56
56
  from .impl.exceptions import ( # noqa
57
- CheckException,
57
+ CheckError,
58
58
  )
59
59
 
60
60
  from .impl.metaclass import ( # noqa
@@ -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
  """
@@ -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.Optional[ta.Callable[[ta.Any], ta.Any]] = None,
36
- check: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
37
- check_type: ta.Optional[bool] = None,
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
- try:
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,
@@ -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("asdict() should be called on dataclass instances")
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("astuple() should be called on dataclass instances")
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 CheckException(Exception):
1
+ class CheckError(Exception):
2
2
  pass