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.
Files changed (51) hide show
  1. omlish/.manifests.json +2 -2
  2. omlish/__about__.py +2 -2
  3. omlish/collections/cache/descriptor.py +0 -2
  4. omlish/collections/identity.py +6 -0
  5. omlish/concurrent/executors.py +0 -1
  6. omlish/concurrent/futures.py +0 -1
  7. omlish/dataclasses/impl/descriptors.py +0 -2
  8. omlish/diag/replserver/server.py +0 -1
  9. omlish/dispatch/_dispatch2.py +7 -3
  10. omlish/dispatch/_dispatch3.py +7 -3
  11. omlish/dispatch/dispatch.py +29 -63
  12. omlish/dispatch/functions.py +1 -1
  13. omlish/dispatch/impls.py +69 -0
  14. omlish/dispatch/methods.py +1 -1
  15. omlish/dynamic.py +0 -3
  16. omlish/formats/json/stream/build.py +2 -0
  17. omlish/formats/yaml.py +0 -3
  18. omlish/graphs/dags.py +0 -2
  19. omlish/graphs/domination.py +0 -5
  20. omlish/graphs/dot/items.py +0 -1
  21. omlish/graphs/dot/rendering.py +0 -1
  22. omlish/graphs/trees.py +0 -1
  23. omlish/inject/binder.py +0 -10
  24. omlish/iterators/iterators.py +0 -4
  25. omlish/lang/__init__.py +1 -0
  26. omlish/lang/collections.py +36 -0
  27. omlish/lang/descriptors.py +0 -1
  28. omlish/lifecycles/base.py +0 -1
  29. omlish/lifecycles/contextmanagers.py +0 -1
  30. omlish/lifecycles/controller.py +0 -2
  31. omlish/lifecycles/manager.py +0 -1
  32. omlish/marshal/trivial/any.py +0 -1
  33. omlish/math/bits.py +0 -1
  34. omlish/math/stats.py +0 -1
  35. omlish/specs/jmespath/cli.py +1 -1
  36. omlish/sql/queries/rendering.py +108 -87
  37. omlish/term/codes.py +0 -1
  38. omlish/testing/pytest/plugins/logging.py +0 -1
  39. omlish/testing/pytest/plugins/pydevd.py +0 -1
  40. omlish/testing/pytest/plugins/repeat.py +0 -1
  41. omlish/testing/pytest/plugins/skips.py +0 -1
  42. omlish/testing/pytest/plugins/spacing.py +0 -1
  43. omlish/testing/pytest/plugins/switches.py +0 -1
  44. omlish/text/delimit.py +0 -1
  45. {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/METADATA +1 -1
  46. {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/RECORD +50 -50
  47. omlish/sql/queries/rendering2.py +0 -248
  48. {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/LICENSE +0 -0
  49. {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/WHEEL +0 -0
  50. {omlish-0.0.0.dev246.dist-info → omlish-0.0.0.dev248.dist-info}/entry_points.txt +0 -0
  51. {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": 258,
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": 265,
186
+ "line": 262,
187
187
  "value": {
188
188
  "$.codecs.base.LazyLoadedCodec": {
189
189
  "mod_name": "omlish.formats.yaml",
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev246'
2
- __revision__ = '796628c78050f0ca988bfa17c2f5a5cad5ee9056'
1
+ __version__ = '0.0.0.dev248'
2
+ __revision__ = 'c1cc77db1e3c02c65fabdb24e9696526d61559e3'
3
3
 
4
4
 
5
5
  #
@@ -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,
@@ -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)
@@ -8,7 +8,6 @@ P = ta.ParamSpec('P')
8
8
 
9
9
 
10
10
  class ImmediateExecutor(cf.Executor):
11
-
12
11
  def __init__(self, *, immediate_exceptions: bool = False) -> None:
13
12
  super().__init__()
14
13
  self._immediate_exceptions = immediate_exceptions
@@ -10,7 +10,6 @@ T = ta.TypeVar('T')
10
10
 
11
11
 
12
12
  class FutureError(Exception, ta.Generic[T]):
13
-
14
13
  def __init__(self, future: cf.Future, target: T | None = None) -> None:
15
14
  super().__init__()
16
15
 
@@ -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,
@@ -38,7 +38,6 @@ log = logging.getLogger(__name__)
38
38
 
39
39
 
40
40
  class ReplServer:
41
-
42
41
  CONNECTION_THREAD_NAME = 'ReplServerConnection'
43
42
 
44
43
  @dc.dataclass(frozen=True)
@@ -2,7 +2,7 @@ import abc
2
2
  import typing as ta
3
3
  import weakref
4
4
 
5
- from .dispatch import find_impl
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 = find_impl(cls, self._impls_by_arg_cls)
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
@@ -2,7 +2,7 @@ import abc
2
2
  import typing as ta
3
3
  import weakref
4
4
 
5
- from .dispatch import find_impl
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 = find_impl(cls, self._impls_by_arg_cls)
105
+ impl = self._find_impl(cls, self._impls_by_arg_cls)
102
106
 
103
107
  self._cache.put(cls, impl)
104
108
  return impl
@@ -3,9 +3,7 @@ import contextlib
3
3
  import typing as ta
4
4
  import weakref
5
5
 
6
- from .. import c3
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)
@@ -3,7 +3,7 @@ import typing as ta
3
3
 
4
4
  from .. import check
5
5
  from .dispatch import Dispatcher
6
- from .dispatch import get_impl_func_cls_set
6
+ from .impls import get_impl_func_cls_set
7
7
 
8
8
 
9
9
  # USE_EXTENSION = True
@@ -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)
@@ -12,7 +12,7 @@ import weakref
12
12
  from .. import check
13
13
  from .. import lang
14
14
  from .dispatch import Dispatcher
15
- from .dispatch import get_impl_func_cls_set
15
+ from .impls import get_impl_func_cls_set
16
16
 
17
17
 
18
18
  T = ta.TypeVar('T')
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__()
@@ -19,6 +19,8 @@ class JsonObjectBuilder:
19
19
  *,
20
20
  yield_object_lists: bool = False,
21
21
  ) -> None:
22
+ super().__init__()
23
+
22
24
  self._stack: list[JsonStreamObject | list | Key] = []
23
25
  self._yield_object_lists = yield_object_lists
24
26
 
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]',
@@ -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
 
@@ -17,7 +17,6 @@ class Item(dc.Frozen, lang.Abstract, lang.Sealed):
17
17
 
18
18
 
19
19
  class Value(Item, lang.Abstract):
20
-
21
20
  @classmethod
22
21
  def of(cls, obj: ta.Union['Value', str, ta.Sequence]) -> 'Value':
23
22
  if isinstance(obj, Value):
@@ -21,7 +21,6 @@ from .items import Text
21
21
 
22
22
 
23
23
  class Renderer:
24
-
25
24
  def __init__(self, out: ta.TextIO) -> None:
26
25
  super().__init__()
27
26
 
omlish/graphs/trees.py CHANGED
@@ -40,7 +40,6 @@ class UnknownNodeError(NodeError[NodeT]):
40
40
 
41
41
 
42
42
  class BasicTreeAnalysis(ta.Generic[NodeT]):
43
-
44
43
  def __init__(
45
44
  self,
46
45
  root: NodeT,
omlish/inject/binder.py CHANGED
@@ -1,13 +1,3 @@
1
- """
2
- TODO:
3
- - multis?
4
-
5
- class SetBinding(Element, lang.Final):
6
- class SetProvider(Provider):
7
-
8
- class MapBinding(Element, lang.Final):
9
- class MapProvider(Provider):
10
- """
11
1
  import functools
12
2
  import inspect
13
3
  import types
@@ -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
@@ -78,6 +78,7 @@ from .cmp import ( # noqa
78
78
  )
79
79
 
80
80
  from .collections import ( # noqa
81
+ empty_map,
81
82
  merge_dicts,
82
83
  yield_dict_init,
83
84
  )
@@ -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
@@ -204,7 +204,6 @@ class AccessForbiddenError(Exception):
204
204
 
205
205
 
206
206
  class AccessForbiddenDescriptor:
207
-
208
207
  def __init__(self, name: str | None = None) -> None:
209
208
  super().__init__()
210
209
 
omlish/lifecycles/base.py CHANGED
@@ -9,7 +9,6 @@ LifecycleCallback: ta.TypeAlias = ta.Callable[[LifecycleT], None]
9
9
 
10
10
 
11
11
  class Lifecycle:
12
-
13
12
  def lifecycle_construct(self) -> None:
14
13
  pass
15
14
 
@@ -28,7 +28,6 @@ class ContextManagerLifecycle(Lifecycle, lang.Final, ta.Generic[ContextManagerT]
28
28
 
29
29
 
30
30
  class LifecycleContextManager(ta.Generic[LifecycleT]):
31
-
32
31
  def __init__(self, lifecycle: LifecycleT) -> None:
33
32
  super().__init__()
34
33
  self._lifecycle = lifecycle
@@ -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,
@@ -13,7 +13,6 @@ from .states import LifecycleStates
13
13
 
14
14
 
15
15
  class LifecycleManager(AbstractLifecycle):
16
-
17
16
  @dc.dataclass(frozen=True)
18
17
  class Entry(lang.Final):
19
18
  controller: LifecycleController
@@ -11,7 +11,6 @@ from ..values import Value
11
11
 
12
12
 
13
13
  class AnyMarshalerUnmarshaler(Marshaler, Unmarshaler):
14
-
15
14
  def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
16
15
  return ctx.make(type(o)).marshal(ctx, o)
17
16
 
omlish/math/bits.py CHANGED
@@ -44,7 +44,6 @@ def _gen_tuple_proxy_method(name):
44
44
 
45
45
 
46
46
  class FixedWidthInt(int):
47
-
48
47
  BITS: ta.ClassVar[int]
49
48
  SIGNED: ta.ClassVar[bool]
50
49