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/inject/elements.py
CHANGED
|
@@ -25,9 +25,9 @@ class Elements(lang.Final):
|
|
|
25
25
|
yield from c
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def as_elements(*args:
|
|
28
|
+
def as_elements(*args: Element | Elements) -> Elements:
|
|
29
29
|
es: set[Element] = set()
|
|
30
|
-
cs: set[
|
|
30
|
+
cs: set[Elements] = set()
|
|
31
31
|
for a in args:
|
|
32
32
|
if isinstance(a, Element):
|
|
33
33
|
es.add(a)
|
omlish/inject/exceptions.py
CHANGED
|
@@ -9,25 +9,25 @@ from .types import Scope
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@dc.dataclass()
|
|
12
|
-
class
|
|
12
|
+
class BaseKeyError(Exception):
|
|
13
13
|
key: Key
|
|
14
14
|
|
|
15
15
|
source: ta.Any = None
|
|
16
|
-
name:
|
|
16
|
+
name: str | None = None
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
@dc.dataclass()
|
|
20
|
-
class
|
|
20
|
+
class UnboundKeyError(KeyError):
|
|
21
21
|
pass
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@dc.dataclass()
|
|
25
|
-
class
|
|
25
|
+
class DuplicateKeyError(KeyError):
|
|
26
26
|
pass
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@dc.dataclass()
|
|
30
|
-
class
|
|
30
|
+
class CyclicDependencyError(KeyError):
|
|
31
31
|
pass
|
|
32
32
|
|
|
33
33
|
|
|
@@ -35,15 +35,15 @@ class CyclicDependencyException(KeyException):
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
@dc.dataclass()
|
|
38
|
-
class
|
|
38
|
+
class ScopeError(Exception):
|
|
39
39
|
scope: Scope
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
@dc.dataclass()
|
|
43
|
-
class
|
|
43
|
+
class ScopeAlreadyOpenError(ScopeError):
|
|
44
44
|
pass
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
@dc.dataclass()
|
|
48
|
-
class
|
|
48
|
+
class ScopeNotOpenError(ScopeError):
|
|
49
49
|
pass
|
omlish/inject/impl/elements.py
CHANGED
|
@@ -25,7 +25,7 @@ from ..bindings import Binding
|
|
|
25
25
|
from ..eagers import Eager
|
|
26
26
|
from ..elements import Element
|
|
27
27
|
from ..elements import Elements
|
|
28
|
-
from ..exceptions import
|
|
28
|
+
from ..exceptions import DuplicateKeyError
|
|
29
29
|
from ..keys import Key
|
|
30
30
|
from ..overrides import Overrides
|
|
31
31
|
from ..private import Expose
|
|
@@ -51,7 +51,7 @@ class ElementCollection(lang.Final):
|
|
|
51
51
|
|
|
52
52
|
self._es = check.isinstance(es, Elements)
|
|
53
53
|
|
|
54
|
-
self._private_infos: ta.MutableMapping[Private,
|
|
54
|
+
self._private_infos: ta.MutableMapping[Private, private_.PrivateInfo] | None = None
|
|
55
55
|
|
|
56
56
|
##
|
|
57
57
|
|
|
@@ -98,7 +98,7 @@ class ElementCollection(lang.Final):
|
|
|
98
98
|
try:
|
|
99
99
|
bs = ovr[k]
|
|
100
100
|
except KeyError:
|
|
101
|
-
bs =
|
|
101
|
+
bs = b
|
|
102
102
|
add(k, *bs)
|
|
103
103
|
|
|
104
104
|
else:
|
|
@@ -139,7 +139,7 @@ class ElementCollection(lang.Final):
|
|
|
139
139
|
mm.setdefault(k, []).extend(bis)
|
|
140
140
|
else:
|
|
141
141
|
if len(bis) > 1:
|
|
142
|
-
raise
|
|
142
|
+
raise DuplicateKeyError(k)
|
|
143
143
|
[pm[k]] = bis
|
|
144
144
|
|
|
145
145
|
if mm:
|
omlish/inject/impl/injector.py
CHANGED
|
@@ -16,8 +16,8 @@ from ... import check
|
|
|
16
16
|
from ... import lang
|
|
17
17
|
from ..eagers import Eager
|
|
18
18
|
from ..elements import Elements
|
|
19
|
-
from ..exceptions import
|
|
20
|
-
from ..exceptions import
|
|
19
|
+
from ..exceptions import CyclicDependencyError
|
|
20
|
+
from ..exceptions import UnboundKeyError
|
|
21
21
|
from ..injector import Injector
|
|
22
22
|
from ..inspect import KwargsTarget
|
|
23
23
|
from ..keys import Key
|
|
@@ -45,7 +45,7 @@ class InjectorImpl(Injector, lang.Final):
|
|
|
45
45
|
super().__init__()
|
|
46
46
|
|
|
47
47
|
self._ec = check.isinstance(ec, ElementCollection)
|
|
48
|
-
self._p:
|
|
48
|
+
self._p: InjectorImpl | None = check.isinstance(p, (InjectorImpl, None))
|
|
49
49
|
|
|
50
50
|
self._internal_consts: dict[Key, ta.Any] = {
|
|
51
51
|
Key(Injector): self,
|
|
@@ -54,7 +54,7 @@ class InjectorImpl(Injector, lang.Final):
|
|
|
54
54
|
self._bim = ec.binding_impl_map()
|
|
55
55
|
|
|
56
56
|
self._cs: weakref.WeakSet[InjectorImpl] | None = None
|
|
57
|
-
self._root: InjectorImpl = p._root if p is not None else self
|
|
57
|
+
self._root: InjectorImpl = p._root if p is not None else self # noqa
|
|
58
58
|
|
|
59
59
|
self.__cur_req: InjectorImpl._Request | None = None
|
|
60
60
|
|
|
@@ -97,7 +97,7 @@ class InjectorImpl(Injector, lang.Final):
|
|
|
97
97
|
except KeyError:
|
|
98
98
|
pass
|
|
99
99
|
if key in self._seen_keys:
|
|
100
|
-
raise
|
|
100
|
+
raise CyclicDependencyError(key)
|
|
101
101
|
self._seen_keys.add(key)
|
|
102
102
|
return lang.empty()
|
|
103
103
|
|
|
@@ -154,7 +154,7 @@ class InjectorImpl(Injector, lang.Final):
|
|
|
154
154
|
v = self.try_provide(key)
|
|
155
155
|
if v.present:
|
|
156
156
|
return v.must()
|
|
157
|
-
raise
|
|
157
|
+
raise UnboundKeyError(key)
|
|
158
158
|
|
|
159
159
|
def provide_kwargs(self, kt: KwargsTarget) -> ta.Mapping[str, ta.Any]:
|
|
160
160
|
ret: dict[str, ta.Any] = {}
|
omlish/inject/impl/inspect.py
CHANGED
|
@@ -11,7 +11,7 @@ import typing as ta
|
|
|
11
11
|
import weakref
|
|
12
12
|
|
|
13
13
|
from ... import reflect as rfl
|
|
14
|
-
from ..exceptions import
|
|
14
|
+
from ..exceptions import DuplicateKeyError
|
|
15
15
|
from ..inspect import Kwarg
|
|
16
16
|
from ..inspect import KwargsTarget
|
|
17
17
|
from ..keys import Key
|
|
@@ -52,7 +52,7 @@ def build_kwargs_target(
|
|
|
52
52
|
obj: ta.Any,
|
|
53
53
|
*,
|
|
54
54
|
skip_args: int = 0,
|
|
55
|
-
skip_kwargs: ta.
|
|
55
|
+
skip_kwargs: ta.Iterable[ta.Any] | None = None,
|
|
56
56
|
raw_optional: bool = False,
|
|
57
57
|
) -> KwargsTarget:
|
|
58
58
|
sig = signature(obj)
|
|
@@ -83,7 +83,7 @@ def build_kwargs_target(
|
|
|
83
83
|
k = tag(k, pt)
|
|
84
84
|
|
|
85
85
|
if k in seen:
|
|
86
|
-
raise
|
|
86
|
+
raise DuplicateKeyError(k)
|
|
87
87
|
seen.add(k)
|
|
88
88
|
|
|
89
89
|
kws.append(Kwarg(
|
omlish/inject/impl/scopes.py
CHANGED
|
@@ -9,8 +9,8 @@ from ... import lang
|
|
|
9
9
|
from ..bindings import Binding
|
|
10
10
|
from ..elements import Elements
|
|
11
11
|
from ..elements import as_elements
|
|
12
|
-
from ..exceptions import
|
|
13
|
-
from ..exceptions import
|
|
12
|
+
from ..exceptions import ScopeAlreadyOpenError
|
|
13
|
+
from ..exceptions import ScopeNotOpenError
|
|
14
14
|
from ..injector import Injector
|
|
15
15
|
from ..keys import Key
|
|
16
16
|
from ..providers import Provider
|
|
@@ -134,7 +134,7 @@ class SeededScopeImpl(ScopeImpl):
|
|
|
134
134
|
|
|
135
135
|
def must_state(self) -> 'SeededScopeImpl.State':
|
|
136
136
|
if (st := self._st) is None:
|
|
137
|
-
raise
|
|
137
|
+
raise ScopeNotOpenError(self._ss)
|
|
138
138
|
return st
|
|
139
139
|
|
|
140
140
|
class Manager(SeededScope.Manager, lang.Final):
|
|
@@ -147,14 +147,14 @@ class SeededScopeImpl(ScopeImpl):
|
|
|
147
147
|
@contextlib.contextmanager
|
|
148
148
|
def __call__(self, seeds: ta.Mapping[Key, ta.Any]) -> ta.Generator[None, None, None]:
|
|
149
149
|
try:
|
|
150
|
-
if self._ssi._st is not None:
|
|
151
|
-
raise
|
|
152
|
-
self._ssi._st = SeededScopeImpl.State(dict(seeds))
|
|
150
|
+
if self._ssi._st is not None: # noqa
|
|
151
|
+
raise ScopeAlreadyOpenError(self._ss)
|
|
152
|
+
self._ssi._st = SeededScopeImpl.State(dict(seeds)) # noqa
|
|
153
153
|
yield
|
|
154
154
|
finally:
|
|
155
|
-
if self._ssi._st is None:
|
|
156
|
-
raise
|
|
157
|
-
self._ssi._st = None
|
|
155
|
+
if self._ssi._st is None: # noqa
|
|
156
|
+
raise ScopeNotOpenError(self._ss)
|
|
157
|
+
self._ssi._st = None # noqa
|
|
158
158
|
|
|
159
159
|
def auto_elements(self) -> Elements:
|
|
160
160
|
return as_elements(
|
omlish/inject/injector.py
CHANGED
omlish/inject/providers.py
CHANGED
|
@@ -53,7 +53,7 @@ class FnProvider(Provider):
|
|
|
53
53
|
return self.cls
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
def fn(fn: ta.Any, cls:
|
|
56
|
+
def fn(fn: ta.Any, cls: Cls | None = _Missing) -> Provider:
|
|
57
57
|
check.not_isinstance(fn, type)
|
|
58
58
|
check.callable(fn)
|
|
59
59
|
if cls is _Missing:
|
|
@@ -90,7 +90,7 @@ class ConstProvider(Provider):
|
|
|
90
90
|
return self.cls
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
def const(v: ta.Any, cls:
|
|
93
|
+
def const(v: ta.Any, cls: Cls | None = _Missing) -> Provider:
|
|
94
94
|
if cls is _Missing:
|
|
95
95
|
cls = type(v)
|
|
96
96
|
return ConstProvider(v, cls)
|
omlish/inject/proxy.py
CHANGED
|
@@ -22,7 +22,7 @@ def _cyclic_dependency_proxy() -> tuple[type, ta.Callable[[ta.Any, ta.Any], None
|
|
|
22
22
|
def __init__(self, cls):
|
|
23
23
|
super().__init__(_CyclicDependencyPlaceholder(cls))
|
|
24
24
|
if isinstance(cls, type):
|
|
25
|
-
self._self__class__ = cls
|
|
25
|
+
self._self__class__ = cls # noqa
|
|
26
26
|
|
|
27
27
|
def __repr__(self) -> str:
|
|
28
28
|
return f'_CyclicDependencyProxy({self.__wrapped__!r})'
|
|
@@ -35,14 +35,14 @@ def _cyclic_dependency_proxy() -> tuple[type, ta.Callable[[ta.Any, ta.Any], None
|
|
|
35
35
|
pass
|
|
36
36
|
return object.__getattribute__(self, att) # noqa
|
|
37
37
|
|
|
38
|
-
def
|
|
38
|
+
def set_obj(prox, obj):
|
|
39
39
|
check.state(type(prox) is _CyclicDependencyProxy)
|
|
40
40
|
check.not_isinstance(obj, _CyclicDependencyPlaceholder)
|
|
41
41
|
check.isinstance(prox.__wrapped__, _CyclicDependencyPlaceholder)
|
|
42
42
|
if hasattr(prox, '_self__class__'):
|
|
43
|
-
check.issubclass(type(obj), prox._self__class__)
|
|
43
|
+
check.issubclass(type(obj), prox._self__class__) # noqa
|
|
44
44
|
prox.__wrapped__ = obj
|
|
45
45
|
if hasattr(prox, '_self__class__'):
|
|
46
|
-
del prox._self__class__
|
|
46
|
+
del prox._self__class__ # noqa
|
|
47
47
|
|
|
48
|
-
return (_CyclicDependencyProxy,
|
|
48
|
+
return (_CyclicDependencyProxy, set_obj) # noqa
|
omlish/iterators.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import collections
|
|
2
2
|
import functools
|
|
3
|
+
import heapq
|
|
3
4
|
import itertools
|
|
4
5
|
import typing as ta
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
T = ta.TypeVar('T')
|
|
9
|
+
U = ta.TypeVar('U')
|
|
8
10
|
|
|
9
11
|
_MISSING = object()
|
|
10
12
|
|
|
@@ -20,66 +22,61 @@ class PeekIterator(ta.Iterator[T]):
|
|
|
20
22
|
|
|
21
23
|
_item: T
|
|
22
24
|
|
|
23
|
-
def __iter__(self) -> ta.
|
|
25
|
+
def __iter__(self) -> ta.Self:
|
|
24
26
|
return self
|
|
25
27
|
|
|
26
28
|
@property
|
|
27
29
|
def done(self) -> bool:
|
|
28
30
|
try:
|
|
29
31
|
self.peek()
|
|
30
|
-
return False
|
|
31
32
|
except StopIteration:
|
|
32
33
|
return True
|
|
34
|
+
else:
|
|
35
|
+
return False
|
|
33
36
|
|
|
34
37
|
def __next__(self) -> T:
|
|
35
38
|
if self._next_item is not _MISSING:
|
|
36
39
|
self._item = ta.cast(T, self._next_item)
|
|
37
40
|
self._next_item = _MISSING
|
|
38
41
|
else:
|
|
39
|
-
|
|
40
|
-
self._item = next(self._it)
|
|
41
|
-
except StopIteration:
|
|
42
|
-
raise
|
|
42
|
+
self._item = next(self._it)
|
|
43
43
|
self._pos += 1
|
|
44
44
|
return self._item
|
|
45
45
|
|
|
46
46
|
def peek(self) -> T:
|
|
47
47
|
if self._next_item is not _MISSING:
|
|
48
48
|
return ta.cast(T, self._next_item)
|
|
49
|
-
|
|
50
|
-
self._next_item = next(self._it)
|
|
51
|
-
except StopIteration:
|
|
52
|
-
raise
|
|
49
|
+
self._next_item = next(self._it)
|
|
53
50
|
return self._next_item
|
|
54
51
|
|
|
55
52
|
def next_peek(self) -> T:
|
|
56
53
|
next(self)
|
|
57
54
|
return self.peek()
|
|
58
55
|
|
|
59
|
-
def takewhile(self, fn):
|
|
56
|
+
def takewhile(self, fn: ta.Callable[[T], bool]) -> ta.Iterator[T]:
|
|
60
57
|
while fn(self.peek()):
|
|
61
58
|
yield next(self)
|
|
62
59
|
|
|
63
|
-
def skipwhile(self, fn):
|
|
60
|
+
def skipwhile(self, fn: ta.Callable[[T], bool]) -> None:
|
|
64
61
|
while fn(self.peek()):
|
|
65
62
|
next(self)
|
|
66
63
|
|
|
67
|
-
def takeuntil(self, fn):
|
|
64
|
+
def takeuntil(self, fn: ta.Callable[[T], bool]) -> ta.Iterator[T]:
|
|
68
65
|
return self.takewhile(lambda e: not fn(e))
|
|
69
66
|
|
|
70
|
-
def skipuntil(self, fn):
|
|
67
|
+
def skipuntil(self, fn: ta.Callable[[T], bool]) -> None:
|
|
71
68
|
self.skipwhile(lambda e: not fn(e))
|
|
72
69
|
|
|
73
|
-
def takethrough(self, pos):
|
|
70
|
+
def takethrough(self, pos: int) -> ta.Iterator[T]:
|
|
74
71
|
return self.takewhile(lambda _: self._pos < pos)
|
|
75
72
|
|
|
76
|
-
def skipthrough(self, pos):
|
|
73
|
+
def skipthrough(self, pos: int) -> None:
|
|
77
74
|
self.skipwhile(lambda _: self._pos < pos)
|
|
78
75
|
|
|
79
|
-
def taketo(self, pos):
|
|
76
|
+
def taketo(self, pos: int) -> ta.Iterator[T]:
|
|
80
77
|
return self.takethrough(pos - 1)
|
|
81
78
|
|
|
82
|
-
def skipto(self, pos):
|
|
79
|
+
def skipto(self, pos: int) -> None:
|
|
83
80
|
self.skipthrough(pos - 1)
|
|
84
81
|
|
|
85
82
|
|
|
@@ -88,7 +85,7 @@ class ProxyIterator(ta.Iterator[T]):
|
|
|
88
85
|
def __init__(self, fn: ta.Callable[[], T]) -> None:
|
|
89
86
|
self._fn = fn
|
|
90
87
|
|
|
91
|
-
def __iter__(self) -> ta.
|
|
88
|
+
def __iter__(self) -> ta.Self:
|
|
92
89
|
return self
|
|
93
90
|
|
|
94
91
|
def __next__(self) -> T:
|
|
@@ -97,13 +94,13 @@ class ProxyIterator(ta.Iterator[T]):
|
|
|
97
94
|
|
|
98
95
|
class PrefetchIterator(ta.Iterator[T]):
|
|
99
96
|
|
|
100
|
-
def __init__(self, fn: ta.
|
|
97
|
+
def __init__(self, fn: ta.Callable[[], T] | None = None) -> None:
|
|
101
98
|
super().__init__()
|
|
102
99
|
|
|
103
100
|
self._fn = fn
|
|
104
|
-
self._deque:
|
|
101
|
+
self._deque: collections.deque[T] = collections.deque()
|
|
105
102
|
|
|
106
|
-
def __iter__(self) -> ta.
|
|
103
|
+
def __iter__(self) -> ta.Self:
|
|
107
104
|
return self
|
|
108
105
|
|
|
109
106
|
def push(self, item) -> None:
|
|
@@ -114,7 +111,7 @@ class PrefetchIterator(ta.Iterator[T]):
|
|
|
114
111
|
return self._deque.popleft()
|
|
115
112
|
except IndexError:
|
|
116
113
|
if self._fn is None:
|
|
117
|
-
raise StopIteration
|
|
114
|
+
raise StopIteration from None
|
|
118
115
|
return self._fn()
|
|
119
116
|
|
|
120
117
|
|
|
@@ -124,9 +121,9 @@ class RetainIterator(ta.Iterator[T]):
|
|
|
124
121
|
super().__init__()
|
|
125
122
|
|
|
126
123
|
self._fn = fn
|
|
127
|
-
self._deque:
|
|
124
|
+
self._deque: collections.deque[T] = collections.deque()
|
|
128
125
|
|
|
129
|
-
def __iter__(self) -> ta.
|
|
126
|
+
def __iter__(self) -> ta.Self:
|
|
130
127
|
return self
|
|
131
128
|
|
|
132
129
|
def pop(self) -> None:
|
|
@@ -138,7 +135,7 @@ class RetainIterator(ta.Iterator[T]):
|
|
|
138
135
|
return item
|
|
139
136
|
|
|
140
137
|
|
|
141
|
-
def unzip(it: ta.Iterable[T], width:
|
|
138
|
+
def unzip(it: ta.Iterable[T], width: int | None = None) -> list:
|
|
142
139
|
if width is None:
|
|
143
140
|
if not isinstance(it, PeekIterator):
|
|
144
141
|
it = PeekIterator(iter(it))
|
|
@@ -182,3 +179,42 @@ def chunk(n: int, iterable: ta.Iterable[T], strict: bool = False) -> ta.Iterator
|
|
|
182
179
|
return iter(ret())
|
|
183
180
|
else:
|
|
184
181
|
return iterator
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def merge_on(
|
|
185
|
+
function: ta.Callable[[T], U],
|
|
186
|
+
*its: ta.Iterable[T],
|
|
187
|
+
) -> ta.Iterator[tuple[U, list[tuple[int, T]]]]:
|
|
188
|
+
indexed_its = [
|
|
189
|
+
(
|
|
190
|
+
(function(item), it_idx, item)
|
|
191
|
+
for it_idx, item in zip(itertools.repeat(it_idx), it)
|
|
192
|
+
)
|
|
193
|
+
for it_idx, it in enumerate(its)
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
grouped_indexed_its = itertools.groupby(
|
|
197
|
+
heapq.merge(*indexed_its),
|
|
198
|
+
key=lambda item_tuple: item_tuple[0],
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
(fn_item, [(it_idx, item) for _, it_idx, item in grp])
|
|
203
|
+
for fn_item, grp in grouped_indexed_its
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def expand_indexed_pairs(
|
|
208
|
+
seq: ta.Iterable[tuple[int, T]],
|
|
209
|
+
default: T,
|
|
210
|
+
*,
|
|
211
|
+
width: int | None = None,
|
|
212
|
+
) -> list[T]:
|
|
213
|
+
width_ = width
|
|
214
|
+
if width_ is None:
|
|
215
|
+
width_ = (max(idx for idx, _ in seq) + 1) if seq else 0
|
|
216
|
+
result = [default] * width_
|
|
217
|
+
for idx, value in seq:
|
|
218
|
+
if idx < width_:
|
|
219
|
+
result[idx] = value
|
|
220
|
+
return result
|
omlish/json.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import json as _json
|
|
3
|
+
import typing as ta
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
dump = _json.dump
|
|
@@ -15,25 +16,25 @@ loads = _json.loads
|
|
|
15
16
|
|
|
16
17
|
PRETTY_INDENT = 2
|
|
17
18
|
|
|
18
|
-
PRETTY_KWARGS = dict(
|
|
19
|
+
PRETTY_KWARGS: ta.Mapping[str, ta.Any] = dict(
|
|
19
20
|
indent=PRETTY_INDENT,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
|
-
dump_pretty = functools.partial(dump, **PRETTY_KWARGS)
|
|
23
|
-
dumps_pretty = functools.partial(dumps, **PRETTY_KWARGS)
|
|
23
|
+
dump_pretty: ta.Callable[..., bytes] = functools.partial(dump, **PRETTY_KWARGS) # type: ignore
|
|
24
|
+
dumps_pretty: ta.Callable[..., str] = functools.partial(dumps, **PRETTY_KWARGS)
|
|
24
25
|
|
|
25
26
|
##
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
COMPACT_SEPARATORS = (',', ':')
|
|
29
30
|
|
|
30
|
-
COMPACT_KWARGS = dict(
|
|
31
|
+
COMPACT_KWARGS: ta.Mapping[str, ta.Any] = dict(
|
|
31
32
|
indent=0,
|
|
32
33
|
separators=COMPACT_SEPARATORS,
|
|
33
34
|
)
|
|
34
35
|
|
|
35
|
-
dump_compact = functools.partial(dump, **COMPACT_KWARGS)
|
|
36
|
-
dumps_compact = functools.partial(dumps, **COMPACT_KWARGS)
|
|
36
|
+
dump_compact: ta.Callable[..., bytes] = functools.partial(dump, **COMPACT_KWARGS) # type: ignore
|
|
37
|
+
dumps_compact: ta.Callable[..., str] = functools.partial(dumps, **COMPACT_KWARGS)
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
##
|