omlish 0.0.0.dev246__py3-none-any.whl → 0.0.0.dev248__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.
- omlish/.manifests.json +2 -2
- omlish/__about__.py +2 -2
- omlish/collections/cache/descriptor.py +0 -2
- omlish/collections/identity.py +6 -0
- omlish/concurrent/executors.py +0 -1
- omlish/concurrent/futures.py +0 -1
- omlish/dataclasses/impl/descriptors.py +0 -2
- omlish/diag/replserver/server.py +0 -1
- omlish/dispatch/_dispatch2.py +7 -3
- omlish/dispatch/_dispatch3.py +7 -3
- omlish/dispatch/dispatch.py +29 -63
- omlish/dispatch/functions.py +1 -1
- omlish/dispatch/impls.py +69 -0
- omlish/dispatch/methods.py +1 -1
- omlish/dynamic.py +0 -3
- omlish/formats/json/stream/build.py +2 -0
- omlish/formats/yaml.py +0 -3
- omlish/graphs/dags.py +0 -2
- omlish/graphs/domination.py +0 -5
- omlish/graphs/dot/items.py +0 -1
- omlish/graphs/dot/rendering.py +0 -1
- omlish/graphs/trees.py +0 -1
- omlish/inject/binder.py +0 -10
- omlish/iterators/iterators.py +0 -4
- omlish/lang/__init__.py +1 -0
- omlish/lang/collections.py +36 -0
- omlish/lang/descriptors.py +0 -1
- omlish/lifecycles/base.py +0 -1
- omlish/lifecycles/contextmanagers.py +0 -1
- omlish/lifecycles/controller.py +0 -2
- omlish/lifecycles/manager.py +0 -1
- omlish/marshal/trivial/any.py +0 -1
- omlish/math/bits.py +0 -1
- omlish/math/stats.py +0 -1
- omlish/specs/jmespath/cli.py +1 -1
- omlish/sql/queries/rendering.py +108 -87
- omlish/term/codes.py +0 -1
- omlish/testing/pytest/plugins/logging.py +0 -1
- omlish/testing/pytest/plugins/pydevd.py +0 -1
- omlish/testing/pytest/plugins/repeat.py +0 -1
- omlish/testing/pytest/plugins/skips.py +0 -1
- omlish/testing/pytest/plugins/spacing.py +0 -1
- omlish/testing/pytest/plugins/switches.py +0 -1
- omlish/text/delimit.py +0 -1
- {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/RECORD +50 -50
- omlish/sql/queries/rendering2.py +0 -248
- {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/top_level.txt +0 -0
omlish/.manifests.json
CHANGED
@@ -167,7 +167,7 @@
|
|
167
167
|
"module": ".formats.yaml",
|
168
168
|
"attr": "_YAML_LAZY_CODEC",
|
169
169
|
"file": "omlish/formats/yaml.py",
|
170
|
-
"line":
|
170
|
+
"line": 255,
|
171
171
|
"value": {
|
172
172
|
"$.codecs.base.LazyLoadedCodec": {
|
173
173
|
"mod_name": "omlish.formats.yaml",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
"module": ".formats.yaml",
|
184
184
|
"attr": "_YAML_UNSAFE_LAZY_CODEC",
|
185
185
|
"file": "omlish/formats/yaml.py",
|
186
|
-
"line":
|
186
|
+
"line": 262,
|
187
187
|
"value": {
|
188
188
|
"$.codecs.base.LazyLoadedCodec": {
|
189
189
|
"mod_name": "omlish.formats.yaml",
|
omlish/__about__.py
CHANGED
@@ -63,7 +63,6 @@ def _make_key(
|
|
63
63
|
|
64
64
|
|
65
65
|
class Ignore:
|
66
|
-
|
67
66
|
def __init__(self, value: ta.Any) -> None:
|
68
67
|
super().__init__()
|
69
68
|
|
@@ -75,7 +74,6 @@ def ignore(value: ta.Any) -> ta.Any:
|
|
75
74
|
|
76
75
|
|
77
76
|
class _CacheDescriptor:
|
78
|
-
|
79
77
|
def __init__(
|
80
78
|
self,
|
81
79
|
fn: ta.Callable,
|
omlish/collections/identity.py
CHANGED
@@ -40,6 +40,9 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
|
|
40
40
|
for k, v in lang.yield_dict_init(*args, **kwargs):
|
41
41
|
self[k] = v
|
42
42
|
|
43
|
+
def __reduce__(self):
|
44
|
+
return (type(self), (list(self.items()),))
|
45
|
+
|
43
46
|
@property
|
44
47
|
def debug(self) -> ta.Sequence[tuple[K, V]]:
|
45
48
|
return list(self.items())
|
@@ -74,6 +77,9 @@ class IdentitySet(ta.MutableSet[T]):
|
|
74
77
|
for item in init:
|
75
78
|
self.add(item)
|
76
79
|
|
80
|
+
def __reduce__(self):
|
81
|
+
return (type(self), (list(self),))
|
82
|
+
|
77
83
|
@property
|
78
84
|
def debug(self) -> ta.Sequence[T]:
|
79
85
|
return list(self)
|
omlish/concurrent/executors.py
CHANGED
omlish/concurrent/futures.py
CHANGED
@@ -6,7 +6,6 @@ from ... import defs
|
|
6
6
|
|
7
7
|
|
8
8
|
class AbstractFieldDescriptor(abc.ABC):
|
9
|
-
|
10
9
|
def __init__(
|
11
10
|
self,
|
12
11
|
*,
|
@@ -69,7 +68,6 @@ class AbstractFieldDescriptor(abc.ABC):
|
|
69
68
|
|
70
69
|
|
71
70
|
class PyFieldDescriptor(AbstractFieldDescriptor):
|
72
|
-
|
73
71
|
def __init__(
|
74
72
|
self,
|
75
73
|
attr: str,
|
omlish/diag/replserver/server.py
CHANGED
omlish/dispatch/_dispatch2.py
CHANGED
@@ -2,7 +2,7 @@ import abc
|
|
2
2
|
import typing as ta
|
3
3
|
import weakref
|
4
4
|
|
5
|
-
from .
|
5
|
+
from .impls import find_impl as default_find_impl
|
6
6
|
|
7
7
|
|
8
8
|
T = ta.TypeVar('T')
|
@@ -12,9 +12,13 @@ T = ta.TypeVar('T')
|
|
12
12
|
|
13
13
|
|
14
14
|
class Dispatcher(ta.Generic[T]):
|
15
|
-
def __init__(self) -> None:
|
15
|
+
def __init__(self, find_impl: ta.Callable[[type, ta.Mapping[type, T]], T | None] | None = None) -> None:
|
16
16
|
super().__init__()
|
17
17
|
|
18
|
+
if find_impl is None:
|
19
|
+
find_impl = default_find_impl
|
20
|
+
self._find_impl = find_impl
|
21
|
+
|
18
22
|
self._impls_by_arg_cls: dict[type, T] = {}
|
19
23
|
self._dispatch_cache: dict[ta.Any, T | None] = {}
|
20
24
|
|
@@ -59,7 +63,7 @@ class Dispatcher(ta.Generic[T]):
|
|
59
63
|
try:
|
60
64
|
impl = self._impls_by_arg_cls[cls]
|
61
65
|
except KeyError:
|
62
|
-
impl =
|
66
|
+
impl = self._find_impl(cls, self._impls_by_arg_cls)
|
63
67
|
|
64
68
|
self._dispatch_cache[weakref.ref(cls, self._cache_remove)] = impl
|
65
69
|
return impl
|
omlish/dispatch/_dispatch3.py
CHANGED
@@ -2,7 +2,7 @@ import abc
|
|
2
2
|
import typing as ta
|
3
3
|
import weakref
|
4
4
|
|
5
|
-
from .
|
5
|
+
from .impls import find_impl as default_find_impl
|
6
6
|
|
7
7
|
|
8
8
|
T = ta.TypeVar('T')
|
@@ -72,9 +72,13 @@ class DispatchCache(DispatchCacheProtocol[T]):
|
|
72
72
|
|
73
73
|
|
74
74
|
class Dispatcher(DispatcherProtocol[T]):
|
75
|
-
def __init__(self) -> None:
|
75
|
+
def __init__(self, find_impl: ta.Callable[[type, ta.Mapping[type, T]], T | None] | None = None) -> None:
|
76
76
|
super().__init__()
|
77
77
|
|
78
|
+
if find_impl is None:
|
79
|
+
find_impl = default_find_impl
|
80
|
+
self._find_impl = find_impl
|
81
|
+
|
78
82
|
self._impls_by_arg_cls: dict[type, T] = {}
|
79
83
|
self._cache: DispatchCache[T | None] = DispatchCache()
|
80
84
|
|
@@ -98,7 +102,7 @@ class Dispatcher(DispatcherProtocol[T]):
|
|
98
102
|
try:
|
99
103
|
impl = self._impls_by_arg_cls[cls]
|
100
104
|
except KeyError:
|
101
|
-
impl =
|
105
|
+
impl = self._find_impl(cls, self._impls_by_arg_cls)
|
102
106
|
|
103
107
|
self._cache.put(cls, impl)
|
104
108
|
return impl
|
omlish/dispatch/dispatch.py
CHANGED
@@ -3,9 +3,7 @@ import contextlib
|
|
3
3
|
import typing as ta
|
4
4
|
import weakref
|
5
5
|
|
6
|
-
from
|
7
|
-
from .. import check
|
8
|
-
from .. import reflect as rfl
|
6
|
+
from .impls import find_impl as default_find_impl
|
9
7
|
|
10
8
|
|
11
9
|
T = ta.TypeVar('T')
|
@@ -14,69 +12,13 @@ T = ta.TypeVar('T')
|
|
14
12
|
##
|
15
13
|
|
16
14
|
|
17
|
-
_IMPL_FUNC_CLS_SET_CACHE: ta.MutableMapping[ta.Callable, frozenset[type]] = weakref.WeakKeyDictionary()
|
18
|
-
|
19
|
-
|
20
|
-
def get_impl_func_cls_set(func: ta.Callable) -> frozenset[type]:
|
21
|
-
with contextlib.suppress(KeyError):
|
22
|
-
return _IMPL_FUNC_CLS_SET_CACHE[func]
|
23
|
-
|
24
|
-
ann = getattr(func, '__annotations__', {})
|
25
|
-
if not ann:
|
26
|
-
raise TypeError(f'Invalid impl func: {func!r}')
|
27
|
-
|
28
|
-
def erase(a):
|
29
|
-
if isinstance(a, rfl.Generic):
|
30
|
-
return a.cls
|
31
|
-
else:
|
32
|
-
return check.isinstance(a, type)
|
33
|
-
|
34
|
-
# Exclude 'return' to support difficult to handle return types - they are unimportant.
|
35
|
-
# TODO: only get hints for first arg - requires inspection, which requires chopping off `self`, which can be tricky.
|
36
|
-
_, cls = next(iter(rfl.get_filtered_type_hints(func, exclude=['return']).items()))
|
37
|
-
|
38
|
-
rty = rfl.type_(cls)
|
39
|
-
if isinstance(rty, rfl.Union):
|
40
|
-
ret = frozenset(erase(arg) for arg in rty.args)
|
41
|
-
else:
|
42
|
-
ret = frozenset([erase(rty)])
|
43
|
-
|
44
|
-
_IMPL_FUNC_CLS_SET_CACHE[func] = ret
|
45
|
-
return ret
|
46
|
-
|
47
|
-
|
48
|
-
def find_impl(cls: type, registry: ta.Mapping[type, T]) -> T | None:
|
49
|
-
mro = c3.compose_mro(cls, registry.keys())
|
50
|
-
|
51
|
-
match: type | None = None
|
52
|
-
for t in mro:
|
53
|
-
if match is not None:
|
54
|
-
# If *match* is an implicit ABC but there is another unrelated, equally matching implicit ABC, refuse the
|
55
|
-
# temptation to guess.
|
56
|
-
if (
|
57
|
-
t in registry
|
58
|
-
and t not in cls.__mro__
|
59
|
-
and match not in cls.__mro__
|
60
|
-
and not issubclass(match, t)
|
61
|
-
):
|
62
|
-
raise RuntimeError(f'Ambiguous dispatch: {match} or {t}')
|
63
|
-
break
|
64
|
-
|
65
|
-
if t in registry:
|
66
|
-
match = t
|
67
|
-
|
68
|
-
if match is None:
|
69
|
-
return None
|
70
|
-
return registry.get(match)
|
71
|
-
|
72
|
-
|
73
|
-
##
|
74
|
-
|
75
|
-
|
76
15
|
class Dispatcher(ta.Generic[T]):
|
77
|
-
def __init__(self) -> None:
|
16
|
+
def __init__(self, find_impl: ta.Callable[[type, ta.Mapping[type, T]], T | None] | None = None) -> None:
|
78
17
|
super().__init__()
|
79
18
|
|
19
|
+
if find_impl is None:
|
20
|
+
find_impl = default_find_impl
|
21
|
+
|
80
22
|
impls_by_arg_cls: dict[type, T] = {}
|
81
23
|
self._impls_by_arg_cls = impls_by_arg_cls
|
82
24
|
|
@@ -142,3 +84,27 @@ class Dispatcher(ta.Generic[T]):
|
|
142
84
|
dispatch: ta.Callable[[type], T | None]
|
143
85
|
|
144
86
|
register: ta.Callable[[T, ta.Iterable[type]], T]
|
87
|
+
|
88
|
+
|
89
|
+
##
|
90
|
+
|
91
|
+
|
92
|
+
# from x.dispatch import _gpto1_2 as _dispatch # noqa
|
93
|
+
#
|
94
|
+
#
|
95
|
+
# class Dispatcher(ta.Generic[T]): # noqa
|
96
|
+
# def __init__(self, find_impl: ta.Callable[[type, ta.Mapping[type, T]], T | None] | None = None) -> None:
|
97
|
+
# super().__init__()
|
98
|
+
#
|
99
|
+
# if find_impl is None:
|
100
|
+
# find_impl = default_find_impl
|
101
|
+
# self._x = _dispatch.Dispatcher(find_impl)
|
102
|
+
#
|
103
|
+
# def cache_size(self) -> int:
|
104
|
+
# return self._x.cache_size()
|
105
|
+
#
|
106
|
+
# def dispatch(self, cls: type) -> T | None:
|
107
|
+
# return self._x.dispatch(cls)
|
108
|
+
#
|
109
|
+
# def register(self, impl: T, cls_col: ta.Iterable[type]) -> T:
|
110
|
+
# return self._x.register(impl, cls_col)
|
omlish/dispatch/functions.py
CHANGED
omlish/dispatch/impls.py
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
import contextlib
|
2
|
+
import typing as ta
|
3
|
+
import weakref
|
4
|
+
|
5
|
+
from .. import c3
|
6
|
+
from .. import check
|
7
|
+
from .. import reflect as rfl
|
8
|
+
|
9
|
+
|
10
|
+
T = ta.TypeVar('T')
|
11
|
+
|
12
|
+
|
13
|
+
##
|
14
|
+
|
15
|
+
|
16
|
+
_IMPL_FUNC_CLS_SET_CACHE: ta.MutableMapping[ta.Callable, frozenset[type]] = weakref.WeakKeyDictionary()
|
17
|
+
|
18
|
+
|
19
|
+
def get_impl_func_cls_set(func: ta.Callable) -> frozenset[type]:
|
20
|
+
with contextlib.suppress(KeyError):
|
21
|
+
return _IMPL_FUNC_CLS_SET_CACHE[func]
|
22
|
+
|
23
|
+
ann = getattr(func, '__annotations__', {})
|
24
|
+
if not ann:
|
25
|
+
raise TypeError(f'Invalid impl func: {func!r}')
|
26
|
+
|
27
|
+
def erase(a):
|
28
|
+
if isinstance(a, rfl.Generic):
|
29
|
+
return a.cls
|
30
|
+
else:
|
31
|
+
return check.isinstance(a, type)
|
32
|
+
|
33
|
+
# Exclude 'return' to support difficult to handle return types - they are unimportant.
|
34
|
+
# TODO: only get hints for first arg - requires inspection, which requires chopping off `self`, which can be tricky.
|
35
|
+
_, cls = next(iter(rfl.get_filtered_type_hints(func, exclude=['return']).items()))
|
36
|
+
|
37
|
+
rty = rfl.type_(cls)
|
38
|
+
if isinstance(rty, rfl.Union):
|
39
|
+
ret = frozenset(erase(arg) for arg in rty.args)
|
40
|
+
else:
|
41
|
+
ret = frozenset([erase(rty)])
|
42
|
+
|
43
|
+
_IMPL_FUNC_CLS_SET_CACHE[func] = ret
|
44
|
+
return ret
|
45
|
+
|
46
|
+
|
47
|
+
def find_impl(cls: type, registry: ta.Mapping[type, T]) -> T | None:
|
48
|
+
mro = c3.compose_mro(cls, registry.keys())
|
49
|
+
|
50
|
+
match: type | None = None
|
51
|
+
for t in mro:
|
52
|
+
if match is not None:
|
53
|
+
# If *match* is an implicit ABC but there is another unrelated, equally matching implicit ABC, refuse the
|
54
|
+
# temptation to guess.
|
55
|
+
if (
|
56
|
+
t in registry
|
57
|
+
and t not in cls.__mro__
|
58
|
+
and match not in cls.__mro__
|
59
|
+
and not issubclass(match, t)
|
60
|
+
):
|
61
|
+
raise RuntimeError(f'Ambiguous dispatch: {match} or {t}')
|
62
|
+
break
|
63
|
+
|
64
|
+
if t in registry:
|
65
|
+
match = t
|
66
|
+
|
67
|
+
if match is None:
|
68
|
+
return None
|
69
|
+
return registry.get(match)
|
omlish/dispatch/methods.py
CHANGED
omlish/dynamic.py
CHANGED
@@ -46,7 +46,6 @@ class UnboundVarError(ValueError):
|
|
46
46
|
|
47
47
|
|
48
48
|
class Var(ta.Generic[T]):
|
49
|
-
|
50
49
|
def __init__(
|
51
50
|
self,
|
52
51
|
default: type[MISSING] | T = MISSING,
|
@@ -152,7 +151,6 @@ class Var(ta.Generic[T]):
|
|
152
151
|
|
153
152
|
|
154
153
|
class Binding(ta.Generic[T]):
|
155
|
-
|
156
154
|
_frame: types.FrameType
|
157
155
|
_frame_bindings: ta.MutableMapping[int, 'Binding']
|
158
156
|
_level: int
|
@@ -207,7 +205,6 @@ class Binding(ta.Generic[T]):
|
|
207
205
|
|
208
206
|
|
209
207
|
class _GeneratorContextManager(contextlib._GeneratorContextManager): # noqa
|
210
|
-
|
211
208
|
@hoist(2)
|
212
209
|
def __enter__(self):
|
213
210
|
return super().__enter__()
|
omlish/formats/yaml.py
CHANGED
@@ -45,7 +45,6 @@ class NodeWrapped(lang.Final, ta.Generic[T]):
|
|
45
45
|
|
46
46
|
|
47
47
|
class NodeUnwrapper:
|
48
|
-
|
49
48
|
seq_types: tuple[type, ...] = (
|
50
49
|
list,
|
51
50
|
set,
|
@@ -95,7 +94,6 @@ def unwrap(nw: NodeWrapped[T]) -> T:
|
|
95
94
|
|
96
95
|
|
97
96
|
class NodeWrappingConstructorMixin:
|
98
|
-
|
99
97
|
def __init__(self, *args, **kwargs):
|
100
98
|
super().__init__(*args, **kwargs)
|
101
99
|
|
@@ -159,7 +157,6 @@ class _cached_class_property: # noqa
|
|
159
157
|
|
160
158
|
|
161
159
|
class WrappedLoaders(lang.Namespace):
|
162
|
-
|
163
160
|
@staticmethod
|
164
161
|
def _wrap(cls): # noqa
|
165
162
|
return type('NodeWrapping$' + cls.__name__, (NodeWrappingConstructorMixin, cls), {})
|
omlish/graphs/dags.py
CHANGED
@@ -51,7 +51,6 @@ def invert_symmetric_set_map(src: ta.Mapping[T, ta.Iterable[T]]) -> dict[T, set[
|
|
51
51
|
|
52
52
|
|
53
53
|
class Dag(ta.Generic[T]):
|
54
|
-
|
55
54
|
def __init__(self, input_its_by_outputs: ta.Mapping[T, ta.Iterable[T]]) -> None:
|
56
55
|
super().__init__()
|
57
56
|
|
@@ -70,7 +69,6 @@ class Dag(ta.Generic[T]):
|
|
70
69
|
|
71
70
|
|
72
71
|
class Subdag(ta.Generic[U]):
|
73
|
-
|
74
72
|
def __init__(
|
75
73
|
self,
|
76
74
|
dag: 'Dag[U]',
|
omlish/graphs/domination.py
CHANGED
@@ -13,7 +13,6 @@ SetMap = ta.Mapping[MK, ta.AbstractSet[MV]]
|
|
13
13
|
|
14
14
|
|
15
15
|
class DirectedGraph(ta.Generic[V], lang.Abstract):
|
16
|
-
|
17
16
|
@abc.abstractmethod
|
18
17
|
def get_successors(self, vertex: V) -> ta.Collection[V]:
|
19
18
|
raise NotImplementedError
|
@@ -24,7 +23,6 @@ class DirectedGraph(ta.Generic[V], lang.Abstract):
|
|
24
23
|
|
25
24
|
|
26
25
|
class ListDictDirectedGraph(DirectedGraph[V]):
|
27
|
-
|
28
26
|
def __init__(self, items: ta.Iterable[tuple[V, ta.Iterable[V]]]) -> None:
|
29
27
|
super().__init__()
|
30
28
|
|
@@ -59,7 +57,6 @@ class ListDictDirectedGraph(DirectedGraph[V]):
|
|
59
57
|
|
60
58
|
|
61
59
|
class DominatorTree(ta.Generic[V]):
|
62
|
-
|
63
60
|
def __init__(self, graph: DirectedGraph[V], root: V) -> None:
|
64
61
|
super().__init__()
|
65
62
|
|
@@ -138,7 +135,6 @@ class DominatorTree(ta.Generic[V]):
|
|
138
135
|
|
139
136
|
|
140
137
|
class _Dfs(ta.Generic[V]):
|
141
|
-
|
142
138
|
def __init__(self, graph: DirectedGraph[V], root: V) -> None:
|
143
139
|
super().__init__()
|
144
140
|
|
@@ -191,7 +187,6 @@ class _Dfs(ta.Generic[V]):
|
|
191
187
|
|
192
188
|
|
193
189
|
class _ImmediateDominanceComputer(ta.Generic[V]):
|
194
|
-
|
195
190
|
def __init__(self, dfs: _Dfs[V]) -> None:
|
196
191
|
super().__init__()
|
197
192
|
|
omlish/graphs/dot/items.py
CHANGED
omlish/graphs/dot/rendering.py
CHANGED
omlish/graphs/trees.py
CHANGED
omlish/inject/binder.py
CHANGED
omlish/iterators/iterators.py
CHANGED
@@ -9,7 +9,6 @@ _MISSING = object()
|
|
9
9
|
|
10
10
|
|
11
11
|
class PeekIterator(ta.Iterator[T]):
|
12
|
-
|
13
12
|
def __init__(self, it: ta.Iterable[T]) -> None:
|
14
13
|
super().__init__()
|
15
14
|
|
@@ -78,7 +77,6 @@ class PeekIterator(ta.Iterator[T]):
|
|
78
77
|
|
79
78
|
|
80
79
|
class ProxyIterator(ta.Iterator[T]):
|
81
|
-
|
82
80
|
def __init__(self, fn: ta.Callable[[], T]) -> None:
|
83
81
|
self._fn = fn
|
84
82
|
|
@@ -90,7 +88,6 @@ class ProxyIterator(ta.Iterator[T]):
|
|
90
88
|
|
91
89
|
|
92
90
|
class PrefetchIterator(ta.Iterator[T]):
|
93
|
-
|
94
91
|
def __init__(self, fn: ta.Callable[[], T] | None = None) -> None:
|
95
92
|
super().__init__()
|
96
93
|
|
@@ -113,7 +110,6 @@ class PrefetchIterator(ta.Iterator[T]):
|
|
113
110
|
|
114
111
|
|
115
112
|
class RetainIterator(ta.Iterator[T]):
|
116
|
-
|
117
113
|
def __init__(self, fn: ta.Callable[[], T]) -> None:
|
118
114
|
super().__init__()
|
119
115
|
|
omlish/lang/__init__.py
CHANGED
omlish/lang/collections.py
CHANGED
@@ -48,3 +48,39 @@ def merge_dicts(
|
|
48
48
|
out[k] = v
|
49
49
|
|
50
50
|
return out
|
51
|
+
|
52
|
+
|
53
|
+
##
|
54
|
+
|
55
|
+
|
56
|
+
class _EmptyMap(ta.Mapping[K, V]):
|
57
|
+
def __init_subclass__(cls, **kwargs):
|
58
|
+
raise TypeError
|
59
|
+
|
60
|
+
def __new__(cls, *args, **kwargs):
|
61
|
+
if args or kwargs:
|
62
|
+
raise TypeError
|
63
|
+
return _EMPTY_MAP
|
64
|
+
|
65
|
+
def __repr__(self) -> str:
|
66
|
+
return f'{self.__class__.__name__}()'
|
67
|
+
|
68
|
+
def __init__(self) -> None:
|
69
|
+
super().__init__()
|
70
|
+
|
71
|
+
def __getitem__(self, k: K) -> V:
|
72
|
+
raise KeyError
|
73
|
+
|
74
|
+
def __len__(self) -> int:
|
75
|
+
return 0
|
76
|
+
|
77
|
+
def __iter__(self) -> ta.Iterator[K]:
|
78
|
+
return
|
79
|
+
yield # noqa
|
80
|
+
|
81
|
+
|
82
|
+
_EMPTY_MAP = object.__new__(_EmptyMap)
|
83
|
+
|
84
|
+
|
85
|
+
def empty_map() -> ta.Mapping[K, V]:
|
86
|
+
return _EMPTY_MAP
|
omlish/lang/descriptors.py
CHANGED
omlish/lifecycles/base.py
CHANGED
omlish/lifecycles/controller.py
CHANGED
@@ -14,7 +14,6 @@ LifecycleT = ta.TypeVar('LifecycleT', bound='Lifecycle')
|
|
14
14
|
|
15
15
|
|
16
16
|
class LifecycleListener(ta.Generic[LifecycleT]):
|
17
|
-
|
18
17
|
def on_starting(self, obj: LifecycleT) -> None:
|
19
18
|
pass
|
20
19
|
|
@@ -29,7 +28,6 @@ class LifecycleListener(ta.Generic[LifecycleT]):
|
|
29
28
|
|
30
29
|
|
31
30
|
class LifecycleController(Lifecycle, ta.Generic[LifecycleT]):
|
32
|
-
|
33
31
|
def __init__(
|
34
32
|
self,
|
35
33
|
lifecycle: LifecycleT,
|
omlish/lifecycles/manager.py
CHANGED
omlish/marshal/trivial/any.py
CHANGED