omlish 0.0.0.dev247__py3-none-any.whl → 0.0.0.dev249__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/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 +14 -0
- omlish/lang/cached/function.py +83 -41
- omlish/lang/collections.py +36 -0
- omlish/lang/descriptors.py +0 -1
- omlish/lang/params.py +261 -0
- 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/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.dev247.dist-info → omlish-0.0.0.dev249.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev247.dist-info → omlish-0.0.0.dev249.dist-info}/RECORD +49 -47
- {omlish-0.0.0.dev247.dist-info → omlish-0.0.0.dev249.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev247.dist-info → omlish-0.0.0.dev249.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev247.dist-info → omlish-0.0.0.dev249.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev247.dist-info → omlish-0.0.0.dev249.dist-info}/top_level.txt +0 -0
omlish/lang/cached/function.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
TODO:
|
3
|
+
- !! reconcile A().f() with A.f(A())
|
4
|
+
- unbound descriptor *should* still hit instance cache
|
3
5
|
- integrate / expose with collections.cache
|
4
6
|
- weakrefs (selectable by arg)
|
5
7
|
- more rigorous descriptor pickling
|
@@ -18,11 +20,18 @@ from ..contextmanagers import DefaultLockable
|
|
18
20
|
from ..contextmanagers import default_lock
|
19
21
|
from ..descriptors import unwrap_func
|
20
22
|
from ..descriptors import unwrap_func_with_partials
|
23
|
+
from ..params import KwargsParam
|
24
|
+
from ..params import Param
|
25
|
+
from ..params import ParamSeparator
|
26
|
+
from ..params import ParamSpec
|
27
|
+
from ..params import ValueParam
|
28
|
+
from ..params import param_render
|
21
29
|
|
22
30
|
|
23
31
|
P = ta.ParamSpec('P')
|
24
32
|
T = ta.TypeVar('T')
|
25
33
|
CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
|
34
|
+
CacheKeyMaker: ta.TypeAlias = ta.Callable[..., tuple]
|
26
35
|
|
27
36
|
|
28
37
|
##
|
@@ -32,66 +41,100 @@ def _nullary_cache_key_maker():
|
|
32
41
|
return ()
|
33
42
|
|
34
43
|
|
35
|
-
def
|
36
|
-
return (
|
44
|
+
def _self_cache_key_maker(self):
|
45
|
+
return (self,)
|
37
46
|
|
38
47
|
|
39
|
-
|
40
|
-
|
41
|
-
|
48
|
+
_PRE_MADE_CACHE_KEY_MAKERS = [
|
49
|
+
_nullary_cache_key_maker,
|
50
|
+
_self_cache_key_maker,
|
51
|
+
]
|
52
|
+
|
53
|
+
|
54
|
+
_PRE_MADE_CACHE_KEY_MAKERS_BY_PARAM_SPEC: ta.Mapping[ParamSpec, CacheKeyMaker] = {
|
55
|
+
ParamSpec.of_signature(inspect.signature(fn)): fn # type: ignore
|
56
|
+
for fn in _PRE_MADE_CACHE_KEY_MAKERS
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
##
|
42
61
|
|
43
|
-
fn, partials = unwrap_func_with_partials(fn)
|
44
62
|
|
63
|
+
def _make_unwrapped_cache_key_maker(
|
64
|
+
fn: ta.Callable,
|
65
|
+
*,
|
66
|
+
bound: bool = False,
|
67
|
+
) -> CacheKeyMaker:
|
45
68
|
if inspect.isgeneratorfunction(fn) or inspect.iscoroutinefunction(fn):
|
46
69
|
raise TypeError(fn)
|
47
70
|
|
48
|
-
|
49
|
-
|
50
|
-
|
71
|
+
ps = ParamSpec.of_signature(
|
72
|
+
inspect.signature(fn),
|
73
|
+
offset=1 if bound else 0,
|
74
|
+
strip_annotations=True,
|
75
|
+
)
|
76
|
+
|
77
|
+
if not len(ps):
|
51
78
|
return _nullary_cache_key_maker
|
52
79
|
|
53
|
-
|
80
|
+
if not ps.has_defaults:
|
81
|
+
try:
|
82
|
+
return _PRE_MADE_CACHE_KEY_MAKERS_BY_PARAM_SPEC[ps]
|
83
|
+
except KeyError:
|
84
|
+
pass
|
85
|
+
|
86
|
+
builtin_pfx = '__cache_key_maker__'
|
87
|
+
ns = {
|
88
|
+
(builtin_tuple := builtin_pfx + 'tuple'): tuple,
|
89
|
+
(builtin_sorted := builtin_pfx + 'sorted'): sorted,
|
90
|
+
}
|
91
|
+
|
54
92
|
src_params = []
|
55
93
|
src_vals = []
|
56
94
|
kwargs_name = None
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
95
|
+
for p in ps:
|
96
|
+
if isinstance(p, ParamSeparator):
|
97
|
+
src_params.append(p.value)
|
98
|
+
continue
|
99
|
+
|
100
|
+
if not isinstance(p, Param):
|
101
|
+
raise TypeError(p)
|
102
|
+
|
103
|
+
if isinstance(p, ValueParam) and p.default.present:
|
62
104
|
ns[p.name] = p.default
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
if
|
70
|
-
render_pos_only_separator = True
|
71
|
-
elif render_pos_only_separator:
|
72
|
-
src_params.append('/')
|
73
|
-
render_pos_only_separator = False
|
74
|
-
if kind == inspect.Parameter.VAR_POSITIONAL:
|
75
|
-
render_kw_only_separator = False
|
76
|
-
elif kind == inspect.Parameter.KEYWORD_ONLY and render_kw_only_separator:
|
77
|
-
src_params.append('*')
|
78
|
-
render_kw_only_separator = False
|
79
|
-
src_params.append(formatted)
|
80
|
-
if kind == inspect.Parameter.VAR_KEYWORD:
|
105
|
+
|
106
|
+
src_params.append(param_render(
|
107
|
+
p,
|
108
|
+
render_default=lambda _: p.name, # noqa
|
109
|
+
))
|
110
|
+
|
111
|
+
if isinstance(p, KwargsParam):
|
81
112
|
kwargs_name = p.name
|
82
113
|
else:
|
83
114
|
src_vals.append(p.name)
|
84
|
-
if render_pos_only_separator:
|
85
|
-
src_params.append('/')
|
86
115
|
|
87
|
-
|
116
|
+
if kwargs_name is not None:
|
117
|
+
src_vals.append(f'{builtin_tuple}({builtin_sorted}({kwargs_name}.items()))')
|
118
|
+
|
88
119
|
rendered = (
|
89
120
|
f'def __func__({", ".join(src_params)}):\n'
|
90
|
-
f' return ({", ".join(src_vals)}{
|
121
|
+
f' return ({", ".join(src_vals)}{"," if len(src_vals) == 1 else ""})\n'
|
91
122
|
)
|
92
123
|
exec(rendered, ns)
|
93
124
|
|
94
|
-
kfn = ns['__func__']
|
125
|
+
kfn: CacheKeyMaker = ns['__func__'] # type: ignore[assignment]
|
126
|
+
return kfn
|
127
|
+
|
128
|
+
|
129
|
+
def _make_cache_key_maker(
|
130
|
+
fn: ta.Any,
|
131
|
+
*,
|
132
|
+
bound: bool = False,
|
133
|
+
):
|
134
|
+
fn, partials = unwrap_func_with_partials(fn)
|
135
|
+
|
136
|
+
kfn = _make_unwrapped_cache_key_maker(fn, bound=bound)
|
137
|
+
|
95
138
|
for part in partials[::-1]:
|
96
139
|
kfn = functools.partial(kfn, *part.args, **part.keywords)
|
97
140
|
|
@@ -105,7 +148,6 @@ class _CachedFunction(ta.Generic[T], Abstract):
|
|
105
148
|
@dc.dataclass(frozen=True)
|
106
149
|
class Opts:
|
107
150
|
map_maker: ta.Callable[[], ta.MutableMapping] = dict
|
108
|
-
simple_key: bool = False
|
109
151
|
lock: DefaultLockable = None
|
110
152
|
transient: bool = False
|
111
153
|
|
@@ -122,7 +164,7 @@ class _CachedFunction(ta.Generic[T], Abstract):
|
|
122
164
|
|
123
165
|
self._fn = (fn,)
|
124
166
|
self._opts = opts
|
125
|
-
self._key_maker = key_maker if key_maker is not None else _make_cache_key_maker(fn
|
167
|
+
self._key_maker = key_maker if key_maker is not None else _make_cache_key_maker(fn)
|
126
168
|
|
127
169
|
self._lock = default_lock(opts.lock, False)() if opts.lock is not None else None
|
128
170
|
self._values = values if values is not None else opts.map_maker()
|
@@ -278,7 +320,7 @@ class _DescriptorCachedFunction(_CachedFunction[T]):
|
|
278
320
|
name = self._name
|
279
321
|
bound_fn = fn.__get__(instance, owner)
|
280
322
|
if self._bound_key_maker is None:
|
281
|
-
self._bound_key_maker = _make_cache_key_maker(fn,
|
323
|
+
self._bound_key_maker = _make_cache_key_maker(fn, bound=True)
|
282
324
|
|
283
325
|
bound = self.__class__(
|
284
326
|
fn,
|
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/lang/params.py
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- check validity
|
4
|
+
"""
|
5
|
+
import dataclasses as dc
|
6
|
+
import enum
|
7
|
+
import inspect
|
8
|
+
import typing as ta
|
9
|
+
|
10
|
+
from .classes.abstract import Abstract
|
11
|
+
from .classes.restrict import Final
|
12
|
+
from .classes.restrict import Sealed
|
13
|
+
from .maybes import Maybe
|
14
|
+
from .maybes import empty
|
15
|
+
from .maybes import just
|
16
|
+
|
17
|
+
|
18
|
+
T = ta.TypeVar('T')
|
19
|
+
|
20
|
+
|
21
|
+
##
|
22
|
+
|
23
|
+
|
24
|
+
@dc.dataclass(frozen=True)
|
25
|
+
class Param(Sealed, Abstract):
|
26
|
+
name: str
|
27
|
+
|
28
|
+
prefix: ta.ClassVar[str] = ''
|
29
|
+
|
30
|
+
@property
|
31
|
+
def name_with_prefix(self) -> str:
|
32
|
+
return f'{self.prefix}{self.name}'
|
33
|
+
|
34
|
+
|
35
|
+
#
|
36
|
+
|
37
|
+
|
38
|
+
@dc.dataclass(frozen=True)
|
39
|
+
class VariadicParam(Param, Abstract):
|
40
|
+
annotation: Maybe = empty()
|
41
|
+
|
42
|
+
|
43
|
+
@dc.dataclass(frozen=True)
|
44
|
+
class ArgsParam(VariadicParam, Final):
|
45
|
+
prefix: ta.ClassVar[str] = '*'
|
46
|
+
|
47
|
+
|
48
|
+
@dc.dataclass(frozen=True)
|
49
|
+
class KwargsParam(VariadicParam, Final):
|
50
|
+
prefix: ta.ClassVar[str] = '**'
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
|
55
|
+
|
56
|
+
@dc.dataclass(frozen=True, unsafe_hash=True)
|
57
|
+
class ValueParam(Param):
|
58
|
+
default: Maybe = empty()
|
59
|
+
annotation: Maybe = empty()
|
60
|
+
|
61
|
+
|
62
|
+
@dc.dataclass(frozen=True, unsafe_hash=True)
|
63
|
+
class PosOnlyParam(ValueParam, Final):
|
64
|
+
pass
|
65
|
+
|
66
|
+
|
67
|
+
@dc.dataclass(frozen=True, unsafe_hash=True)
|
68
|
+
class KwOnlyParam(ValueParam, Final):
|
69
|
+
pass
|
70
|
+
|
71
|
+
|
72
|
+
#
|
73
|
+
|
74
|
+
|
75
|
+
class ParamSeparator(enum.Enum):
|
76
|
+
POS_ONLY = '/'
|
77
|
+
KW_ONLY = '*'
|
78
|
+
|
79
|
+
|
80
|
+
##
|
81
|
+
|
82
|
+
|
83
|
+
def _inspect_empty_to_maybe(o: T) -> Maybe[T]:
|
84
|
+
if o is inspect.Parameter.empty:
|
85
|
+
return empty()
|
86
|
+
else:
|
87
|
+
return just(o)
|
88
|
+
|
89
|
+
|
90
|
+
class ParamSpec(ta.Sequence[Param], Final):
|
91
|
+
def __init__(self, *ps: Param) -> None:
|
92
|
+
super().__init__()
|
93
|
+
|
94
|
+
self._ps = ps
|
95
|
+
|
96
|
+
self._hash: int | None = None
|
97
|
+
|
98
|
+
self._has_defaults: bool | None = None
|
99
|
+
self._has_annotations: bool | None = None
|
100
|
+
|
101
|
+
self._with_seps: tuple[Param | ParamSeparator, ...] | None = None
|
102
|
+
|
103
|
+
#
|
104
|
+
|
105
|
+
@classmethod
|
106
|
+
def of_signature(
|
107
|
+
cls,
|
108
|
+
sig: inspect.Signature,
|
109
|
+
*,
|
110
|
+
offset: int = 0,
|
111
|
+
strip_defaults: bool = False,
|
112
|
+
strip_annotations: bool = False,
|
113
|
+
) -> 'ParamSpec':
|
114
|
+
ps: list[Param] = []
|
115
|
+
|
116
|
+
ip: inspect.Parameter
|
117
|
+
for i, ip in enumerate(sig.parameters.values()):
|
118
|
+
if i < offset:
|
119
|
+
continue
|
120
|
+
|
121
|
+
dfl = _inspect_empty_to_maybe(ip.default) if not strip_defaults else empty()
|
122
|
+
ann = _inspect_empty_to_maybe(ip.annotation) if not strip_annotations else empty()
|
123
|
+
|
124
|
+
if ip.kind == inspect.Parameter.POSITIONAL_ONLY:
|
125
|
+
ps.append(PosOnlyParam(ip.name, dfl, ann))
|
126
|
+
|
127
|
+
elif ip.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
|
128
|
+
ps.append(ValueParam(ip.name, dfl, ann))
|
129
|
+
|
130
|
+
elif ip.kind == inspect.Parameter.VAR_POSITIONAL:
|
131
|
+
ps.append(ArgsParam(ip.name))
|
132
|
+
|
133
|
+
elif ip.kind == inspect.Parameter.VAR_KEYWORD:
|
134
|
+
ps.append(KwargsParam(ip.name))
|
135
|
+
|
136
|
+
elif ip.kind == inspect.Parameter.KEYWORD_ONLY:
|
137
|
+
ps.append(KwOnlyParam(ip.name, dfl, ann))
|
138
|
+
|
139
|
+
else:
|
140
|
+
raise ValueError(ip.kind)
|
141
|
+
|
142
|
+
return cls(*ps)
|
143
|
+
|
144
|
+
#
|
145
|
+
|
146
|
+
def __repr__(self) -> str:
|
147
|
+
return f'{self.__class__.__name__}({", ".join(map(repr, self._ps))})'
|
148
|
+
|
149
|
+
def __hash__(self) -> int:
|
150
|
+
if (h := self._hash) is not None:
|
151
|
+
return h
|
152
|
+
self._hash = h = hash(self._ps)
|
153
|
+
return h
|
154
|
+
|
155
|
+
def __eq__(self, other: object) -> bool:
|
156
|
+
if type(other) is not ParamSpec:
|
157
|
+
raise TypeError(other)
|
158
|
+
return self._ps == other._ps # noqa
|
159
|
+
|
160
|
+
#
|
161
|
+
|
162
|
+
@property
|
163
|
+
def has_defaults(self) -> bool:
|
164
|
+
if (hd := self._has_defaults) is not None:
|
165
|
+
return hd
|
166
|
+
self._has_defaults = hd = any(
|
167
|
+
isinstance(p, ValueParam) and p.default.present
|
168
|
+
for p in self._ps
|
169
|
+
)
|
170
|
+
return hd
|
171
|
+
|
172
|
+
@property
|
173
|
+
def has_annotations(self) -> bool:
|
174
|
+
if (ha := self._has_defaults) is not None:
|
175
|
+
return ha
|
176
|
+
self._has_annotations = ha = any(
|
177
|
+
isinstance(p, (VariadicParam, ValueParam)) and p.annotation.present
|
178
|
+
for p in self._ps
|
179
|
+
)
|
180
|
+
return ha
|
181
|
+
|
182
|
+
#
|
183
|
+
|
184
|
+
@property
|
185
|
+
def with_seps(self) -> ta.Sequence[Param | ParamSeparator]:
|
186
|
+
if (ws := self._with_seps) is not None:
|
187
|
+
return ws
|
188
|
+
|
189
|
+
l: list[Param | ParamSeparator] = []
|
190
|
+
needs_pos_only = False
|
191
|
+
seen_kw_only = False
|
192
|
+
for p in self._ps:
|
193
|
+
if isinstance(p, PosOnlyParam):
|
194
|
+
needs_pos_only = True
|
195
|
+
elif needs_pos_only:
|
196
|
+
l.append(ParamSeparator.POS_ONLY)
|
197
|
+
needs_pos_only = False
|
198
|
+
|
199
|
+
if isinstance(p, KwOnlyParam) and not seen_kw_only:
|
200
|
+
l.append(ParamSeparator.KW_ONLY)
|
201
|
+
seen_kw_only = True
|
202
|
+
elif isinstance(p, KwargsParam):
|
203
|
+
seen_kw_only = True
|
204
|
+
|
205
|
+
l.append(p)
|
206
|
+
|
207
|
+
self._with_seps = ws = tuple(l)
|
208
|
+
return ws
|
209
|
+
|
210
|
+
#
|
211
|
+
|
212
|
+
@ta.overload
|
213
|
+
def __getitem__(self, index: int) -> Param: ...
|
214
|
+
|
215
|
+
@ta.overload
|
216
|
+
def __getitem__(self, index: slice) -> ta.Sequence[Param]: ...
|
217
|
+
|
218
|
+
def __getitem__(self, index):
|
219
|
+
return self._ps[index]
|
220
|
+
|
221
|
+
def __len__(self) -> int:
|
222
|
+
return len(self._ps)
|
223
|
+
|
224
|
+
|
225
|
+
##
|
226
|
+
|
227
|
+
|
228
|
+
def param_render(
|
229
|
+
p: Param | ParamSeparator,
|
230
|
+
*,
|
231
|
+
render_default: ta.Callable[[ta.Any], str] | None = None,
|
232
|
+
render_annotation: ta.Callable[[ta.Any], str] | None = None,
|
233
|
+
) -> str:
|
234
|
+
if isinstance(p, Param):
|
235
|
+
dfl_s: str | None = None
|
236
|
+
if isinstance(p, ValueParam) and p.default.present:
|
237
|
+
if render_default is None:
|
238
|
+
raise ValueError(f'Param {p.name} has a default but no default renderer provided')
|
239
|
+
dfl_s = render_default(p.default.must())
|
240
|
+
|
241
|
+
ann_s: str | None = None
|
242
|
+
if isinstance(p, (VariadicParam, ValueParam)) and p.annotation.present:
|
243
|
+
if render_annotation is None:
|
244
|
+
raise ValueError(f'Param {p.name} has an annotation but no annotation renderer provided')
|
245
|
+
ann_s = render_annotation(p.annotation.must())
|
246
|
+
|
247
|
+
if ann_s is not None:
|
248
|
+
if dfl_s is not None:
|
249
|
+
return f'{p.name_with_prefix}: {ann_s} = {dfl_s}'
|
250
|
+
else:
|
251
|
+
return f'{p.name_with_prefix}: {ann_s}'
|
252
|
+
elif dfl_s is not None:
|
253
|
+
return f'{p.name_with_prefix}={dfl_s}'
|
254
|
+
else:
|
255
|
+
return p.name_with_prefix
|
256
|
+
|
257
|
+
elif isinstance(p, ParamSeparator):
|
258
|
+
return p.value
|
259
|
+
|
260
|
+
else:
|
261
|
+
raise TypeError(p)
|
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
omlish/math/bits.py
CHANGED
omlish/math/stats.py
CHANGED
omlish/term/codes.py
CHANGED
@@ -3,7 +3,6 @@ from ._registry import register
|
|
3
3
|
|
4
4
|
@register
|
5
5
|
class SpacingPlugin:
|
6
|
-
|
7
6
|
def pytest_addoption(self, parser):
|
8
7
|
parser.addoption('--newlines-before', action='store', type=int, help='Adds newlines before tests')
|
9
8
|
parser.addoption('--newlines-after', action='store', type=int, help='Adds newlines after tests')
|
omlish/text/delimit.py
CHANGED