omlish 0.0.0.dev1__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 (187) hide show
  1. omlish/__about__.py +7 -0
  2. omlish/__init__.py +0 -0
  3. omlish/argparse.py +223 -0
  4. omlish/asyncs/__init__.py +17 -0
  5. omlish/asyncs/anyio.py +23 -0
  6. omlish/asyncs/asyncio.py +19 -0
  7. omlish/asyncs/asyncs.py +76 -0
  8. omlish/asyncs/futures.py +179 -0
  9. omlish/asyncs/trio.py +11 -0
  10. omlish/c3.py +173 -0
  11. omlish/cached.py +9 -0
  12. omlish/check.py +231 -0
  13. omlish/collections/__init__.py +63 -0
  14. omlish/collections/_abc.py +156 -0
  15. omlish/collections/_io_abc.py +78 -0
  16. omlish/collections/cache/__init__.py +11 -0
  17. omlish/collections/cache/descriptor.py +188 -0
  18. omlish/collections/cache/impl.py +485 -0
  19. omlish/collections/cache/types.py +37 -0
  20. omlish/collections/coerce.py +337 -0
  21. omlish/collections/frozen.py +148 -0
  22. omlish/collections/identity.py +106 -0
  23. omlish/collections/indexed.py +75 -0
  24. omlish/collections/mappings.py +127 -0
  25. omlish/collections/ordered.py +81 -0
  26. omlish/collections/persistent.py +36 -0
  27. omlish/collections/skiplist.py +193 -0
  28. omlish/collections/sorted.py +126 -0
  29. omlish/collections/treap.py +228 -0
  30. omlish/collections/treapmap.py +144 -0
  31. omlish/collections/unmodifiable.py +174 -0
  32. omlish/collections/utils.py +110 -0
  33. omlish/configs/__init__.py +0 -0
  34. omlish/configs/flattening.py +147 -0
  35. omlish/configs/props.py +64 -0
  36. omlish/dataclasses/__init__.py +83 -0
  37. omlish/dataclasses/impl/__init__.py +6 -0
  38. omlish/dataclasses/impl/api.py +260 -0
  39. omlish/dataclasses/impl/as_.py +76 -0
  40. omlish/dataclasses/impl/exceptions.py +2 -0
  41. omlish/dataclasses/impl/fields.py +148 -0
  42. omlish/dataclasses/impl/frozen.py +55 -0
  43. omlish/dataclasses/impl/hashing.py +85 -0
  44. omlish/dataclasses/impl/init.py +173 -0
  45. omlish/dataclasses/impl/internals.py +118 -0
  46. omlish/dataclasses/impl/main.py +150 -0
  47. omlish/dataclasses/impl/metaclass.py +126 -0
  48. omlish/dataclasses/impl/metadata.py +74 -0
  49. omlish/dataclasses/impl/order.py +47 -0
  50. omlish/dataclasses/impl/params.py +150 -0
  51. omlish/dataclasses/impl/processing.py +16 -0
  52. omlish/dataclasses/impl/reflect.py +173 -0
  53. omlish/dataclasses/impl/replace.py +40 -0
  54. omlish/dataclasses/impl/repr.py +34 -0
  55. omlish/dataclasses/impl/simple.py +92 -0
  56. omlish/dataclasses/impl/slots.py +80 -0
  57. omlish/dataclasses/impl/utils.py +167 -0
  58. omlish/defs.py +193 -0
  59. omlish/dispatch/__init__.py +3 -0
  60. omlish/dispatch/dispatch.py +137 -0
  61. omlish/dispatch/functions.py +52 -0
  62. omlish/dispatch/methods.py +162 -0
  63. omlish/docker.py +149 -0
  64. omlish/dynamic.py +220 -0
  65. omlish/graphs/__init__.py +0 -0
  66. omlish/graphs/dot/__init__.py +19 -0
  67. omlish/graphs/dot/items.py +162 -0
  68. omlish/graphs/dot/rendering.py +147 -0
  69. omlish/graphs/dot/utils.py +30 -0
  70. omlish/graphs/trees.py +249 -0
  71. omlish/http/__init__.py +0 -0
  72. omlish/http/consts.py +20 -0
  73. omlish/http/wsgi.py +34 -0
  74. omlish/inject/__init__.py +85 -0
  75. omlish/inject/binder.py +12 -0
  76. omlish/inject/bindings.py +49 -0
  77. omlish/inject/eagers.py +21 -0
  78. omlish/inject/elements.py +43 -0
  79. omlish/inject/exceptions.py +49 -0
  80. omlish/inject/impl/__init__.py +0 -0
  81. omlish/inject/impl/bindings.py +19 -0
  82. omlish/inject/impl/elements.py +154 -0
  83. omlish/inject/impl/injector.py +182 -0
  84. omlish/inject/impl/inspect.py +98 -0
  85. omlish/inject/impl/private.py +109 -0
  86. omlish/inject/impl/providers.py +132 -0
  87. omlish/inject/impl/scopes.py +198 -0
  88. omlish/inject/injector.py +40 -0
  89. omlish/inject/inspect.py +14 -0
  90. omlish/inject/keys.py +43 -0
  91. omlish/inject/managed.py +24 -0
  92. omlish/inject/overrides.py +18 -0
  93. omlish/inject/private.py +29 -0
  94. omlish/inject/providers.py +111 -0
  95. omlish/inject/proxy.py +48 -0
  96. omlish/inject/scopes.py +84 -0
  97. omlish/inject/types.py +21 -0
  98. omlish/iterators.py +184 -0
  99. omlish/json.py +194 -0
  100. omlish/lang/__init__.py +112 -0
  101. omlish/lang/cached.py +267 -0
  102. omlish/lang/classes/__init__.py +24 -0
  103. omlish/lang/classes/abstract.py +74 -0
  104. omlish/lang/classes/restrict.py +137 -0
  105. omlish/lang/classes/simple.py +120 -0
  106. omlish/lang/classes/test/__init__.py +0 -0
  107. omlish/lang/classes/test/test_abstract.py +89 -0
  108. omlish/lang/classes/test/test_restrict.py +71 -0
  109. omlish/lang/classes/test/test_simple.py +58 -0
  110. omlish/lang/classes/test/test_virtual.py +72 -0
  111. omlish/lang/classes/virtual.py +130 -0
  112. omlish/lang/clsdct.py +67 -0
  113. omlish/lang/cmp.py +63 -0
  114. omlish/lang/contextmanagers.py +249 -0
  115. omlish/lang/datetimes.py +67 -0
  116. omlish/lang/descriptors.py +52 -0
  117. omlish/lang/functions.py +126 -0
  118. omlish/lang/imports.py +153 -0
  119. omlish/lang/iterables.py +54 -0
  120. omlish/lang/maybes.py +136 -0
  121. omlish/lang/objects.py +103 -0
  122. omlish/lang/resolving.py +50 -0
  123. omlish/lang/strings.py +128 -0
  124. omlish/lang/typing.py +92 -0
  125. omlish/libc.py +532 -0
  126. omlish/logs/__init__.py +9 -0
  127. omlish/logs/_abc.py +247 -0
  128. omlish/logs/configs.py +62 -0
  129. omlish/logs/filters.py +9 -0
  130. omlish/logs/formatters.py +67 -0
  131. omlish/logs/utils.py +20 -0
  132. omlish/marshal/__init__.py +52 -0
  133. omlish/marshal/any.py +25 -0
  134. omlish/marshal/base.py +201 -0
  135. omlish/marshal/base64.py +25 -0
  136. omlish/marshal/dataclasses.py +115 -0
  137. omlish/marshal/datetimes.py +90 -0
  138. omlish/marshal/enums.py +43 -0
  139. omlish/marshal/exceptions.py +7 -0
  140. omlish/marshal/factories.py +129 -0
  141. omlish/marshal/global_.py +33 -0
  142. omlish/marshal/iterables.py +57 -0
  143. omlish/marshal/mappings.py +66 -0
  144. omlish/marshal/naming.py +17 -0
  145. omlish/marshal/objects.py +106 -0
  146. omlish/marshal/optionals.py +49 -0
  147. omlish/marshal/polymorphism.py +147 -0
  148. omlish/marshal/primitives.py +43 -0
  149. omlish/marshal/registries.py +57 -0
  150. omlish/marshal/standard.py +80 -0
  151. omlish/marshal/utils.py +23 -0
  152. omlish/marshal/uuids.py +29 -0
  153. omlish/marshal/values.py +30 -0
  154. omlish/math.py +184 -0
  155. omlish/os.py +32 -0
  156. omlish/reflect.py +359 -0
  157. omlish/replserver/__init__.py +5 -0
  158. omlish/replserver/__main__.py +4 -0
  159. omlish/replserver/console.py +247 -0
  160. omlish/replserver/server.py +146 -0
  161. omlish/runmodule.py +28 -0
  162. omlish/stats.py +342 -0
  163. omlish/term.py +222 -0
  164. omlish/testing/__init__.py +7 -0
  165. omlish/testing/pydevd.py +225 -0
  166. omlish/testing/pytest/__init__.py +8 -0
  167. omlish/testing/pytest/helpers.py +35 -0
  168. omlish/testing/pytest/inject/__init__.py +1 -0
  169. omlish/testing/pytest/inject/harness.py +159 -0
  170. omlish/testing/pytest/plugins/__init__.py +20 -0
  171. omlish/testing/pytest/plugins/_registry.py +6 -0
  172. omlish/testing/pytest/plugins/logging.py +13 -0
  173. omlish/testing/pytest/plugins/pycharm.py +54 -0
  174. omlish/testing/pytest/plugins/repeat.py +19 -0
  175. omlish/testing/pytest/plugins/skips.py +32 -0
  176. omlish/testing/pytest/plugins/spacing.py +19 -0
  177. omlish/testing/pytest/plugins/switches.py +70 -0
  178. omlish/testing/testing.py +102 -0
  179. omlish/text/__init__.py +0 -0
  180. omlish/text/delimit.py +171 -0
  181. omlish/text/indent.py +50 -0
  182. omlish/text/parts.py +265 -0
  183. omlish-0.0.0.dev1.dist-info/LICENSE +21 -0
  184. omlish-0.0.0.dev1.dist-info/METADATA +17 -0
  185. omlish-0.0.0.dev1.dist-info/RECORD +187 -0
  186. omlish-0.0.0.dev1.dist-info/WHEEL +5 -0
  187. omlish-0.0.0.dev1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,228 @@
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Gabriel Ochsenhofer
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
8
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
9
+ persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
12
+ Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
15
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
+ """
19
+ import typing as ta
20
+
21
+
22
+ T = ta.TypeVar('T')
23
+ Comparer = ta.Callable[[T, T], int]
24
+
25
+
26
+ class TreapNode(ta.Generic[T]):
27
+ __slots__ = ('_value', '_priority', '_left', '_right')
28
+
29
+ def __init__(
30
+ self,
31
+ *,
32
+ _value: T,
33
+ _priority: int,
34
+ _left: ta.Optional['TreapNode[T]'],
35
+ _right: ta.Optional['TreapNode[T]'],
36
+ ) -> None:
37
+ super().__init__()
38
+
39
+ self._value = _value
40
+ self._priority = _priority
41
+ self._left = _left
42
+ self._right = _right
43
+
44
+ @property
45
+ def value(self) -> T:
46
+ return self._value
47
+
48
+ @property
49
+ def priority(self) -> int:
50
+ return self._priority
51
+
52
+ @property
53
+ def left(self) -> ta.Optional['TreapNode[T]']:
54
+ return self._left
55
+
56
+ @property
57
+ def right(self) -> ta.Optional['TreapNode[T]']:
58
+ return self._right
59
+
60
+ def __iter__(self) -> ta.Iterator[T]:
61
+ if self._left is not None:
62
+ yield from self._left
63
+ yield self._value
64
+ if self._right is not None:
65
+ yield from self._right
66
+
67
+
68
+ def find(n: ta.Optional[TreapNode[T]], v: T, c: Comparer[T]) -> ta.Optional[TreapNode[T]]:
69
+ while True:
70
+ if n is None:
71
+ return None
72
+ diff = c(n._value, v) # noqa
73
+ if diff == 0:
74
+ return n
75
+ elif diff < 0:
76
+ n = n._right # noqa
77
+ else:
78
+ n = n._left # noqa
79
+
80
+
81
+ def union(
82
+ n: ta.Optional[TreapNode[T]],
83
+ other: ta.Optional[TreapNode[T]],
84
+ c: Comparer[T],
85
+ overwrite: bool,
86
+ ) -> ta.Optional[TreapNode[T]]:
87
+ if n is None:
88
+ return other
89
+ if other is None:
90
+ return n
91
+ if n._priority < other._priority:
92
+ other, n, overwrite = n, other, not overwrite
93
+ left, dupe, right = split(other, n._value, c)
94
+ value = n._value
95
+ if overwrite and dupe is not None:
96
+ value = dupe._value
97
+ left = union(n._left, left, c, overwrite)
98
+ right = union(n._right, right, c, overwrite)
99
+ return TreapNode(_value=value, _priority=n._priority, _left=left, _right=right)
100
+
101
+
102
+ def split(
103
+ n: ta.Optional[TreapNode[T]],
104
+ v: T,
105
+ c: Comparer[T],
106
+ ) -> tuple[
107
+ ta.Optional[TreapNode[T]],
108
+ ta.Optional[TreapNode[T]],
109
+ ta.Optional[TreapNode[T]],
110
+ ]:
111
+ tmp: TreapNode[T] = TreapNode(_value=None, _priority=0, _left=None, _right=None) # type: ignore
112
+ leftp, rightp = [tmp, 'l'], [tmp, 'r']
113
+
114
+ def setp(p, o):
115
+ t, s = p
116
+ if s == 'l':
117
+ t._left = o
118
+ elif s == 'r':
119
+ t._right = o
120
+ else:
121
+ raise ValueError(p)
122
+
123
+ cur: ta.Optional[TreapNode[T]] = n
124
+ while True:
125
+ if cur is None:
126
+ setp(leftp, None)
127
+ setp(rightp, None)
128
+ return tmp._left, None, tmp._right # noqa
129
+
130
+ d = c(cur._value, v)
131
+ if d < 0:
132
+ root = TreapNode(_value=cur._value, _priority=cur._priority, _left=cur._left, _right=None)
133
+ setp(leftp, root)
134
+ leftp[0], leftp[1] = root, 'r'
135
+ cur = cur._right
136
+ elif d > 0:
137
+ root = TreapNode(_value=cur._value, _priority=cur._priority, _left=None, _right=cur._right)
138
+ setp(rightp, root)
139
+ rightp[0], rightp[1] = root, 'l'
140
+ cur = cur._left
141
+ else:
142
+ root = TreapNode(_value=cur._value, _priority=cur._priority, _left=None, _right=None)
143
+ setp(leftp, cur._left)
144
+ setp(rightp, cur._right)
145
+ return tmp._left, root, tmp._right
146
+
147
+
148
+ def intersect(
149
+ n: ta.Optional[TreapNode[T]],
150
+ other: ta.Optional[TreapNode[T]],
151
+ c: Comparer[T],
152
+ ) -> ta.Optional[TreapNode[T]]:
153
+ if n is None or other is None:
154
+ return None
155
+
156
+ if n._priority < other._priority:
157
+ n, other = other, n
158
+
159
+ left, found, right = split(other, n._value, c)
160
+ left = intersect(n._left, left, c)
161
+ right = intersect(n._right, right, c)
162
+
163
+ if found is None:
164
+ # TODO: use a destructive join as both left/right are copies
165
+ return _join(left, right)
166
+
167
+ return TreapNode(_value=n._value, _priority=n._priority, _left=left, _right=right)
168
+
169
+
170
+ def delete(n: ta.Optional[TreapNode[T]], v: T, c: Comparer[T]) -> ta.Optional[TreapNode[T]]:
171
+ left, _, right = split(n, v, c)
172
+ return _join(left, right)
173
+
174
+
175
+ def diff(n: ta.Optional[TreapNode[T]], other: ta.Optional[TreapNode[T]], c: Comparer[T]) -> ta.Optional[TreapNode[T]]:
176
+ if n is None or other is None:
177
+ return n
178
+
179
+ # TODO -- use count
180
+ if n._priority >= other._priority:
181
+ left, dupe, right = split(other, n._value, c)
182
+ left, right = diff(n._left, left, c), diff(n._right, right, c)
183
+ if dupe is not None:
184
+ return _join(left, right)
185
+ return TreapNode(_value=n._value, _priority=n._priority, _left=left, _right=right)
186
+
187
+ left, _, right = split(n, other._value, c)
188
+ left = diff(left, other._left, c)
189
+ right = diff(right, other._right, c)
190
+ return _join(left, right)
191
+
192
+
193
+ def _join(n: ta.Optional[TreapNode[T]], other: ta.Optional[TreapNode[T]]) -> ta.Optional[TreapNode[T]]:
194
+ result: ta.Optional[TreapNode[T]] = None
195
+ resultp: list[ta.Any] = [None, None]
196
+
197
+ def setresultp(o):
198
+ t, s = resultp
199
+ if t is None:
200
+ nonlocal result
201
+ result = o
202
+ elif s == 'l':
203
+ t._left = o
204
+ elif s == 'r':
205
+ t._right = o
206
+ else:
207
+ raise ValueError(resultp)
208
+
209
+ cur: ta.Optional[TreapNode[T]] = n
210
+ while True:
211
+ if cur is None:
212
+ setresultp(other)
213
+ return result
214
+
215
+ if other is None:
216
+ setresultp(cur)
217
+ return result
218
+
219
+ if cur._priority <= other._priority:
220
+ root = TreapNode(_value=cur._value, _priority=cur._priority, _left=cur._left, _right=None)
221
+ setresultp(root)
222
+ resultp[0], resultp[1] = root, 'r'
223
+ cur = cur._right
224
+ else:
225
+ root = TreapNode(_value=other._value, _priority=other._priority, _left=None, _right=other._right)
226
+ setresultp(root)
227
+ resultp[0], resultp[1] = root, 'l'
228
+ other = other._left
@@ -0,0 +1,144 @@
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Gabriel Ochsenhofer
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
8
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
9
+ persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
12
+ Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
15
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
+ """
19
+ import random
20
+ import typing as ta
21
+
22
+ from . import treap
23
+ from .persistent import PersistentMap
24
+
25
+
26
+ K = ta.TypeVar('K')
27
+ V = ta.TypeVar('V')
28
+
29
+
30
+ class TreapMap(PersistentMap[K, V]):
31
+ __slots__ = ('_n', '_c')
32
+
33
+ def __init__(
34
+ self,
35
+ *,
36
+ _n: ta.Optional[treap.TreapNode[tuple[K, V]]],
37
+ _c: treap.Comparer[tuple[K, V]],
38
+ ) -> None:
39
+ super().__init__()
40
+
41
+ self._n = _n
42
+ self._c = _c
43
+
44
+ def __len__(self) -> int:
45
+ # TODO: memo
46
+ # TODO: itertools lol
47
+ if self._n is None:
48
+ return 0
49
+ result = 0
50
+ for _ in self._n:
51
+ result += 1
52
+ return result
53
+
54
+ def __contains__(self, item: K) -> bool:
55
+ try:
56
+ self[item] # noqa
57
+ except KeyError:
58
+ return False
59
+ else:
60
+ return True
61
+
62
+ def __getitem__(self, item: K) -> V:
63
+ n = treap.find(self._n, (item, None), self._c) # type: ignore
64
+ if n is None:
65
+ raise KeyError(item)
66
+ return n.value
67
+
68
+ def __iter__(self) -> ta.Iterator[tuple[K, V]]:
69
+ i = self.iterate()
70
+ while i.has_next():
71
+ yield i.next()
72
+
73
+ def iterate(self) -> 'TreapMapIterator[K, V]':
74
+ i = TreapMapIterator(
75
+ _st=[],
76
+ _n=self._n,
77
+ _b=False,
78
+ )
79
+ while (n := i._n) is not None and n.left is not None: # noqa
80
+ i._st.append(n) # noqa
81
+ i._n = n.left # noqa
82
+ return i
83
+
84
+ def with_(self, k: K, v: V) -> 'TreapMap[K, V]':
85
+ node = treap.TreapNode(
86
+ _value=(k, v),
87
+ _priority=int(random.random() * 0xFFFFFFFF),
88
+ _left=None,
89
+ _right=None,
90
+ )
91
+ n = treap.union(self._n, node, self._c, True)
92
+ return TreapMap(_n=n, _c=self._c)
93
+
94
+ def without(self, k: K) -> 'TreapMap[K, V]':
95
+ n = treap.delete(self._n, (k, None), self._c) # type: ignore
96
+ return TreapMap(_n=n, _c=self._c)
97
+
98
+ def default(self, k: K, v: V) -> 'TreapMap[K, V]':
99
+ try:
100
+ self[k] # noqa
101
+ except KeyError:
102
+ return self.with_(k, v)
103
+ else:
104
+ return self
105
+
106
+
107
+ def new_treap_map(cmp: ta.Callable[[tuple[K, V], tuple[K, V]], int]) -> PersistentMap[K, V]:
108
+ return TreapMap(_n=None, _c=cmp)
109
+
110
+
111
+ class TreapMapIterator(ta.Generic[K, V]):
112
+ __slots__ = ('_st', '_n', '_b')
113
+
114
+ def __init__(
115
+ self,
116
+ *,
117
+ _st: list[treap.TreapNode[tuple[K, V]]],
118
+ _n: ta.Optional[treap.TreapNode[tuple[K, V]]],
119
+ _b: bool,
120
+ ) -> None:
121
+ super().__init__()
122
+
123
+ self._st = _st
124
+ self._n = _n
125
+ self._b = _b
126
+
127
+ def has_next(self) -> bool:
128
+ return self._n is not None
129
+
130
+ def next(self) -> tuple[K, V]:
131
+ n = self._n
132
+ if n is None:
133
+ raise StopIteration
134
+ if n.right is not None:
135
+ self._n = n.right
136
+ while self._n.left is not None:
137
+ self._st.append(self._n)
138
+ self._n = self._n.left
139
+ elif len(self._st) > 0:
140
+ self._n = self._st[-1]
141
+ self._st.pop()
142
+ else:
143
+ self._n = None
144
+ return n.value
@@ -0,0 +1,174 @@
1
+ import typing as ta
2
+
3
+ from .. import lang
4
+
5
+
6
+ T = ta.TypeVar('T')
7
+ K = ta.TypeVar('K')
8
+ V = ta.TypeVar('V')
9
+
10
+
11
+ class Unmodifiable(lang.Abstract):
12
+ pass
13
+
14
+
15
+ class UnmodifiableSequence(ta.Sequence[T], Unmodifiable, lang.Final):
16
+
17
+ def __init__(self, target: ta.Sequence[T]) -> None:
18
+ super().__init__()
19
+
20
+ if target is None:
21
+ raise TypeError(target)
22
+ self._target = target
23
+
24
+ def __repr__(self) -> str:
25
+ return '%s(%r)' % (type(self).__name__, self._target)
26
+
27
+ def __contains__(self, x: object) -> bool:
28
+ return x in self._target
29
+
30
+ def __eq__(self, o: object) -> bool:
31
+ return self._target == o
32
+
33
+ def __ge__(self, other: object) -> bool:
34
+ return self._target >= other # type: ignore
35
+
36
+ def __getitem__(self, i: ta.Union[int, slice]) -> T: # type: ignore
37
+ return self._target[i] # type: ignore
38
+
39
+ def __gt__(self, other: object) -> bool:
40
+ return self._target > other # type: ignore
41
+
42
+ def __iter__(self) -> ta.Iterator[T]:
43
+ return iter(self._target)
44
+
45
+ def __le__(self, other: object) -> bool:
46
+ return self._target <= other # type: ignore
47
+
48
+ def __len__(self) -> int:
49
+ return len(self._target)
50
+
51
+ def __lt__(self, other: object) -> bool:
52
+ return self._target < other # type: ignore
53
+
54
+ def __ne__(self, o: object) -> bool:
55
+ return self._target != o
56
+
57
+ def __reversed__(self) -> ta.Iterator[T]:
58
+ return reversed(self._target)
59
+
60
+ def count(self, x: ta.Any) -> int:
61
+ return self._target.count(x)
62
+
63
+ def index(self, x: ta.Any, *args, **kwargs) -> int: # type: ignore
64
+ return self._target.index(x, *args, **kwargs)
65
+
66
+
67
+ class UnmodifiableSet(ta.AbstractSet[T], Unmodifiable, lang.Final):
68
+
69
+ def __init__(self, target: ta.AbstractSet[T]) -> None:
70
+ super().__init__()
71
+
72
+ if target is None:
73
+ raise TypeError(target)
74
+ self._target = target
75
+
76
+ def __repr__(self) -> str:
77
+ return '%s(%r)' % (type(self).__name__, self._target)
78
+
79
+ def __and__(self, s: ta.AbstractSet[ta.Any]) -> ta.AbstractSet[T]:
80
+ return self._target & s
81
+
82
+ def __contains__(self, x: object) -> bool:
83
+ return x in self._target
84
+
85
+ def __eq__(self, o: object) -> bool:
86
+ return self._target == o
87
+
88
+ def __ge__(self, s: ta.AbstractSet[ta.Any]) -> bool:
89
+ return self._target >= s
90
+
91
+ def __gt__(self, s: ta.AbstractSet[ta.Any]) -> bool:
92
+ return self._target > s
93
+
94
+ def __iter__(self) -> ta.Iterator[T]:
95
+ return iter(self._target)
96
+
97
+ def __le__(self, s: ta.AbstractSet[ta.Any]) -> bool:
98
+ return self._target <= s
99
+
100
+ def __len__(self) -> int:
101
+ return len(self._target)
102
+
103
+ def __lt__(self, s: ta.AbstractSet[ta.Any]) -> bool:
104
+ return self._target > s
105
+
106
+ def __ne__(self, o: object) -> bool:
107
+ return self._target != o
108
+
109
+ def __or__(self, s: ta.AbstractSet[T]) -> ta.AbstractSet[T]: # type: ignore
110
+ return self._target | s
111
+
112
+ def __sub__(self, s: ta.AbstractSet[ta.Any]) -> ta.AbstractSet[T]:
113
+ return self._target - s
114
+
115
+ def __xor__(self, s: ta.AbstractSet[T]) -> ta.AbstractSet[T]: # type: ignore
116
+ return self._target ^ s
117
+
118
+ def isdisjoint(self, s: ta.Iterable[ta.Any]) -> bool:
119
+ return self._target.isdisjoint(s)
120
+
121
+
122
+ class UnmodifiableMapping(ta.Mapping[K, V], Unmodifiable, lang.Final):
123
+
124
+ def __init__(self, target: ta.Mapping[K, V]) -> None:
125
+ super().__init__()
126
+
127
+ if target is None:
128
+ raise TypeError(target)
129
+ self._target = target
130
+
131
+ def __repr__(self) -> str:
132
+ return '%s(%r)' % (type(self).__name__, self._target)
133
+
134
+ def __contains__(self, o: object) -> bool:
135
+ return o in self._target
136
+
137
+ def __eq__(self, o: object) -> bool:
138
+ return self._target == o
139
+
140
+ def __ge__(self, other: object) -> bool:
141
+ return self._target >= other # type: ignore
142
+
143
+ def __getitem__(self, k: K) -> V:
144
+ return self._target[k]
145
+
146
+ def __gt__(self, other: object) -> bool:
147
+ return self._target > other # type: ignore
148
+
149
+ def __iter__(self) -> ta.Iterator[T]:
150
+ return iter(self._target) # type: ignore
151
+
152
+ def __le__(self, other: object) -> bool:
153
+ return self._target <= other # type: ignore
154
+
155
+ def __len__(self) -> int:
156
+ return len(self._target)
157
+
158
+ def __lt__(self, other: object) -> bool:
159
+ return self._target < other # type: ignore
160
+
161
+ def __ne__(self, o: object) -> bool:
162
+ return self._target != o
163
+
164
+ def get(self, k: K, default=None) -> ta.Optional[V]: # type: ignore
165
+ return self._target.get(k)
166
+
167
+ def items(self) -> ta.ItemsView[K, V]:
168
+ return self._target.items()
169
+
170
+ def keys(self) -> ta.KeysView[K]:
171
+ return self._target.keys()
172
+
173
+ def values(self) -> ta.ValuesView[V]:
174
+ return self._target.values()
@@ -0,0 +1,110 @@
1
+ import functools
2
+ import itertools
3
+ import typing as ta
4
+
5
+ from .. import check
6
+ from .identity import IdentityKeyDict
7
+ from .identity import IdentitySet
8
+
9
+
10
+ T = ta.TypeVar('T')
11
+ K = ta.TypeVar('K')
12
+ V = ta.TypeVar('V')
13
+
14
+
15
+ def mut_toposort(data: dict[T, set[T]]) -> ta.Iterator[set[T]]:
16
+ for k, v in data.items():
17
+ v.discard(k)
18
+ extra_items_in_deps = functools.reduce(set.union, data.values()) - set(data.keys())
19
+ data.update({item: set() for item in extra_items_in_deps})
20
+ while True:
21
+ ordered = set(item for item, dep in data.items() if not dep)
22
+ if not ordered:
23
+ break
24
+ yield ordered
25
+ data = {item: (dep - ordered) for item, dep in data.items() if item not in ordered}
26
+ if data:
27
+ raise ValueError('Cyclic dependencies exist among these items: ' + ' '.join(repr(x) for x in data.items()))
28
+
29
+
30
+ def toposort(data: ta.Mapping[T, ta.AbstractSet[T]]) -> ta.Iterator[set[T]]:
31
+ return mut_toposort({k: set(v) for k, v in data.items()})
32
+
33
+
34
+ def partition(items: ta.Iterable[T], pred: ta.Callable[[T], bool]) -> tuple[list[T], list[T]]:
35
+ t: list[T] = []
36
+ f: list[T] = []
37
+ for e in items:
38
+ if pred(e):
39
+ t.append(e)
40
+ else:
41
+ f.append(e)
42
+ return t, f
43
+
44
+
45
+ def unique(it: ta.Iterable[T], *, identity: bool = False) -> list[T]:
46
+ if isinstance(it, str):
47
+ raise TypeError(it)
48
+ ret: list[T] = []
49
+ seen: ta.MutableSet[T] = IdentitySet() if identity else set()
50
+ for e in it:
51
+ if e not in seen:
52
+ seen.add(e)
53
+ ret.append(e)
54
+ return ret
55
+
56
+
57
+ def unique_dict(items: ta.Iterable[tuple[K, V]], *, identity: bool = False) -> ta.MutableMapping[K, V]:
58
+ dct: ta.MutableMapping[K, V] = IdentityKeyDict() if identity else {}
59
+ for k, v in items:
60
+ if k in dct:
61
+ raise KeyError(k)
62
+ dct[k] = v
63
+ return dct
64
+
65
+
66
+ def all_equal(it: ta.Iterable[T]) -> bool:
67
+ i = iter(it)
68
+ try:
69
+ l = next(i)
70
+ except StopIteration:
71
+ return True
72
+ return all(r == l for r in i)
73
+
74
+
75
+ def all_not_equal(it: ta.Iterable[T]) -> bool:
76
+ s = set()
77
+ for v in it:
78
+ if v in s:
79
+ return False
80
+ s.add(v)
81
+ return True
82
+
83
+
84
+ def key_cmp(fn: ta.Callable[[K, K], int]) -> ta.Callable[[tuple[K, V], tuple[K, V]], int]:
85
+ return lambda t0, t1: fn(t0[0], t1[0])
86
+
87
+
88
+ def indexes(it: ta.Iterable[T]) -> dict[T, int]:
89
+ return {e: i for i, e in enumerate(it)}
90
+
91
+
92
+ def mut_unify_sets(sets: ta.Iterable[set[T]]) -> list[set[T]]:
93
+ rem: list[set[T]] = list(sets)
94
+ ret: list[set[T]] = []
95
+ while rem:
96
+ cur = rem.pop()
97
+ while True:
98
+ moved = False
99
+ for i in range(len(rem) - 1, -1, -1):
100
+ if any(e in cur for e in rem[i]):
101
+ cur.update(rem.pop(i))
102
+ moved = True
103
+ if not moved:
104
+ break
105
+ ret.append(cur)
106
+ if ret:
107
+ all_ = set(itertools.chain.from_iterable(ret))
108
+ num = sum(map(len, ret))
109
+ check.equal(len(all_), num)
110
+ return ret
File without changes