omlish 0.0.0.dev1__py3-none-any.whl → 0.0.0.dev2__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 -2
- omlish/argparse.py +4 -4
- omlish/asyncs/anyio.py +62 -1
- omlish/asyncs/futures.py +6 -6
- omlish/c3.py +4 -4
- omlish/check.py +6 -6
- omlish/collections/__init__.py +98 -63
- omlish/collections/cache/descriptor.py +5 -5
- omlish/collections/cache/impl.py +4 -4
- omlish/collections/coerce.py +43 -43
- omlish/collections/frozen.py +3 -3
- omlish/collections/identity.py +1 -1
- omlish/collections/mappings.py +3 -3
- omlish/collections/ordered.py +1 -1
- omlish/collections/skiplist.py +6 -6
- omlish/collections/sorted.py +3 -3
- omlish/collections/treap.py +17 -17
- omlish/collections/treapmap.py +2 -2
- omlish/collections/unmodifiable.py +28 -27
- omlish/configs/flattening.py +1 -1
- omlish/configs/props.py +1 -1
- omlish/dataclasses/impl/__init__.py +2 -0
- omlish/dataclasses/impl/api.py +5 -13
- omlish/dataclasses/impl/fields.py +1 -1
- omlish/dataclasses/impl/init.py +1 -1
- omlish/dataclasses/impl/internals.py +15 -0
- omlish/dataclasses/impl/main.py +4 -4
- omlish/dataclasses/impl/metaclass.py +1 -1
- omlish/dataclasses/impl/metadata.py +1 -1
- omlish/dataclasses/impl/order.py +1 -1
- omlish/dataclasses/impl/params.py +4 -38
- omlish/dataclasses/impl/reflect.py +1 -7
- omlish/dataclasses/impl/repr.py +23 -5
- omlish/dataclasses/impl/simple.py +2 -2
- omlish/dataclasses/impl/slots.py +2 -2
- omlish/dataclasses/impl/utils.py +4 -4
- omlish/dispatch/dispatch.py +9 -8
- omlish/dispatch/methods.py +2 -2
- omlish/docker.py +8 -6
- omlish/dynamic.py +5 -5
- omlish/graphs/dot/items.py +1 -1
- omlish/graphs/trees.py +15 -21
- omlish/inject/elements.py +1 -1
- omlish/inject/exceptions.py +1 -1
- omlish/inject/impl/injector.py +1 -1
- omlish/inject/impl/inspect.py +1 -1
- omlish/inject/injector.py +1 -1
- omlish/inject/providers.py +2 -2
- omlish/iterators.py +43 -2
- omlish/lang/__init__.py +167 -112
- omlish/lang/cached.py +13 -5
- omlish/lang/classes/__init__.py +35 -24
- omlish/lang/classes/abstract.py +1 -1
- omlish/lang/classes/simple.py +1 -1
- omlish/lang/clsdct.py +1 -1
- omlish/lang/contextmanagers.py +23 -15
- omlish/lang/datetimes.py +1 -1
- omlish/lang/descriptors.py +35 -2
- omlish/lang/exceptions.py +2 -0
- omlish/lang/functions.py +43 -13
- omlish/lang/imports.py +8 -8
- omlish/lang/iterables.py +1 -1
- omlish/lang/maybes.py +1 -1
- omlish/lang/objects.py +2 -2
- omlish/lang/timeouts.py +53 -0
- omlish/lang/typing.py +2 -2
- omlish/libc.py +6 -6
- omlish/marshal/base.py +6 -6
- omlish/marshal/dataclasses.py +2 -2
- omlish/marshal/enums.py +2 -2
- omlish/marshal/factories.py +10 -10
- omlish/marshal/iterables.py +2 -2
- omlish/marshal/mappings.py +2 -2
- omlish/marshal/optionals.py +4 -4
- omlish/marshal/polymorphism.py +4 -4
- omlish/marshal/standard.py +6 -6
- omlish/marshal/utils.py +1 -1
- omlish/os.py +13 -4
- omlish/procfs.py +336 -0
- omlish/reflect.py +2 -12
- omlish/replserver/console.py +9 -9
- omlish/replserver/server.py +4 -4
- omlish/sql/__init__.py +0 -0
- omlish/sql/_abcs.py +65 -0
- omlish/sql/dbs.py +90 -0
- omlish/stats.py +3 -3
- omlish/testing/pydevd.py +4 -6
- omlish/testing/pytest/inject/__init__.py +7 -0
- omlish/testing/pytest/inject/harness.py +23 -1
- omlish/testing/pytest/plugins/__init__.py +1 -1
- omlish/testing/pytest/plugins/pydevd.py +12 -0
- omlish/testing/pytest/plugins/switches.py +2 -2
- omlish/testing/testing.py +5 -5
- omlish/text/parts.py +3 -3
- omlish-0.0.0.dev2.dist-info/METADATA +31 -0
- omlish-0.0.0.dev2.dist-info/RECORD +193 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/WHEEL +1 -1
- 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-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/top_level.txt +0 -0
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/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
|
|
|
@@ -97,7 +99,7 @@ class ProxyIterator(ta.Iterator[T]):
|
|
|
97
99
|
|
|
98
100
|
class PrefetchIterator(ta.Iterator[T]):
|
|
99
101
|
|
|
100
|
-
def __init__(self, fn: ta.
|
|
102
|
+
def __init__(self, fn: ta.Callable[[], T] | None = None) -> None:
|
|
101
103
|
super().__init__()
|
|
102
104
|
|
|
103
105
|
self._fn = fn
|
|
@@ -138,7 +140,7 @@ class RetainIterator(ta.Iterator[T]):
|
|
|
138
140
|
return item
|
|
139
141
|
|
|
140
142
|
|
|
141
|
-
def unzip(it: ta.Iterable[T], width:
|
|
143
|
+
def unzip(it: ta.Iterable[T], width: int | None = None) -> list:
|
|
142
144
|
if width is None:
|
|
143
145
|
if not isinstance(it, PeekIterator):
|
|
144
146
|
it = PeekIterator(iter(it))
|
|
@@ -182,3 +184,42 @@ def chunk(n: int, iterable: ta.Iterable[T], strict: bool = False) -> ta.Iterator
|
|
|
182
184
|
return iter(ret())
|
|
183
185
|
else:
|
|
184
186
|
return iterator
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def merge_on(
|
|
190
|
+
function: ta.Callable[[T], U],
|
|
191
|
+
*its: ta.Iterable[T],
|
|
192
|
+
) -> ta.Iterator[tuple[U, list[tuple[int, T]]]]:
|
|
193
|
+
indexed_its = [
|
|
194
|
+
(
|
|
195
|
+
(function(item), it_idx, item)
|
|
196
|
+
for it_idx, item in zip(itertools.repeat(it_idx), it)
|
|
197
|
+
)
|
|
198
|
+
for it_idx, it in enumerate(its)
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
grouped_indexed_its = itertools.groupby(
|
|
202
|
+
heapq.merge(*indexed_its),
|
|
203
|
+
key=lambda item_tuple: item_tuple[0],
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
(fn_item, [(it_idx, item) for _, it_idx, item in grp])
|
|
208
|
+
for fn_item, grp in grouped_indexed_its
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def expand_indexed_pairs(
|
|
213
|
+
seq: ta.Iterable[tuple[int, T]],
|
|
214
|
+
default: T,
|
|
215
|
+
*,
|
|
216
|
+
width: int | None = None,
|
|
217
|
+
) -> list[T]:
|
|
218
|
+
width_ = width
|
|
219
|
+
if width_ is None:
|
|
220
|
+
width_ = (max(idx for idx, _ in seq) + 1) if seq else 0
|
|
221
|
+
result = [default] * width_
|
|
222
|
+
for idx, value in seq:
|
|
223
|
+
if idx < width_:
|
|
224
|
+
result[idx] = value
|
|
225
|
+
return result
|
omlish/lang/__init__.py
CHANGED
|
@@ -1,112 +1,167 @@
|
|
|
1
|
-
from .cached import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from .classes import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
from .
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
from .
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
from .contextmanagers import
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
from .
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
from .
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
from .
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
from .
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
from .
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
from .cached import ( # noqa
|
|
2
|
+
cached_function,
|
|
3
|
+
cached_property,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
from .classes import ( # noqa
|
|
7
|
+
Abstract,
|
|
8
|
+
Callable,
|
|
9
|
+
Descriptor,
|
|
10
|
+
Final,
|
|
11
|
+
FinalException,
|
|
12
|
+
LazySingleton,
|
|
13
|
+
Marker,
|
|
14
|
+
Namespace,
|
|
15
|
+
NoBool,
|
|
16
|
+
NotInstantiable,
|
|
17
|
+
NotPicklable,
|
|
18
|
+
PackageSealed,
|
|
19
|
+
Picklable,
|
|
20
|
+
Sealed,
|
|
21
|
+
SealedException,
|
|
22
|
+
SimpleMetaDict,
|
|
23
|
+
Singleton,
|
|
24
|
+
Virtual,
|
|
25
|
+
is_abstract,
|
|
26
|
+
is_abstract_class,
|
|
27
|
+
is_abstract_method,
|
|
28
|
+
make_abstract,
|
|
29
|
+
no_bool,
|
|
30
|
+
virtual_check,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from .clsdct import ( # noqa
|
|
34
|
+
ClassDctFn,
|
|
35
|
+
cls_dct_fn,
|
|
36
|
+
get_caller_cls_dct,
|
|
37
|
+
is_possibly_cls_dct,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from .cmp import ( # noqa
|
|
41
|
+
Infinity,
|
|
42
|
+
InfinityType,
|
|
43
|
+
NegativeInfinity,
|
|
44
|
+
NegativeInfinityType,
|
|
45
|
+
cmp,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
from .contextmanagers import ( # noqa
|
|
49
|
+
ContextManaged,
|
|
50
|
+
ContextWrapped,
|
|
51
|
+
DefaultLockable,
|
|
52
|
+
ExitStacked,
|
|
53
|
+
Lockable,
|
|
54
|
+
NOP_CONTEXT_MANAGED,
|
|
55
|
+
NOP_CONTEXT_MANAGER,
|
|
56
|
+
NopContextManaged,
|
|
57
|
+
NopContextManager,
|
|
58
|
+
a_defer,
|
|
59
|
+
attr_setting,
|
|
60
|
+
breakpoint_on_exception,
|
|
61
|
+
context_var_setting,
|
|
62
|
+
context_wrapped,
|
|
63
|
+
default_lock,
|
|
64
|
+
defer,
|
|
65
|
+
disposing,
|
|
66
|
+
maybe_managing,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
from .datetimes import ( # noqa
|
|
70
|
+
months_ago,
|
|
71
|
+
parse_date,
|
|
72
|
+
parse_timedelta,
|
|
73
|
+
to_seconds,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
from .descriptors import ( # noqa
|
|
77
|
+
AccessForbiddenException,
|
|
78
|
+
access_forbidden,
|
|
79
|
+
classonly,
|
|
80
|
+
is_method_descriptor,
|
|
81
|
+
unwrap_method_descriptors,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
from .exceptions import ( # noqa
|
|
85
|
+
Unreachable,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
from .functions import ( # noqa
|
|
89
|
+
Args,
|
|
90
|
+
VoidException,
|
|
91
|
+
constant,
|
|
92
|
+
identity,
|
|
93
|
+
is_lambda,
|
|
94
|
+
is_none,
|
|
95
|
+
is_not_none,
|
|
96
|
+
maybe_call,
|
|
97
|
+
periodically,
|
|
98
|
+
raise_,
|
|
99
|
+
recurse,
|
|
100
|
+
try_,
|
|
101
|
+
unwrap_func,
|
|
102
|
+
unwrap_func_with_partials,
|
|
103
|
+
void,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
from .imports import ( # noqa
|
|
107
|
+
import_all,
|
|
108
|
+
import_module,
|
|
109
|
+
import_module_attr,
|
|
110
|
+
lazy_import,
|
|
111
|
+
proxy_import,
|
|
112
|
+
try_import,
|
|
113
|
+
yield_import_all,
|
|
114
|
+
yield_importable,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
from .iterables import ( # noqa
|
|
118
|
+
BUILTIN_SCALAR_ITERABLE_TYPES,
|
|
119
|
+
asrange,
|
|
120
|
+
exhaust,
|
|
121
|
+
ilen,
|
|
122
|
+
peek,
|
|
123
|
+
prodrange,
|
|
124
|
+
take,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
from .maybes import ( # noqa
|
|
128
|
+
Maybe,
|
|
129
|
+
empty,
|
|
130
|
+
just,
|
|
131
|
+
maybe,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
from .objects import ( # noqa
|
|
135
|
+
SimpleProxy,
|
|
136
|
+
arg_repr,
|
|
137
|
+
attr_repr,
|
|
138
|
+
new_type,
|
|
139
|
+
super_meta,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
from .strings import ( # noqa
|
|
143
|
+
camel_case,
|
|
144
|
+
indent_lines,
|
|
145
|
+
is_dunder,
|
|
146
|
+
is_ident,
|
|
147
|
+
is_ident_cont,
|
|
148
|
+
is_ident_start,
|
|
149
|
+
is_sunder,
|
|
150
|
+
prefix_lines,
|
|
151
|
+
snake_case,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
from .timeouts import ( # noqa
|
|
155
|
+
DeadlineTimeout,
|
|
156
|
+
InfiniteTimeout,
|
|
157
|
+
Timeout,
|
|
158
|
+
TimeoutLike,
|
|
159
|
+
timeout,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
from .typing import ( # noqa
|
|
163
|
+
BytesLike,
|
|
164
|
+
protocol_check,
|
|
165
|
+
typed_lambda,
|
|
166
|
+
typed_partial,
|
|
167
|
+
)
|
omlish/lang/cached.py
CHANGED
|
@@ -105,11 +105,11 @@ class _CachedFunction(ta.Generic[T]):
|
|
|
105
105
|
opts: Opts = Opts(),
|
|
106
106
|
keyer: ta.Callable[..., tuple] | None = None,
|
|
107
107
|
values: ta.MutableMapping | None = None,
|
|
108
|
-
value_fn: ta.
|
|
108
|
+
value_fn: ta.Callable[P, T] | None = None,
|
|
109
109
|
) -> None:
|
|
110
110
|
super().__init__()
|
|
111
111
|
|
|
112
|
-
self._fn = fn
|
|
112
|
+
self._fn = (fn,)
|
|
113
113
|
self._opts = opts
|
|
114
114
|
self._keyer = keyer if keyer is not None else _make_cache_keyer(fn, simple=opts.simple_key)
|
|
115
115
|
|
|
@@ -118,6 +118,14 @@ class _CachedFunction(ta.Generic[T]):
|
|
|
118
118
|
self._value_fn = value_fn if value_fn is not None else fn
|
|
119
119
|
functools.update_wrapper(self, fn)
|
|
120
120
|
|
|
121
|
+
@property
|
|
122
|
+
def _fn(self):
|
|
123
|
+
return self.__fn
|
|
124
|
+
|
|
125
|
+
@_fn.setter
|
|
126
|
+
def _fn(self, x):
|
|
127
|
+
self.__fn = x
|
|
128
|
+
|
|
121
129
|
def reset(self) -> None:
|
|
122
130
|
self._values = {}
|
|
123
131
|
|
|
@@ -157,8 +165,8 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
|
|
|
157
165
|
*,
|
|
158
166
|
instance: ta.Any = None,
|
|
159
167
|
owner: ta.Any = None,
|
|
160
|
-
name:
|
|
161
|
-
**kwargs
|
|
168
|
+
name: str | None = None,
|
|
169
|
+
**kwargs,
|
|
162
170
|
) -> None:
|
|
163
171
|
super().__init__(fn, **kwargs)
|
|
164
172
|
|
|
@@ -173,7 +181,7 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
|
|
|
173
181
|
if owner is self._owner and (instance is self._instance or scope is classmethod):
|
|
174
182
|
return self
|
|
175
183
|
|
|
176
|
-
fn = self._fn
|
|
184
|
+
fn, = self._fn
|
|
177
185
|
name = self._name
|
|
178
186
|
bound_fn = fn.__get__(instance, owner)
|
|
179
187
|
if self._bound_keyer is None:
|
omlish/lang/classes/__init__.py
CHANGED
|
@@ -1,24 +1,35 @@
|
|
|
1
|
-
from .abstract import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from .restrict import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
from .
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
from .abstract import ( # noqa
|
|
2
|
+
Abstract,
|
|
3
|
+
is_abstract,
|
|
4
|
+
is_abstract_class,
|
|
5
|
+
is_abstract_method,
|
|
6
|
+
make_abstract,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from .restrict import ( # noqa
|
|
10
|
+
Final,
|
|
11
|
+
FinalException,
|
|
12
|
+
NoBool,
|
|
13
|
+
NotInstantiable,
|
|
14
|
+
NotPicklable,
|
|
15
|
+
PackageSealed,
|
|
16
|
+
Sealed,
|
|
17
|
+
SealedException,
|
|
18
|
+
no_bool,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from .simple import ( # noqa
|
|
22
|
+
LazySingleton,
|
|
23
|
+
Marker,
|
|
24
|
+
Namespace,
|
|
25
|
+
SimpleMetaDict,
|
|
26
|
+
Singleton,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from .virtual import ( # noqa
|
|
30
|
+
Callable,
|
|
31
|
+
Descriptor,
|
|
32
|
+
Picklable,
|
|
33
|
+
Virtual,
|
|
34
|
+
virtual_check,
|
|
35
|
+
)
|
omlish/lang/classes/abstract.py
CHANGED
omlish/lang/classes/simple.py
CHANGED
omlish/lang/clsdct.py
CHANGED
|
@@ -37,7 +37,7 @@ def get_caller_cls_dct(offset: int = 0) -> ta.MutableMapping[str, ta.Any]:
|
|
|
37
37
|
|
|
38
38
|
class ClassDctFn:
|
|
39
39
|
|
|
40
|
-
def __init__(self, fn: ta.Callable, offset:
|
|
40
|
+
def __init__(self, fn: ta.Callable, offset: int | None = None, *, wrap=True) -> None:
|
|
41
41
|
super().__init__()
|
|
42
42
|
|
|
43
43
|
self._fn = fn
|
omlish/lang/contextmanagers.py
CHANGED
|
@@ -19,10 +19,10 @@ class ContextManaged:
|
|
|
19
19
|
|
|
20
20
|
def __exit__(
|
|
21
21
|
self,
|
|
22
|
-
exc_type: ta.
|
|
23
|
-
exc_val:
|
|
24
|
-
exc_tb:
|
|
25
|
-
) ->
|
|
22
|
+
exc_type: ta.Type[Exception] | None,
|
|
23
|
+
exc_val: Exception | None,
|
|
24
|
+
exc_tb: types.TracebackType | None,
|
|
25
|
+
) -> bool | None:
|
|
26
26
|
return None
|
|
27
27
|
|
|
28
28
|
|
|
@@ -51,7 +51,7 @@ NOP_CONTEXT_MANAGER = NopContextManager()
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
@contextlib.contextmanager
|
|
54
|
-
def defer(fn: ta.Callable) -> ta.
|
|
54
|
+
def defer(fn: ta.Callable) -> ta.Generator[ta.Callable, None, None]:
|
|
55
55
|
try:
|
|
56
56
|
yield fn
|
|
57
57
|
finally:
|
|
@@ -59,7 +59,7 @@ def defer(fn: ta.Callable) -> ta.Iterator[ta.Callable]:
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
@contextlib.asynccontextmanager
|
|
62
|
-
async def a_defer(fn: ta.Awaitable) -> ta.
|
|
62
|
+
async def a_defer(fn: ta.Awaitable) -> ta.AsyncGenerator[ta.Awaitable, None]:
|
|
63
63
|
try:
|
|
64
64
|
yield fn
|
|
65
65
|
finally:
|
|
@@ -146,10 +146,10 @@ class ExitStacked:
|
|
|
146
146
|
|
|
147
147
|
def __exit__(
|
|
148
148
|
self,
|
|
149
|
-
exc_type: ta.
|
|
150
|
-
exc_val:
|
|
151
|
-
exc_tb:
|
|
152
|
-
) ->
|
|
149
|
+
exc_type: ta.Type[Exception] | None,
|
|
150
|
+
exc_val: Exception | None,
|
|
151
|
+
exc_tb: types.TracebackType | None,
|
|
152
|
+
) -> bool | None:
|
|
153
153
|
self._exit_stack.__exit__(exc_type, exc_val, exc_tb)
|
|
154
154
|
try:
|
|
155
155
|
superfn = super().__exit__ # type: ignore
|
|
@@ -162,20 +162,28 @@ class ExitStacked:
|
|
|
162
162
|
##
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
ContextWrappable: ta.TypeAlias = ta.
|
|
165
|
+
ContextWrappable: ta.TypeAlias = ta.ContextManager | str | ta.Callable[..., ta.ContextManager]
|
|
166
166
|
|
|
167
167
|
|
|
168
168
|
class ContextWrapped:
|
|
169
169
|
|
|
170
|
-
def __init__(self, fn: ta.Callable, cm:
|
|
170
|
+
def __init__(self, fn: ta.Callable, cm: str | ContextWrappable) -> None:
|
|
171
171
|
super().__init__()
|
|
172
172
|
|
|
173
|
-
self._fn = fn
|
|
173
|
+
self._fn = (fn,)
|
|
174
174
|
self._cm = cm
|
|
175
175
|
self._name: str | None = None
|
|
176
176
|
|
|
177
177
|
functools.update_wrapper(self, fn)
|
|
178
178
|
|
|
179
|
+
@property
|
|
180
|
+
def _fn(self):
|
|
181
|
+
return self.__fn
|
|
182
|
+
|
|
183
|
+
@_fn.setter
|
|
184
|
+
def _fn(self, x):
|
|
185
|
+
self.__fn = x
|
|
186
|
+
|
|
179
187
|
def __set_name__(self, owner, name):
|
|
180
188
|
if name is not None:
|
|
181
189
|
if self._name is not None:
|
|
@@ -187,7 +195,7 @@ class ContextWrapped:
|
|
|
187
195
|
def __get__(self, instance, owner=None):
|
|
188
196
|
if instance is None and owner is None:
|
|
189
197
|
return self
|
|
190
|
-
fn = self._fn.__get__(instance, owner) # noqa
|
|
198
|
+
fn = self._fn[0].__get__(instance, owner) # noqa
|
|
191
199
|
cm: ta.Any = self._cm
|
|
192
200
|
if isinstance(self._cm, str):
|
|
193
201
|
if instance is not None:
|
|
@@ -217,7 +225,7 @@ class ContextWrapped:
|
|
|
217
225
|
if not hasattr(cm, '__enter__') and callable(cm):
|
|
218
226
|
cm = cm(*args, **kwargs)
|
|
219
227
|
with cm: # type: ignore
|
|
220
|
-
return self._fn(*args, **kwargs)
|
|
228
|
+
return self._fn[0](*args, **kwargs)
|
|
221
229
|
|
|
222
230
|
|
|
223
231
|
def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], CallableT]:
|
omlish/lang/datetimes.py
CHANGED
|
@@ -62,6 +62,6 @@ def parse_timedelta(s: str) -> datetime.timedelta:
|
|
|
62
62
|
for k, v in match.groupdict().items()
|
|
63
63
|
if k != 'negative' and v is not None}
|
|
64
64
|
if not timedelta_kwargs:
|
|
65
|
-
raise ValueError
|
|
65
|
+
raise ValueError
|
|
66
66
|
sign = -1 if match.groupdict().get('negative') else 1
|
|
67
67
|
return sign * datetime.timedelta(**timedelta_kwargs)
|
omlish/lang/descriptors.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import functools
|
|
1
2
|
import typing as ta
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
T = ta.TypeVar('T')
|
|
6
|
+
|
|
7
|
+
|
|
4
8
|
##
|
|
5
9
|
|
|
6
10
|
|
|
@@ -26,14 +30,14 @@ def unwrap_method_descriptors(fn: ta.Callable) -> ta.Callable:
|
|
|
26
30
|
|
|
27
31
|
class AccessForbiddenException(Exception):
|
|
28
32
|
|
|
29
|
-
def __init__(self, name:
|
|
33
|
+
def __init__(self, name: str | None = None, *args: ta.Any, **kwargs: ta.Any) -> None:
|
|
30
34
|
super().__init__(*((name,) if name is not None else ()), *args, **kwargs) # noqa
|
|
31
35
|
self.name = name
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
class AccessForbiddenDescriptor:
|
|
35
39
|
|
|
36
|
-
def __init__(self, name:
|
|
40
|
+
def __init__(self, name: str | None = None) -> None:
|
|
37
41
|
super().__init__()
|
|
38
42
|
|
|
39
43
|
self._name = name
|
|
@@ -50,3 +54,32 @@ class AccessForbiddenDescriptor:
|
|
|
50
54
|
|
|
51
55
|
def access_forbidden():
|
|
52
56
|
return AccessForbiddenDescriptor()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class _ClassOnly:
|
|
63
|
+
def __init__(self, mth):
|
|
64
|
+
if not isinstance(mth, classmethod):
|
|
65
|
+
raise TypeError(f'must be classmethod: {mth}')
|
|
66
|
+
super().__init__()
|
|
67
|
+
self._mth = (mth,)
|
|
68
|
+
functools.update_wrapper(self, mth) # type: ignore
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def _mth(self):
|
|
72
|
+
return self.__mth
|
|
73
|
+
|
|
74
|
+
@_mth.setter
|
|
75
|
+
def _mth(self, x):
|
|
76
|
+
self.__mth = x
|
|
77
|
+
|
|
78
|
+
def __get__(self, instance, owner):
|
|
79
|
+
if instance is not None:
|
|
80
|
+
raise TypeError(f'method must not be used on instance: {self._mth}')
|
|
81
|
+
return self._mth[0].__get__(instance, owner)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def classonly(obj: T) -> T: # noqa
|
|
85
|
+
return _ClassOnly(obj) # type: ignore
|