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/cache/impl.py
CHANGED
|
@@ -8,6 +8,7 @@ TODO:
|
|
|
8
8
|
- further cythonize hot path?
|
|
9
9
|
"""
|
|
10
10
|
import collections
|
|
11
|
+
import contextlib
|
|
11
12
|
import functools
|
|
12
13
|
import logging
|
|
13
14
|
import time
|
|
@@ -17,7 +18,7 @@ import weakref
|
|
|
17
18
|
from ... import lang
|
|
18
19
|
from .types import Cache
|
|
19
20
|
from .types import Eviction
|
|
20
|
-
from .types import
|
|
21
|
+
from .types import OverweightError
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
K = ta.TypeVar('K')
|
|
@@ -33,15 +34,15 @@ class SKIP(lang.Marker):
|
|
|
33
34
|
pass
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
def LRU(cache: 'Cache') -> None:
|
|
37
|
+
def LRU(cache: 'Cache') -> None: # noqa
|
|
37
38
|
cache._kill(cache._root.lru_next) # type: ignore # noqa
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
def LRI(cache: 'Cache') -> None:
|
|
41
|
+
def LRI(cache: 'Cache') -> None: # noqa
|
|
41
42
|
cache._kill(cache._root.ins_next) # type: ignore # noqa
|
|
42
43
|
|
|
43
44
|
|
|
44
|
-
def LFU(cache: 'Cache') -> None:
|
|
45
|
+
def LFU(cache: 'Cache') -> None: # noqa
|
|
45
46
|
cache._kill(cache._root.lfu_prev) # type: ignore # noqa
|
|
46
47
|
|
|
47
48
|
|
|
@@ -82,8 +83,8 @@ class CacheImpl(Cache[K, V]):
|
|
|
82
83
|
lru_next: 'CacheImpl.Link'
|
|
83
84
|
lfu_prev: 'CacheImpl.Link'
|
|
84
85
|
lfu_next: 'CacheImpl.Link'
|
|
85
|
-
key: ta.
|
|
86
|
-
value: ta.
|
|
86
|
+
key: ta.Any | weakref.ref
|
|
87
|
+
value: ta.Any | weakref.ref
|
|
87
88
|
weight: float
|
|
88
89
|
written: float
|
|
89
90
|
accessed: float
|
|
@@ -92,7 +93,7 @@ class CacheImpl(Cache[K, V]):
|
|
|
92
93
|
|
|
93
94
|
def __repr__(self) -> str:
|
|
94
95
|
return (
|
|
95
|
-
f'Link@{
|
|
96
|
+
f'Link@{self.seq!s}('
|
|
96
97
|
f'ins_prev={("@" + str(self.ins_prev.seq)) if self.ins_prev is not None else None}, '
|
|
97
98
|
f'ins_next={("@" + str(self.ins_next.seq)) if self.ins_next is not None else None}, '
|
|
98
99
|
f'lru_prev={("@" + str(self.lru_prev.seq)) if self.lru_prev is not None else None}, '
|
|
@@ -120,7 +121,7 @@ class CacheImpl(Cache[K, V]):
|
|
|
120
121
|
identity_keys: bool = False,
|
|
121
122
|
expire_after_access: float | None = None,
|
|
122
123
|
expire_after_write: float | None = None,
|
|
123
|
-
removal_listener: ta.Callable[[
|
|
124
|
+
removal_listener: ta.Callable[[K | weakref.ref, V | weakref.ref], None] | None = None,
|
|
124
125
|
clock: ta.Callable[[], float] | None = None,
|
|
125
126
|
weak_keys: bool = False,
|
|
126
127
|
weak_values: bool = False,
|
|
@@ -165,7 +166,7 @@ class CacheImpl(Cache[K, V]):
|
|
|
165
166
|
if self._track_frequency:
|
|
166
167
|
self._root.lfu_next = self._root.lfu_prev = self._root
|
|
167
168
|
|
|
168
|
-
weak_dead:
|
|
169
|
+
weak_dead: collections.deque[CacheImpl.Link] | None
|
|
169
170
|
if weak_keys or weak_values:
|
|
170
171
|
weak_dead = collections.deque()
|
|
171
172
|
weak_dead_ref = weakref.ref(weak_dead)
|
|
@@ -276,10 +277,8 @@ class CacheImpl(Cache[K, V]):
|
|
|
276
277
|
raise Exception
|
|
277
278
|
|
|
278
279
|
def fail():
|
|
279
|
-
|
|
280
|
+
with contextlib.suppress(KeyError):
|
|
280
281
|
del self._cache[cache_key]
|
|
281
|
-
except KeyError:
|
|
282
|
-
pass
|
|
283
282
|
self._unlink(link)
|
|
284
283
|
raise KeyError(key)
|
|
285
284
|
|
|
@@ -309,7 +308,7 @@ class CacheImpl(Cache[K, V]):
|
|
|
309
308
|
link, value = self._get_link(key)
|
|
310
309
|
except KeyError:
|
|
311
310
|
self._misses += 1
|
|
312
|
-
raise KeyError(key)
|
|
311
|
+
raise KeyError(key) from None
|
|
313
312
|
|
|
314
313
|
if link.lru_next is not self._root:
|
|
315
314
|
link.lru_prev.lru_next = link.lru_next
|
|
@@ -340,7 +339,7 @@ class CacheImpl(Cache[K, V]):
|
|
|
340
339
|
return value
|
|
341
340
|
|
|
342
341
|
@staticmethod
|
|
343
|
-
def _weak_die(dead_ref: weakref.ref, link: Link, key_ref: weakref.ref) -> None:
|
|
342
|
+
def _weak_die(dead_ref: weakref.ref, link: Link, key_ref: weakref.ref) -> None: # noqa
|
|
344
343
|
dead = dead_ref()
|
|
345
344
|
if dead is not None:
|
|
346
345
|
dead.append(link)
|
|
@@ -372,7 +371,7 @@ class CacheImpl(Cache[K, V]):
|
|
|
372
371
|
|
|
373
372
|
if self._max_weight is not None and weight > self._max_weight:
|
|
374
373
|
if self._raise_overweight:
|
|
375
|
-
raise
|
|
374
|
+
raise OverweightError
|
|
376
375
|
else:
|
|
377
376
|
return
|
|
378
377
|
|
|
@@ -387,10 +386,18 @@ class CacheImpl(Cache[K, V]):
|
|
|
387
386
|
self._eviction(self)
|
|
388
387
|
|
|
389
388
|
link = CacheImpl.Link()
|
|
389
|
+
|
|
390
390
|
self._seq += 1
|
|
391
391
|
link.seq = self._seq
|
|
392
|
-
|
|
393
|
-
|
|
392
|
+
|
|
393
|
+
def make_ref(o, b):
|
|
394
|
+
if not b:
|
|
395
|
+
return o
|
|
396
|
+
return weakref.ref(o, functools.partial(CacheImpl._weak_die, self._weak_dead_ref, link)) # type: ignore # noqa
|
|
397
|
+
|
|
398
|
+
link.key = make_ref(key, self._weak_keys)
|
|
399
|
+
link.value = make_ref(value, self._weak_values)
|
|
400
|
+
|
|
394
401
|
link.weight = weight
|
|
395
402
|
link.written = link.accessed = self._clock()
|
|
396
403
|
link.hits = 0
|
|
@@ -463,10 +470,10 @@ class CacheImpl(Cache[K, V]):
|
|
|
463
470
|
else:
|
|
464
471
|
yield key # type: ignore
|
|
465
472
|
|
|
466
|
-
|
|
467
|
-
if
|
|
473
|
+
nxt = link.ins_prev
|
|
474
|
+
if nxt is link:
|
|
468
475
|
raise ValueError
|
|
469
|
-
link =
|
|
476
|
+
link = nxt
|
|
470
477
|
|
|
471
478
|
@property
|
|
472
479
|
def stats(self) -> Cache.Stats:
|
omlish/collections/coerce.py
CHANGED
|
@@ -39,8 +39,8 @@ def seq(
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def opt_seq(
|
|
42
|
-
it: ta.
|
|
43
|
-
) -> ta.
|
|
42
|
+
it: ta.Iterable[T] | None,
|
|
43
|
+
) -> ta.Sequence[T] | None:
|
|
44
44
|
if it is None:
|
|
45
45
|
return None
|
|
46
46
|
else:
|
|
@@ -48,8 +48,8 @@ def opt_seq(
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def seq_or_none(
|
|
51
|
-
it: ta.
|
|
52
|
-
) -> ta.
|
|
51
|
+
it: ta.Iterable[T] | None,
|
|
52
|
+
) -> ta.Sequence[T] | None:
|
|
53
53
|
ret = opt_seq(it)
|
|
54
54
|
if ret:
|
|
55
55
|
return ret
|
|
@@ -58,7 +58,7 @@ def seq_or_none(
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def seq_of(
|
|
61
|
-
fn: ta.
|
|
61
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
62
62
|
) -> ta.Callable[[ta.Iterable[T]], ta.Sequence[T2]]:
|
|
63
63
|
def inner(it):
|
|
64
64
|
return seq(fn(e) for e in it) # type: ignore
|
|
@@ -68,8 +68,8 @@ def seq_of(
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
def opt_seq_of(
|
|
71
|
-
fn: ta.
|
|
72
|
-
) -> ta.Callable[[ta.
|
|
71
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
72
|
+
) -> ta.Callable[[ta.Iterable[T] | None], ta.Sequence[T2] | None]:
|
|
73
73
|
def inner(it):
|
|
74
74
|
if it is None:
|
|
75
75
|
return None
|
|
@@ -81,8 +81,8 @@ def opt_seq_of(
|
|
|
81
81
|
|
|
82
82
|
|
|
83
83
|
def seq_of_or_none(
|
|
84
|
-
fn: ta.
|
|
85
|
-
) -> ta.Callable[[ta.
|
|
84
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
85
|
+
) -> ta.Callable[[ta.Iterable[T] | None], ta.Sequence[T2] | None]:
|
|
86
86
|
def inner(it):
|
|
87
87
|
if it is None:
|
|
88
88
|
return None
|
|
@@ -115,8 +115,8 @@ def abs_set(
|
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
def opt_abs_set(
|
|
118
|
-
it: ta.
|
|
119
|
-
) -> ta.
|
|
118
|
+
it: ta.Iterable[T] | None,
|
|
119
|
+
) -> ta.AbstractSet[T] | None:
|
|
120
120
|
if it is None:
|
|
121
121
|
return None
|
|
122
122
|
else:
|
|
@@ -124,8 +124,8 @@ def opt_abs_set(
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
def abs_set_or_none(
|
|
127
|
-
it: ta.
|
|
128
|
-
) -> ta.
|
|
127
|
+
it: ta.Iterable[T] | None,
|
|
128
|
+
) -> ta.AbstractSet[T] | None:
|
|
129
129
|
ret = opt_abs_set(it)
|
|
130
130
|
if ret:
|
|
131
131
|
return ret
|
|
@@ -134,7 +134,7 @@ def abs_set_or_none(
|
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
def abs_set_of(
|
|
137
|
-
fn: ta.
|
|
137
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
138
138
|
) -> ta.Callable[[ta.Iterable[T]], ta.AbstractSet[T2]]:
|
|
139
139
|
def inner(it):
|
|
140
140
|
return abs_set(fn(e) for e in it) # type: ignore
|
|
@@ -144,8 +144,8 @@ def abs_set_of(
|
|
|
144
144
|
|
|
145
145
|
|
|
146
146
|
def opt_abs_set_of(
|
|
147
|
-
fn: ta.
|
|
148
|
-
) -> ta.Callable[[ta.
|
|
147
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
148
|
+
) -> ta.Callable[[ta.Iterable[T] | None], ta.AbstractSet[T2] | None]:
|
|
149
149
|
def inner(it):
|
|
150
150
|
if it is None:
|
|
151
151
|
return None
|
|
@@ -157,8 +157,8 @@ def opt_abs_set_of(
|
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
def abs_set_of_or_none(
|
|
160
|
-
fn: ta.
|
|
161
|
-
) -> ta.Callable[[ta.
|
|
160
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
161
|
+
) -> ta.Callable[[ta.Iterable[T] | None], ta.AbstractSet[T2] | None]:
|
|
162
162
|
def inner(it):
|
|
163
163
|
if it is None:
|
|
164
164
|
return None
|
|
@@ -191,8 +191,8 @@ def frozenset_(
|
|
|
191
191
|
|
|
192
192
|
|
|
193
193
|
def opt_frozenset(
|
|
194
|
-
it: ta.
|
|
195
|
-
) ->
|
|
194
|
+
it: ta.Iterable[T] | None,
|
|
195
|
+
) -> frozenset[T] | None:
|
|
196
196
|
if it is None:
|
|
197
197
|
return None
|
|
198
198
|
else:
|
|
@@ -200,8 +200,8 @@ def opt_frozenset(
|
|
|
200
200
|
|
|
201
201
|
|
|
202
202
|
def frozenset_or_none(
|
|
203
|
-
it: ta.
|
|
204
|
-
) ->
|
|
203
|
+
it: ta.Iterable[T] | None,
|
|
204
|
+
) -> frozenset[T] | None:
|
|
205
205
|
ret = opt_frozenset(it)
|
|
206
206
|
if ret:
|
|
207
207
|
return ret
|
|
@@ -210,7 +210,7 @@ def frozenset_or_none(
|
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
def frozenset_of(
|
|
213
|
-
fn: ta.
|
|
213
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
214
214
|
) -> ta.Callable[[ta.Iterable[T]], frozenset[T2]]:
|
|
215
215
|
def inner(it):
|
|
216
216
|
return frozenset_(fn(e) for e in it) # type: ignore
|
|
@@ -220,8 +220,8 @@ def frozenset_of(
|
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
def opt_frozenset_of(
|
|
223
|
-
fn: ta.
|
|
224
|
-
) -> ta.Callable[[ta.
|
|
223
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
224
|
+
) -> ta.Callable[[ta.Iterable[T] | None], frozenset[T2] | None]:
|
|
225
225
|
def inner(it):
|
|
226
226
|
if it is None:
|
|
227
227
|
return None
|
|
@@ -233,8 +233,8 @@ def opt_frozenset_of(
|
|
|
233
233
|
|
|
234
234
|
|
|
235
235
|
def frozenset_of_or_none(
|
|
236
|
-
fn: ta.
|
|
237
|
-
) -> ta.Callable[[ta.
|
|
236
|
+
fn: ta.Callable[[T], T2] | tuple,
|
|
237
|
+
) -> ta.Callable[[ta.Iterable[T] | None], frozenset[T2] | None]:
|
|
238
238
|
def inner(it):
|
|
239
239
|
if it is None:
|
|
240
240
|
return None
|
|
@@ -255,15 +255,15 @@ def frozenset_of_or_none(
|
|
|
255
255
|
# region map
|
|
256
256
|
|
|
257
257
|
|
|
258
|
-
def map(
|
|
259
|
-
src: ta.
|
|
258
|
+
def map( # noqa
|
|
259
|
+
src: ta.Mapping[K, V] | ta.Iterable[tuple[K, V]],
|
|
260
260
|
) -> ta.Mapping[K, V]:
|
|
261
261
|
return FrozenDict(src)
|
|
262
262
|
|
|
263
263
|
|
|
264
264
|
def opt_map(
|
|
265
|
-
src: ta.
|
|
266
|
-
) -> ta.
|
|
265
|
+
src: ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None,
|
|
266
|
+
) -> ta.Mapping[K, V] | None:
|
|
267
267
|
if src is None:
|
|
268
268
|
return None
|
|
269
269
|
else:
|
|
@@ -271,8 +271,8 @@ def opt_map(
|
|
|
271
271
|
|
|
272
272
|
|
|
273
273
|
def map_or_none(
|
|
274
|
-
src: ta.
|
|
275
|
-
) -> ta.
|
|
274
|
+
src: ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None,
|
|
275
|
+
) -> ta.Mapping[K, V] | None:
|
|
276
276
|
ret = opt_map(src)
|
|
277
277
|
if ret:
|
|
278
278
|
return ret
|
|
@@ -281,10 +281,10 @@ def map_or_none(
|
|
|
281
281
|
|
|
282
282
|
|
|
283
283
|
def map_of(
|
|
284
|
-
key_fn: ta.
|
|
285
|
-
value_fn: ta.
|
|
284
|
+
key_fn: ta.Callable[[K], K2] | tuple,
|
|
285
|
+
value_fn: ta.Callable[[V], V2] | tuple,
|
|
286
286
|
) -> ta.Callable[
|
|
287
|
-
[ta.
|
|
287
|
+
[ta.Mapping[K, V] | ta.Iterable[tuple[K, V]]],
|
|
288
288
|
ta.Mapping[K2, V2],
|
|
289
289
|
]:
|
|
290
290
|
def inner(src):
|
|
@@ -296,11 +296,11 @@ def map_of(
|
|
|
296
296
|
|
|
297
297
|
|
|
298
298
|
def opt_map_of(
|
|
299
|
-
key_fn: ta.
|
|
300
|
-
value_fn: ta.
|
|
299
|
+
key_fn: ta.Callable[[K], K2] | tuple,
|
|
300
|
+
value_fn: ta.Callable[[V], V2] | tuple,
|
|
301
301
|
) -> ta.Callable[
|
|
302
|
-
[ta.
|
|
303
|
-
ta.
|
|
302
|
+
[ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None],
|
|
303
|
+
ta.Mapping[K2, V2] | None,
|
|
304
304
|
]:
|
|
305
305
|
def inner(src):
|
|
306
306
|
if src is None:
|
|
@@ -314,11 +314,11 @@ def opt_map_of(
|
|
|
314
314
|
|
|
315
315
|
|
|
316
316
|
def map_of_or_none(
|
|
317
|
-
key_fn: ta.
|
|
318
|
-
value_fn: ta.
|
|
317
|
+
key_fn: ta.Callable[[K], K2] | tuple,
|
|
318
|
+
value_fn: ta.Callable[[V], V2] | tuple,
|
|
319
319
|
) -> ta.Callable[
|
|
320
|
-
[ta.
|
|
321
|
-
ta.
|
|
320
|
+
[ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None],
|
|
321
|
+
ta.Mapping[K2, V2] | None,
|
|
322
322
|
]:
|
|
323
323
|
def inner(src):
|
|
324
324
|
if src is None:
|
omlish/collections/frozen.py
CHANGED
|
@@ -17,7 +17,7 @@ class Frozen(ta.Hashable, abc.ABC):
|
|
|
17
17
|
|
|
18
18
|
class FrozenDict(ta.Mapping[K, V], Frozen):
|
|
19
19
|
|
|
20
|
-
def __new__(cls, *args, **kwargs) -> 'FrozenDict[K, V]':
|
|
20
|
+
def __new__(cls, *args: ta.Any, **kwargs: ta.Any) -> 'FrozenDict[K, V]': # noqa
|
|
21
21
|
if len(args) == 1 and Frozen in type(args[0]).__bases__:
|
|
22
22
|
return args[0]
|
|
23
23
|
return super().__new__(cls)
|
|
@@ -35,10 +35,10 @@ class FrozenDict(ta.Mapping[K, V], Frozen):
|
|
|
35
35
|
return dict(self._dct)
|
|
36
36
|
|
|
37
37
|
def __repr__(self) -> str:
|
|
38
|
-
return '(
|
|
38
|
+
return f'({self._dct!r})'
|
|
39
39
|
|
|
40
40
|
def __eq__(self, other) -> bool:
|
|
41
|
-
return type(self)
|
|
41
|
+
return type(self) is type(other) and self._dct == other._dct
|
|
42
42
|
|
|
43
43
|
def __getitem__(self, key: K) -> V:
|
|
44
44
|
return self._dct[key]
|
|
@@ -63,29 +63,29 @@ class FrozenDict(ta.Mapping[K, V], Frozen):
|
|
|
63
63
|
def __setstate__(self, t):
|
|
64
64
|
self.__init__(t) # type: ignore
|
|
65
65
|
|
|
66
|
-
def drop(self, *keys):
|
|
66
|
+
def drop(self, *keys: T) -> 'FrozenDict[K, V]':
|
|
67
67
|
ks = frozenset(keys)
|
|
68
68
|
return type(self)((k, self[k]) for k in self if k not in ks)
|
|
69
69
|
|
|
70
|
-
def set(self, *args, **kwargs):
|
|
70
|
+
def set(self, *args: ta.Any, **kwargs: ta.Any) -> 'FrozenDict[K, V]':
|
|
71
71
|
new = type(self)(*args, **kwargs)
|
|
72
72
|
return type(self)(itertools.chain(self.items(), new.items()))
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
class FrozenList(ta.Sequence[T], Frozen):
|
|
76
76
|
|
|
77
|
-
def __init__(self, it: ta.
|
|
77
|
+
def __init__(self, it: ta.Iterable[T] | None = None) -> None:
|
|
78
78
|
super().__init__()
|
|
79
79
|
|
|
80
80
|
self._tup: tuple = tuple(it) if it is not None else ()
|
|
81
|
-
self._hash:
|
|
81
|
+
self._hash: int | None = None
|
|
82
82
|
|
|
83
83
|
@property
|
|
84
84
|
def debug(self) -> ta.Sequence[T]:
|
|
85
85
|
return list(self)
|
|
86
86
|
|
|
87
87
|
def __repr__(self) -> str:
|
|
88
|
-
return '([
|
|
88
|
+
return f'([{", ".join(map(repr, self._tup))}])'
|
|
89
89
|
|
|
90
90
|
def __add__(self, o) -> 'FrozenList[T]':
|
|
91
91
|
if isinstance(o, FrozenList):
|
|
@@ -111,7 +111,7 @@ class FrozenList(ta.Sequence[T], Frozen):
|
|
|
111
111
|
self._hash = hash(self._tup)
|
|
112
112
|
return self._hash
|
|
113
113
|
|
|
114
|
-
def __getitem__(self, idx:
|
|
114
|
+
def __getitem__(self, idx: int | slice) -> 'FrozenList[T]': # type: ignore
|
|
115
115
|
if isinstance(idx, int):
|
|
116
116
|
return self._tup[idx]
|
|
117
117
|
else:
|
omlish/collections/identity.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
import operator as op
|
|
2
3
|
import typing as ta
|
|
3
4
|
|
|
@@ -63,13 +64,13 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
|
|
|
63
64
|
def __iter__(self) -> ta.Iterator[K]:
|
|
64
65
|
return iter(map(op.itemgetter(0), self._dict.values()))
|
|
65
66
|
|
|
66
|
-
def clear(self):
|
|
67
|
+
def clear(self) -> None:
|
|
67
68
|
self._dict.clear()
|
|
68
69
|
|
|
69
70
|
|
|
70
71
|
class IdentitySet(ta.MutableSet[T]):
|
|
71
72
|
|
|
72
|
-
def __init__(self, init: ta.
|
|
73
|
+
def __init__(self, init: ta.Iterable[T] | None = None) -> None:
|
|
73
74
|
super().__init__()
|
|
74
75
|
self._dict: dict[int, T] = {}
|
|
75
76
|
if init is not None:
|
|
@@ -87,10 +88,8 @@ class IdentitySet(ta.MutableSet[T]):
|
|
|
87
88
|
self._dict[id(item)] = item
|
|
88
89
|
|
|
89
90
|
def discard(self, item: T) -> None:
|
|
90
|
-
|
|
91
|
+
with contextlib.suppress(KeyError):
|
|
91
92
|
del self._dict[id(item)]
|
|
92
|
-
except KeyError:
|
|
93
|
-
pass
|
|
94
93
|
|
|
95
94
|
def update(self, items: ta.Iterable[T]) -> None:
|
|
96
95
|
for item in items:
|
omlish/collections/mappings.py
CHANGED
|
@@ -8,7 +8,7 @@ K = ta.TypeVar('K')
|
|
|
8
8
|
V = ta.TypeVar('V')
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def multikey_dict(dct: ta.Mapping[ta.
|
|
11
|
+
def multikey_dict(dct: ta.Mapping[ta.Iterable[K] | K, V], *, deep: bool = False) -> dict[K, V]:
|
|
12
12
|
ret = {}
|
|
13
13
|
for k, v in dct.items():
|
|
14
14
|
if deep and isinstance(v, dict):
|
|
@@ -23,7 +23,7 @@ def multikey_dict(dct: ta.Mapping[ta.Union[ta.Iterable[K], K], V], *, deep: bool
|
|
|
23
23
|
|
|
24
24
|
def guarded_map_update(
|
|
25
25
|
dst: ta.MutableMapping[ta.Any, ta.Any],
|
|
26
|
-
*srcs: ta.Mapping[ta.Any, ta.Any]
|
|
26
|
+
*srcs: ta.Mapping[ta.Any, ta.Any],
|
|
27
27
|
) -> ta.MutableMapping[ta.Any, ta.Any]:
|
|
28
28
|
for src in srcs:
|
|
29
29
|
for k, v in src.items():
|
|
@@ -68,10 +68,10 @@ class TypeMap(ta.Generic[T]):
|
|
|
68
68
|
def __len__(self) -> int:
|
|
69
69
|
return len(self._items)
|
|
70
70
|
|
|
71
|
-
def __iter__(self) -> ta.
|
|
71
|
+
def __iter__(self) -> ta.Iterator[T]:
|
|
72
72
|
return iter(self._items)
|
|
73
73
|
|
|
74
|
-
def get(self, ty: type[T]) ->
|
|
74
|
+
def get(self, ty: type[T]) -> T | None:
|
|
75
75
|
return self._dct.get(ty)
|
|
76
76
|
|
|
77
77
|
def __getitem__(self, ty: type[T]) -> ta.Sequence[T]:
|
|
@@ -99,7 +99,7 @@ class TypeMultiMap(ta.Generic[V]):
|
|
|
99
99
|
def __len__(self) -> int:
|
|
100
100
|
return len(self._items)
|
|
101
101
|
|
|
102
|
-
def __iter__(self) -> ta.
|
|
102
|
+
def __iter__(self) -> ta.Iterator[V]:
|
|
103
103
|
return iter(self._items)
|
|
104
104
|
|
|
105
105
|
def __getitem__(self, ty: type[T]) -> ta.Sequence[T]:
|
omlish/collections/ordered.py
CHANGED
|
@@ -6,7 +6,7 @@ T = ta.TypeVar('T')
|
|
|
6
6
|
|
|
7
7
|
class OrderedSet(ta.MutableSet[T]):
|
|
8
8
|
|
|
9
|
-
def __init__(self, iterable: ta.
|
|
9
|
+
def __init__(self, iterable: ta.Iterable[T] | None = None) -> None:
|
|
10
10
|
super().__init__()
|
|
11
11
|
self._dct: dict[T, ta.Any] = {}
|
|
12
12
|
if iterable is not None:
|
|
@@ -37,17 +37,17 @@ class OrderedSet(ta.MutableSet[T]):
|
|
|
37
37
|
def __reversed__(self):
|
|
38
38
|
return reversed(self._dct.keys())
|
|
39
39
|
|
|
40
|
-
def pop(self, last=True):
|
|
40
|
+
def pop(self, last: bool = True) -> T:
|
|
41
41
|
if not self:
|
|
42
42
|
raise KeyError('set is empty')
|
|
43
43
|
item = next(reversed(self._dct.keys()))
|
|
44
44
|
self.discard(item)
|
|
45
45
|
return item
|
|
46
46
|
|
|
47
|
-
def __repr__(self):
|
|
47
|
+
def __repr__(self) -> str:
|
|
48
48
|
if not self:
|
|
49
|
-
return '
|
|
50
|
-
return '
|
|
49
|
+
return f'{self.__class__.__name__}()'
|
|
50
|
+
return f'{self.__class__.__name__}({list(self)!r})'
|
|
51
51
|
|
|
52
52
|
def __eq__(self, other) -> bool:
|
|
53
53
|
if isinstance(other, OrderedSet):
|
|
@@ -55,11 +55,11 @@ class OrderedSet(ta.MutableSet[T]):
|
|
|
55
55
|
return set(self) == set(other)
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
class OrderedFrozenSet(ta.FrozenSet[T]):
|
|
58
|
+
class OrderedFrozenSet(ta.FrozenSet[T]): # noqa
|
|
59
59
|
|
|
60
60
|
_list: ta.Sequence[T]
|
|
61
61
|
|
|
62
|
-
def __new__(cls, items: ta.Iterable[T]) ->
|
|
62
|
+
def __new__(cls, items: ta.Iterable[T]) -> frozenset[T]: # type: ignore
|
|
63
63
|
item_set = set()
|
|
64
64
|
item_list = []
|
|
65
65
|
for item in items:
|
|
@@ -76,6 +76,6 @@ class OrderedFrozenSet(ta.FrozenSet[T]):
|
|
|
76
76
|
def __iter__(self) -> ta.Iterator[T]:
|
|
77
77
|
return iter(self._list)
|
|
78
78
|
|
|
79
|
-
def __sub__(self, other: ta.Iterable[T]) ->
|
|
79
|
+
def __sub__(self, other: ta.Iterable[T]) -> frozenset[T]:
|
|
80
80
|
s = set(other)
|
|
81
81
|
return type(self)(i for i in self if i not in s)
|
omlish/collections/skiplist.py
CHANGED
|
@@ -27,7 +27,7 @@ class SkipList(SortedCollection[T]):
|
|
|
27
27
|
def __init__(
|
|
28
28
|
self,
|
|
29
29
|
value: T,
|
|
30
|
-
level: int
|
|
30
|
+
level: int,
|
|
31
31
|
) -> None:
|
|
32
32
|
super().__init__()
|
|
33
33
|
|
|
@@ -46,7 +46,7 @@ class SkipList(SortedCollection[T]):
|
|
|
46
46
|
self,
|
|
47
47
|
*,
|
|
48
48
|
max_height: int = 16,
|
|
49
|
-
comparator:
|
|
49
|
+
comparator: SortedCollection.Comparator[T] | None = None,
|
|
50
50
|
) -> None:
|
|
51
51
|
super().__init__()
|
|
52
52
|
|
|
@@ -108,7 +108,7 @@ class SkipList(SortedCollection[T]):
|
|
|
108
108
|
self._length += 1
|
|
109
109
|
return True
|
|
110
110
|
|
|
111
|
-
def _find(self, value: T) ->
|
|
111
|
+
def _find(self, value: T) -> _Node | None:
|
|
112
112
|
if value is None:
|
|
113
113
|
raise TypeError(value)
|
|
114
114
|
|
|
@@ -120,7 +120,7 @@ class SkipList(SortedCollection[T]):
|
|
|
120
120
|
|
|
121
121
|
return cur.next[0]
|
|
122
122
|
|
|
123
|
-
def find(self, value: T) ->
|
|
123
|
+
def find(self, value: T) -> T | None:
|
|
124
124
|
node = self._find(value)
|
|
125
125
|
if node is None:
|
|
126
126
|
return None
|
|
@@ -157,7 +157,7 @@ class SkipList(SortedCollection[T]):
|
|
|
157
157
|
self._length -= 1
|
|
158
158
|
return True
|
|
159
159
|
|
|
160
|
-
def iter(self, base:
|
|
160
|
+
def iter(self, base: T | None = None) -> ta.Iterable[T]:
|
|
161
161
|
if base is not None:
|
|
162
162
|
cur = self._find(base)
|
|
163
163
|
while cur is not None and self._compare(base, cur.value) > 0: # type: ignore
|
|
@@ -169,7 +169,7 @@ class SkipList(SortedCollection[T]):
|
|
|
169
169
|
yield cur.value # type: ignore
|
|
170
170
|
cur = cur.next[0]
|
|
171
171
|
|
|
172
|
-
def riter(self, base:
|
|
172
|
+
def riter(self, base: T | None = None) -> ta.Iterable[T]:
|
|
173
173
|
if base is not None:
|
|
174
174
|
cur = self._find(base)
|
|
175
175
|
while cur is not self._head and self._compare(base, cur.value) < 0: # type: ignore
|
|
@@ -190,4 +190,4 @@ class SkipList(SortedCollection[T]):
|
|
|
190
190
|
class SkipListDict(SortedListDict[K, V]):
|
|
191
191
|
|
|
192
192
|
def __init__(self, *args, **kwargs) -> None:
|
|
193
|
-
super().__init__(SkipList(comparator=SortedListDict._item_comparator), *args, **kwargs)
|
|
193
|
+
super().__init__(SkipList(comparator=SortedListDict._item_comparator), *args, **kwargs) # noqa
|
omlish/collections/sorted.py
CHANGED
|
@@ -38,7 +38,7 @@ class SortedCollection(lang.Abstract, ta.Collection[T]):
|
|
|
38
38
|
raise NotImplementedError
|
|
39
39
|
|
|
40
40
|
@abc.abstractmethod
|
|
41
|
-
def find(self, value: T) ->
|
|
41
|
+
def find(self, value: T) -> T | None:
|
|
42
42
|
raise NotImplementedError
|
|
43
43
|
|
|
44
44
|
@abc.abstractmethod
|
|
@@ -46,11 +46,11 @@ class SortedCollection(lang.Abstract, ta.Collection[T]):
|
|
|
46
46
|
raise NotImplementedError
|
|
47
47
|
|
|
48
48
|
@abc.abstractmethod
|
|
49
|
-
def iter(self, base:
|
|
49
|
+
def iter(self, base: T | None = None) -> ta.Iterable[T]:
|
|
50
50
|
raise NotImplementedError
|
|
51
51
|
|
|
52
52
|
@abc.abstractmethod
|
|
53
|
-
def riter(self, base:
|
|
53
|
+
def riter(self, base: T | None = None) -> ta.Iterable[T]:
|
|
54
54
|
raise NotImplementedError
|
|
55
55
|
|
|
56
56
|
|
|
@@ -110,7 +110,7 @@ class SortedListDict(SortedMutableMapping[K, V]):
|
|
|
110
110
|
return len(self._impl)
|
|
111
111
|
|
|
112
112
|
def __iter__(self) -> ta.Iterator[K]:
|
|
113
|
-
for k,
|
|
113
|
+
for k, _ in self._impl:
|
|
114
114
|
yield k
|
|
115
115
|
|
|
116
116
|
def items(self) -> ta.Iterator[tuple[K, V]]: # type: ignore
|