omlish 0.0.0.dev2__py3-none-any.whl → 0.0.0.dev4__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 +1 -2
- omlish/__init__.py +8 -0
- omlish/argparse.py +4 -4
- omlish/asyncs/__init__.py +23 -2
- omlish/asyncs/anyio.py +13 -11
- omlish/asyncs/asyncs.py +1 -3
- omlish/asyncs/flavors.py +201 -0
- omlish/asyncs/futures.py +10 -9
- omlish/asyncs/trio_asyncio.py +41 -0
- omlish/c3.py +1 -1
- omlish/check.py +3 -3
- 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 +8 -8
- omlish/collections/cache/impl.py +24 -17
- omlish/collections/cache/types.py +1 -1
- omlish/collections/coerce.py +1 -1
- omlish/collections/frozen.py +6 -6
- omlish/collections/identity.py +3 -4
- omlish/collections/mappings.py +2 -2
- omlish/collections/ordered.py +7 -7
- omlish/collections/skiplist.py +1 -1
- omlish/collections/sorted.py +1 -1
- omlish/collections/treap.py +25 -0
- omlish/collections/treapmap.py +57 -5
- omlish/collections/unmodifiable.py +9 -9
- omlish/collections/utils.py +1 -1
- omlish/configs/flattening.py +7 -6
- omlish/configs/props.py +3 -3
- omlish/dataclasses/__init__.py +1 -1
- omlish/dataclasses/impl/__init__.py +17 -1
- omlish/dataclasses/impl/api.py +10 -11
- omlish/dataclasses/impl/as_.py +4 -4
- omlish/dataclasses/impl/exceptions.py +1 -1
- omlish/dataclasses/impl/fields.py +7 -7
- omlish/dataclasses/impl/frozen.py +2 -2
- omlish/dataclasses/impl/init.py +5 -5
- omlish/dataclasses/impl/internals.py +1 -1
- omlish/dataclasses/impl/metaclass.py +1 -1
- omlish/dataclasses/impl/order.py +1 -1
- omlish/dataclasses/impl/replace.py +1 -1
- omlish/dataclasses/impl/repr.py +4 -4
- omlish/dataclasses/impl/utils.py +6 -6
- omlish/defs.py +13 -17
- omlish/{procfs.py → diag/procfs.py} +22 -24
- omlish/diag/ps.py +47 -0
- omlish/{replserver → diag/replserver}/console.py +18 -20
- omlish/{replserver → diag/replserver}/server.py +8 -8
- omlish/dispatch/dispatch.py +5 -8
- omlish/dispatch/functions.py +1 -1
- omlish/dispatch/methods.py +4 -5
- omlish/docker.py +1 -1
- omlish/dynamic.py +10 -10
- omlish/fnpairs.py +400 -0
- omlish/graphs/trees.py +13 -13
- omlish/inject/__init__.py +7 -7
- omlish/inject/elements.py +1 -1
- omlish/inject/exceptions.py +7 -7
- omlish/inject/impl/elements.py +17 -5
- omlish/inject/impl/injector.py +12 -10
- omlish/inject/impl/inspect.py +2 -2
- omlish/inject/impl/scopes.py +12 -11
- omlish/inject/proxy.py +5 -5
- omlish/iterators.py +19 -24
- omlish/json.py +143 -6
- omlish/lang/__init__.py +13 -4
- omlish/lang/cached.py +2 -5
- omlish/lang/classes/__init__.py +2 -2
- omlish/lang/classes/abstract.py +2 -2
- omlish/lang/classes/restrict.py +14 -14
- omlish/lang/classes/simple.py +1 -1
- omlish/lang/classes/virtual.py +5 -5
- omlish/lang/clsdct.py +1 -1
- omlish/lang/cmp.py +2 -2
- omlish/lang/contextmanagers.py +12 -14
- omlish/lang/descriptors.py +16 -4
- omlish/lang/exceptions.py +1 -1
- omlish/lang/functions.py +58 -22
- omlish/lang/imports.py +22 -27
- omlish/lang/iterables.py +2 -2
- omlish/lang/maybes.py +1 -0
- omlish/lang/objects.py +15 -9
- omlish/lang/resolving.py +1 -1
- omlish/lang/strings.py +1 -1
- omlish/lang/sys.py +7 -0
- omlish/lang/typing.py +3 -3
- omlish/libc.py +9 -5
- 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 +3 -3
- omlish/marshal/exceptions.py +1 -1
- omlish/marshal/global_.py +10 -4
- omlish/marshal/objects.py +1 -2
- omlish/marshal/registries.py +3 -3
- omlish/marshal/utils.py +2 -2
- omlish/marshal/values.py +1 -1
- omlish/math.py +9 -9
- omlish/reflect.py +3 -3
- omlish/sql/__init__.py +9 -0
- omlish/sql/asyncs.py +148 -0
- omlish/stats.py +4 -5
- omlish/term.py +1 -1
- omlish/testing/pydevd.py +28 -6
- omlish/testing/pytest/inject/harness.py +1 -1
- omlish/testing/pytest/plugins/pydevd.py +1 -1
- omlish/testing/pytest/plugins/switches.py +1 -1
- omlish/text/delimit.py +3 -6
- {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/METADATA +4 -1
- omlish-0.0.0.dev4.dist-info/RECORD +195 -0
- {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.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-0.0.0.dev2.dist-info/RECORD +0 -193
- /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/sql/{_abcs.py → _abc.py} +0 -0
- {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/top_level.txt +0 -0
omlish/lang/cached.py
CHANGED
|
@@ -207,7 +207,7 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
|
|
|
207
207
|
return bound
|
|
208
208
|
|
|
209
209
|
|
|
210
|
-
def cached_function(fn=None, **kwargs):
|
|
210
|
+
def cached_function(fn=None, **kwargs): # noqa
|
|
211
211
|
if fn is None:
|
|
212
212
|
return functools.partial(cached_function, **kwargs)
|
|
213
213
|
opts = _CachedFunction.Opts(**kwargs)
|
|
@@ -217,9 +217,6 @@ def cached_function(fn=None, **kwargs):
|
|
|
217
217
|
return _CachedFunctionDescriptor(fn, scope, opts=opts)
|
|
218
218
|
|
|
219
219
|
|
|
220
|
-
cached_function = cached_function
|
|
221
|
-
|
|
222
|
-
|
|
223
220
|
##
|
|
224
221
|
|
|
225
222
|
|
|
@@ -269,7 +266,7 @@ class _CachedProperty:
|
|
|
269
266
|
raise TypeError(self._name)
|
|
270
267
|
|
|
271
268
|
|
|
272
|
-
def cached_property(fn=None, **kwargs):
|
|
269
|
+
def cached_property(fn=None, **kwargs): # noqa
|
|
273
270
|
if fn is None:
|
|
274
271
|
return functools.partial(cached_property, **kwargs)
|
|
275
272
|
return _CachedProperty(fn, **kwargs)
|
omlish/lang/classes/__init__.py
CHANGED
omlish/lang/classes/abstract.py
CHANGED
|
@@ -23,7 +23,7 @@ def make_abstract(obj: T) -> T:
|
|
|
23
23
|
return obj
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
class Abstract(abc.ABC):
|
|
26
|
+
class Abstract(abc.ABC): # noqa
|
|
27
27
|
__slots__ = ()
|
|
28
28
|
|
|
29
29
|
def __forceabstract__(self):
|
|
@@ -31,7 +31,7 @@ class Abstract(abc.ABC):
|
|
|
31
31
|
|
|
32
32
|
setattr(__forceabstract__, '__isabstractmethod__', True)
|
|
33
33
|
|
|
34
|
-
def __init_subclass__(cls, **kwargs) -> None:
|
|
34
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
35
35
|
if Abstract in cls.__bases__:
|
|
36
36
|
cls.__forceabstract__ = Abstract.__forceabstract__ # type: ignore
|
|
37
37
|
else:
|
omlish/lang/classes/restrict.py
CHANGED
|
@@ -8,9 +8,9 @@ from .abstract import is_abstract
|
|
|
8
8
|
##
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class
|
|
11
|
+
class FinalError(TypeError):
|
|
12
12
|
|
|
13
|
-
def __init__(self, _type:
|
|
13
|
+
def __init__(self, _type: type) -> None:
|
|
14
14
|
super().__init__()
|
|
15
15
|
|
|
16
16
|
self._type = _type
|
|
@@ -22,17 +22,17 @@ class FinalException(TypeError):
|
|
|
22
22
|
class Final(Abstract):
|
|
23
23
|
__slots__ = ()
|
|
24
24
|
|
|
25
|
-
def __init_subclass__(cls, **kwargs) -> None:
|
|
25
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
26
26
|
super().__init_subclass__(**kwargs)
|
|
27
27
|
|
|
28
28
|
abstracts: set[ta.Any] = set()
|
|
29
29
|
for base in cls.__bases__:
|
|
30
30
|
if base is Abstract:
|
|
31
|
-
raise
|
|
31
|
+
raise FinalError(base)
|
|
32
32
|
elif base is Final:
|
|
33
33
|
continue
|
|
34
34
|
elif Final in base.__mro__:
|
|
35
|
-
raise
|
|
35
|
+
raise FinalError(base)
|
|
36
36
|
else:
|
|
37
37
|
abstracts.update(getattr(base, '__abstractmethods__', []))
|
|
38
38
|
|
|
@@ -40,15 +40,15 @@ class Final(Abstract):
|
|
|
40
40
|
try:
|
|
41
41
|
v = cls.__dict__[a]
|
|
42
42
|
except KeyError:
|
|
43
|
-
raise
|
|
43
|
+
raise FinalError(a) from None
|
|
44
44
|
if is_abstract(v):
|
|
45
|
-
raise
|
|
45
|
+
raise FinalError(a)
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
##
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
class
|
|
51
|
+
class SealedError(TypeError):
|
|
52
52
|
|
|
53
53
|
def __init__(self, _type) -> None:
|
|
54
54
|
super().__init__()
|
|
@@ -62,24 +62,24 @@ class SealedException(TypeError):
|
|
|
62
62
|
class Sealed:
|
|
63
63
|
__slots__ = ()
|
|
64
64
|
|
|
65
|
-
def __init_subclass__(cls, **kwargs) -> None:
|
|
65
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
66
66
|
for base in cls.__bases__:
|
|
67
67
|
if base is not Abstract:
|
|
68
68
|
if Sealed in base.__bases__:
|
|
69
69
|
if cls.__module__ != base.__module__:
|
|
70
|
-
raise
|
|
70
|
+
raise SealedError(base)
|
|
71
71
|
super().__init_subclass__(**kwargs)
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
class PackageSealed:
|
|
75
75
|
__slots__ = ()
|
|
76
76
|
|
|
77
|
-
def __init_subclass__(cls, **kwargs) -> None:
|
|
77
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
78
78
|
for base in cls.__bases__:
|
|
79
79
|
if base is not Abstract:
|
|
80
80
|
if PackageSealed in base.__bases__:
|
|
81
81
|
if cls.__module__.split('.')[:-1] != base.__module__.split('.')[:-1]:
|
|
82
|
-
raise
|
|
82
|
+
raise SealedError(base)
|
|
83
83
|
super().__init_subclass__(**kwargs)
|
|
84
84
|
|
|
85
85
|
|
|
@@ -89,7 +89,7 @@ class PackageSealed:
|
|
|
89
89
|
class NotInstantiable(Abstract):
|
|
90
90
|
__slots__ = ()
|
|
91
91
|
|
|
92
|
-
def __new__(cls, *args, **kwargs)
|
|
92
|
+
def __new__(cls, *args, **kwargs):
|
|
93
93
|
raise TypeError
|
|
94
94
|
|
|
95
95
|
|
|
@@ -133,5 +133,5 @@ class _NoBoolDescriptor:
|
|
|
133
133
|
return self._fn(*args, **kwargs)
|
|
134
134
|
|
|
135
135
|
|
|
136
|
-
def no_bool(fn):
|
|
136
|
+
def no_bool(fn): # noqa
|
|
137
137
|
return _NoBoolDescriptor(fn)
|
omlish/lang/classes/simple.py
CHANGED
|
@@ -100,7 +100,7 @@ class Singleton:
|
|
|
100
100
|
def __new__(cls):
|
|
101
101
|
return cls.__dict__[_SINGLETON_INSTANCE_ATTR]
|
|
102
102
|
|
|
103
|
-
def __init_subclass__(cls, **kwargs):
|
|
103
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
104
104
|
super().__init_subclass__(**kwargs)
|
|
105
105
|
_set_singleton_instance(super().__new__(cls)) # noqa
|
|
106
106
|
|
omlish/lang/classes/virtual.py
CHANGED
|
@@ -15,10 +15,10 @@ Ty = ta.TypeVar('Ty', bound=type)
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def _make_not_instantiable():
|
|
18
|
-
def __new__(cls, *args, **kwargs):
|
|
18
|
+
def __new__(cls, *args, **kwargs): # noqa
|
|
19
19
|
raise TypeError(cls)
|
|
20
20
|
|
|
21
|
-
def __init__(self, *args, **kwargs):
|
|
21
|
+
def __init__(self, *args, **kwargs): # noqa
|
|
22
22
|
raise TypeError(self)
|
|
23
23
|
|
|
24
24
|
return {
|
|
@@ -49,7 +49,7 @@ class _VirtualMeta(abc.ABCMeta):
|
|
|
49
49
|
reqset -= set(mro_cls.__dict__)
|
|
50
50
|
return reqset
|
|
51
51
|
|
|
52
|
-
def __subclasshook__(cls, subclass):
|
|
52
|
+
def __subclasshook__(cls, subclass): # noqa
|
|
53
53
|
if cls is not kls:
|
|
54
54
|
return super(kls, cls).__subclasshook__(subclass) # type: ignore
|
|
55
55
|
if get_missing_reqs(subclass):
|
|
@@ -117,11 +117,11 @@ class Callable(NotInstantiable, Final, ta.Generic[T]):
|
|
|
117
117
|
raise TypeError
|
|
118
118
|
|
|
119
119
|
@classmethod
|
|
120
|
-
def __instancecheck__(cls, instance):
|
|
120
|
+
def __instancecheck__(cls, instance: object) -> bool:
|
|
121
121
|
return callable(instance)
|
|
122
122
|
|
|
123
123
|
@classmethod
|
|
124
|
-
def __subclasscheck__(cls, subclass):
|
|
124
|
+
def __subclasscheck__(cls, subclass: type) -> bool:
|
|
125
125
|
if not hasattr(subclass, '__call__'):
|
|
126
126
|
return False
|
|
127
127
|
call = subclass.__call__
|
omlish/lang/clsdct.py
CHANGED
omlish/lang/cmp.py
CHANGED
|
@@ -18,7 +18,7 @@ class InfinityType:
|
|
|
18
18
|
def __le__(self, other: ta.Any) -> bool:
|
|
19
19
|
return False
|
|
20
20
|
|
|
21
|
-
def __eq__(self, other:
|
|
21
|
+
def __eq__(self, other: object) -> bool:
|
|
22
22
|
return isinstance(other, self.__class__)
|
|
23
23
|
|
|
24
24
|
def __gt__(self, other: ta.Any) -> bool:
|
|
@@ -47,7 +47,7 @@ class NegativeInfinityType:
|
|
|
47
47
|
def __le__(self, other: ta.Any) -> bool:
|
|
48
48
|
return True
|
|
49
49
|
|
|
50
|
-
def __eq__(self, other:
|
|
50
|
+
def __eq__(self, other: object) -> bool:
|
|
51
51
|
return isinstance(other, self.__class__)
|
|
52
52
|
|
|
53
53
|
def __gt__(self, other: ta.Any) -> bool:
|
omlish/lang/contextmanagers.py
CHANGED
|
@@ -19,8 +19,8 @@ class ContextManaged:
|
|
|
19
19
|
|
|
20
20
|
def __exit__(
|
|
21
21
|
self,
|
|
22
|
-
exc_type:
|
|
23
|
-
exc_val:
|
|
22
|
+
exc_type: type[BaseException] | None,
|
|
23
|
+
exc_val: BaseException | None,
|
|
24
24
|
exc_tb: types.TracebackType | None,
|
|
25
25
|
) -> bool | None:
|
|
26
26
|
return None
|
|
@@ -28,7 +28,7 @@ class ContextManaged:
|
|
|
28
28
|
|
|
29
29
|
class NopContextManaged(ContextManaged):
|
|
30
30
|
|
|
31
|
-
def __init_subclass__(cls, **kwargs):
|
|
31
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
32
32
|
raise TypeError
|
|
33
33
|
|
|
34
34
|
|
|
@@ -37,7 +37,7 @@ NOP_CONTEXT_MANAGED = NopContextManaged()
|
|
|
37
37
|
|
|
38
38
|
class NopContextManager:
|
|
39
39
|
|
|
40
|
-
def __init_subclass__(cls, **kwargs):
|
|
40
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
41
41
|
raise TypeError
|
|
42
42
|
|
|
43
43
|
def __call__(self, *args, **kwargs):
|
|
@@ -84,11 +84,11 @@ def disposing(obj: T, attr: str = 'dispose') -> ta.Iterator[T]:
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
@contextlib.contextmanager
|
|
87
|
-
def breakpoint_on_exception():
|
|
87
|
+
def breakpoint_on_exception(): # noqa
|
|
88
88
|
try:
|
|
89
89
|
yield
|
|
90
90
|
except Exception as e: # noqa
|
|
91
|
-
breakpoint()
|
|
91
|
+
breakpoint() # noqa
|
|
92
92
|
raise
|
|
93
93
|
|
|
94
94
|
|
|
@@ -102,7 +102,7 @@ def context_var_setting(var: contextvars.ContextVar[T], val: T) -> ta.Iterator[T
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
@contextlib.contextmanager
|
|
105
|
-
def attr_setting(obj, attr, val, *, default=None):
|
|
105
|
+
def attr_setting(obj, attr, val, *, default=None): # noqa
|
|
106
106
|
not_set = object()
|
|
107
107
|
orig = getattr(obj, attr, not_set)
|
|
108
108
|
try:
|
|
@@ -146,8 +146,8 @@ class ExitStacked:
|
|
|
146
146
|
|
|
147
147
|
def __exit__(
|
|
148
148
|
self,
|
|
149
|
-
exc_type:
|
|
150
|
-
exc_val:
|
|
149
|
+
exc_type: type[BaseException] | None,
|
|
150
|
+
exc_val: BaseException | None,
|
|
151
151
|
exc_tb: types.TracebackType | None,
|
|
152
152
|
) -> bool | None:
|
|
153
153
|
self._exit_stack.__exit__(exc_type, exc_val, exc_tb)
|
|
@@ -212,10 +212,8 @@ class ContextWrapped:
|
|
|
212
212
|
raise TypeError(cm)
|
|
213
213
|
ret = type(self)(fn, cm)
|
|
214
214
|
if self._name is not None:
|
|
215
|
-
|
|
215
|
+
with contextlib.suppress(TypeError):
|
|
216
216
|
instance.__dict__[self._name] = ret
|
|
217
|
-
except TypeError:
|
|
218
|
-
pass
|
|
219
217
|
return ret
|
|
220
218
|
|
|
221
219
|
def __call__(self, *args, **kwargs):
|
|
@@ -228,7 +226,7 @@ class ContextWrapped:
|
|
|
228
226
|
return self._fn[0](*args, **kwargs)
|
|
229
227
|
|
|
230
228
|
|
|
231
|
-
def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], CallableT]:
|
|
229
|
+
def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], CallableT]: # noqa
|
|
232
230
|
def inner(fn):
|
|
233
231
|
return ContextWrapped(fn, cm)
|
|
234
232
|
return inner
|
|
@@ -238,7 +236,7 @@ def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], Callabl
|
|
|
238
236
|
|
|
239
237
|
|
|
240
238
|
Lockable = ta.Callable[[], ta.ContextManager]
|
|
241
|
-
DefaultLockable =
|
|
239
|
+
DefaultLockable = bool | Lockable | ta.ContextManager | None
|
|
242
240
|
|
|
243
241
|
|
|
244
242
|
def default_lock(value: DefaultLockable, default: DefaultLockable) -> Lockable:
|
omlish/lang/descriptors.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import functools
|
|
2
|
+
import operator
|
|
2
3
|
import typing as ta
|
|
3
4
|
|
|
4
5
|
|
|
@@ -8,6 +9,17 @@ T = ta.TypeVar('T')
|
|
|
8
9
|
##
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
def attr_property(n: str):
|
|
13
|
+
return property(operator.attrgetter(n))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def item_property(n: str):
|
|
17
|
+
return property(operator.itemgetter(n))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
|
|
22
|
+
|
|
11
23
|
BUILTIN_METHOD_DESCRIPTORS = (classmethod, staticmethod)
|
|
12
24
|
|
|
13
25
|
|
|
@@ -28,7 +40,7 @@ def unwrap_method_descriptors(fn: ta.Callable) -> ta.Callable:
|
|
|
28
40
|
##
|
|
29
41
|
|
|
30
42
|
|
|
31
|
-
class
|
|
43
|
+
class AccessForbiddenError(Exception):
|
|
32
44
|
|
|
33
45
|
def __init__(self, name: str | None = None, *args: ta.Any, **kwargs: ta.Any) -> None:
|
|
34
46
|
super().__init__(*((name,) if name is not None else ()), *args, **kwargs) # noqa
|
|
@@ -42,17 +54,17 @@ class AccessForbiddenDescriptor:
|
|
|
42
54
|
|
|
43
55
|
self._name = name
|
|
44
56
|
|
|
45
|
-
def __set_name__(self, owner:
|
|
57
|
+
def __set_name__(self, owner: type, name: str) -> None:
|
|
46
58
|
if self._name is None:
|
|
47
59
|
self._name = name
|
|
48
60
|
elif name != self._name:
|
|
49
61
|
raise NameError(name)
|
|
50
62
|
|
|
51
63
|
def __get__(self, instance, owner=None):
|
|
52
|
-
raise
|
|
64
|
+
raise AccessForbiddenError(self._name)
|
|
53
65
|
|
|
54
66
|
|
|
55
|
-
def access_forbidden():
|
|
67
|
+
def access_forbidden(): # noqa
|
|
56
68
|
return AccessForbiddenDescriptor()
|
|
57
69
|
|
|
58
70
|
|
omlish/lang/exceptions.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class Unreachable(Exception):
|
|
1
|
+
class Unreachable(Exception): # noqa
|
|
2
2
|
pass
|
omlish/lang/functions.py
CHANGED
|
@@ -7,14 +7,21 @@ from .descriptors import is_method_descriptor
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
T = ta.TypeVar('T')
|
|
10
|
+
P = ta.ParamSpec('P')
|
|
10
11
|
CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
##
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
def is_lambda(f: ta.Any) -> bool:
|
|
14
18
|
l = lambda: 0
|
|
15
19
|
return isinstance(f, type(l)) and f.__name__ == l.__name__
|
|
16
20
|
|
|
17
21
|
|
|
22
|
+
##
|
|
23
|
+
|
|
24
|
+
|
|
18
25
|
def maybe_call(obj: ta.Any, att: str, *args, default: ta.Any = None, **kwargs) -> ta.Any:
|
|
19
26
|
try:
|
|
20
27
|
fn = getattr(obj, att)
|
|
@@ -24,6 +31,16 @@ def maybe_call(obj: ta.Any, att: str, *args, default: ta.Any = None, **kwargs) -
|
|
|
24
31
|
return fn(*args, **kwargs)
|
|
25
32
|
|
|
26
33
|
|
|
34
|
+
def recurse(fn: ta.Callable[..., T], *args, **kwargs) -> T:
|
|
35
|
+
def rec(*args, **kwargs) -> T:
|
|
36
|
+
return fn(rec, *args, **kwargs)
|
|
37
|
+
|
|
38
|
+
return rec(*args, **kwargs)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
|
|
43
|
+
|
|
27
44
|
def unwrap_func(fn: ta.Callable) -> ta.Callable:
|
|
28
45
|
fn, _ = unwrap_func_with_partials(fn)
|
|
29
46
|
return fn
|
|
@@ -41,38 +58,51 @@ def unwrap_func_with_partials(fn: ta.Callable) -> tuple[ta.Callable, list[functo
|
|
|
41
58
|
nxt = getattr(fn, '__wrapped__', None)
|
|
42
59
|
if not callable(nxt):
|
|
43
60
|
break
|
|
44
|
-
|
|
61
|
+
if nxt is fn:
|
|
45
62
|
raise TypeError(fn)
|
|
46
63
|
fn = nxt
|
|
47
64
|
return fn, ps
|
|
48
65
|
|
|
49
66
|
|
|
67
|
+
##
|
|
68
|
+
|
|
69
|
+
|
|
50
70
|
def raise_(o: BaseException) -> ta.NoReturn:
|
|
51
71
|
raise o
|
|
52
72
|
|
|
53
73
|
|
|
74
|
+
def raising(o: BaseException) -> ta.Callable[..., ta.NoReturn]:
|
|
75
|
+
def inner(*args, **kwargs):
|
|
76
|
+
raise o
|
|
77
|
+
return inner
|
|
78
|
+
|
|
79
|
+
|
|
54
80
|
def try_(
|
|
81
|
+
fn: ta.Callable[P, T],
|
|
55
82
|
exc: type[Exception] | ta.Iterable[type[Exception]] = Exception,
|
|
56
83
|
default: T | None = None,
|
|
57
|
-
) -> ta.Callable[
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return default
|
|
64
|
-
|
|
65
|
-
return inner
|
|
84
|
+
) -> ta.Callable[P, T]:
|
|
85
|
+
def inner(*args, **kwargs):
|
|
86
|
+
try:
|
|
87
|
+
return fn(*args, **kwargs)
|
|
88
|
+
except exct:
|
|
89
|
+
return default
|
|
66
90
|
|
|
67
91
|
exct = (exc,) if isinstance(exc, type) else tuple(exc)
|
|
68
|
-
return
|
|
92
|
+
return inner
|
|
69
93
|
|
|
70
94
|
|
|
71
|
-
def
|
|
72
|
-
def
|
|
73
|
-
|
|
95
|
+
def finally_(fn: ta.Callable[P, T], fin: ta.Callable) -> ta.Callable[P, T]:
|
|
96
|
+
def inner(*args, **kwargs):
|
|
97
|
+
try:
|
|
98
|
+
return fn(*args, **kwargs)
|
|
99
|
+
finally:
|
|
100
|
+
fin()
|
|
101
|
+
|
|
102
|
+
return inner
|
|
74
103
|
|
|
75
|
-
|
|
104
|
+
|
|
105
|
+
##
|
|
76
106
|
|
|
77
107
|
|
|
78
108
|
def identity(obj: T) -> T:
|
|
@@ -98,21 +128,24 @@ def is_not_none(o: ta.Any) -> bool:
|
|
|
98
128
|
return o is not None
|
|
99
129
|
|
|
100
130
|
|
|
101
|
-
class
|
|
131
|
+
class VoidError(Exception):
|
|
102
132
|
pass
|
|
103
133
|
|
|
104
134
|
|
|
105
135
|
class Void:
|
|
106
136
|
|
|
107
|
-
def __new__(cls, *args, **kwargs):
|
|
108
|
-
raise
|
|
137
|
+
def __new__(cls, *args: ta.Any, **kwargs: ta.Any) -> None: # type: ignore # noqa
|
|
138
|
+
raise VoidError
|
|
139
|
+
|
|
140
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
|
141
|
+
raise VoidError
|
|
109
142
|
|
|
110
|
-
def __init_subclass__(cls, **kwargs):
|
|
111
|
-
raise VoidException
|
|
112
143
|
|
|
144
|
+
def void(*args: ta.Any, **kwargs: ta.Any) -> ta.NoReturn:
|
|
145
|
+
raise VoidError
|
|
113
146
|
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
|
|
148
|
+
##
|
|
116
149
|
|
|
117
150
|
|
|
118
151
|
_MISSING = object()
|
|
@@ -142,6 +175,9 @@ def periodically(
|
|
|
142
175
|
return inner # type: ignore
|
|
143
176
|
|
|
144
177
|
|
|
178
|
+
##
|
|
179
|
+
|
|
180
|
+
|
|
145
181
|
@dc.dataclass(init=False)
|
|
146
182
|
class Args:
|
|
147
183
|
args: ta.Sequence[ta.Any]
|
omlish/lang/imports.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
import functools
|
|
2
|
-
import importlib
|
|
3
|
+
import importlib.resources
|
|
3
4
|
import sys
|
|
4
5
|
import types
|
|
5
6
|
import typing as ta
|
|
@@ -17,7 +18,7 @@ def lazy_import(name: str, package: str | None = None) -> ta.Callable[[], ta.Any
|
|
|
17
18
|
def proxy_import(name: str, package: str | None = None) -> types.ModuleType:
|
|
18
19
|
omod = None
|
|
19
20
|
|
|
20
|
-
def __getattr__(att):
|
|
21
|
+
def __getattr__(att): # noqa
|
|
21
22
|
nonlocal omod
|
|
22
23
|
if omod is None:
|
|
23
24
|
omod = importlib.import_module(name, package=package)
|
|
@@ -31,9 +32,6 @@ def proxy_import(name: str, package: str | None = None) -> types.ModuleType:
|
|
|
31
32
|
##
|
|
32
33
|
|
|
33
34
|
|
|
34
|
-
_pkg_resources = lazy_import('pkg_resources')
|
|
35
|
-
|
|
36
|
-
|
|
37
35
|
def import_module(dotted_path: str) -> types.ModuleType:
|
|
38
36
|
if not dotted_path:
|
|
39
37
|
raise ImportError(dotted_path)
|
|
@@ -42,7 +40,7 @@ def import_module(dotted_path: str) -> types.ModuleType:
|
|
|
42
40
|
try:
|
|
43
41
|
mod = getattr(mod, name)
|
|
44
42
|
except AttributeError:
|
|
45
|
-
raise AttributeError('Module
|
|
43
|
+
raise AttributeError(f'Module {mod!r} has no attribute {name!r}') from None
|
|
46
44
|
return mod
|
|
47
45
|
|
|
48
46
|
|
|
@@ -52,7 +50,7 @@ def import_module_attr(dotted_path: str) -> ta.Any:
|
|
|
52
50
|
try:
|
|
53
51
|
return getattr(mod, class_name)
|
|
54
52
|
except AttributeError:
|
|
55
|
-
raise AttributeError('Module
|
|
53
|
+
raise AttributeError(f'Module {module_name!r} has no attr {class_name!r}') from None
|
|
56
54
|
|
|
57
55
|
|
|
58
56
|
SPECIAL_IMPORTABLE: ta.AbstractSet[str] = frozenset([
|
|
@@ -65,46 +63,43 @@ def yield_importable(
|
|
|
65
63
|
package_root: str,
|
|
66
64
|
*,
|
|
67
65
|
recursive: bool = False,
|
|
68
|
-
filter: ta.Callable[[str], bool] | None = None,
|
|
66
|
+
filter: ta.Callable[[str], bool] | None = None, # noqa
|
|
69
67
|
include_special: bool = False,
|
|
70
68
|
) -> ta.Iterator[str]:
|
|
71
|
-
def rec(
|
|
72
|
-
if
|
|
69
|
+
def rec(cur):
|
|
70
|
+
if cur.split('.')[-1] == '__pycache__':
|
|
73
71
|
return
|
|
74
72
|
|
|
75
73
|
try:
|
|
76
|
-
module = sys.modules[
|
|
74
|
+
module = sys.modules[cur]
|
|
77
75
|
except KeyError:
|
|
78
76
|
try:
|
|
79
|
-
__import__(
|
|
77
|
+
__import__(cur)
|
|
80
78
|
except ImportError:
|
|
81
79
|
return
|
|
82
|
-
module = sys.modules[
|
|
80
|
+
module = sys.modules[cur]
|
|
83
81
|
|
|
84
82
|
# FIXME: pyox
|
|
85
83
|
if getattr(module, '__file__', None) is None:
|
|
86
84
|
return
|
|
87
85
|
|
|
88
|
-
for file in
|
|
89
|
-
if file.endswith('.py'):
|
|
90
|
-
if not (include_special or file not in SPECIAL_IMPORTABLE):
|
|
86
|
+
for file in importlib.resources.files(cur).iterdir():
|
|
87
|
+
if file.is_file() and file.name.endswith('.py'):
|
|
88
|
+
if not (include_special or file.name not in SPECIAL_IMPORTABLE):
|
|
91
89
|
continue
|
|
92
90
|
|
|
93
|
-
name =
|
|
91
|
+
name = cur + '.' + file.name[:-3]
|
|
94
92
|
if filter is not None and not filter(name):
|
|
95
93
|
continue
|
|
96
94
|
|
|
97
95
|
yield name
|
|
98
96
|
|
|
99
|
-
elif recursive and
|
|
100
|
-
name =
|
|
97
|
+
elif recursive and file.is_dir():
|
|
98
|
+
name = cur + '.' + file.name
|
|
101
99
|
if filter is not None and not filter(name):
|
|
102
100
|
continue
|
|
103
|
-
|
|
104
|
-
try:
|
|
101
|
+
with contextlib.suppress(ImportError, NotImplementedError):
|
|
105
102
|
yield from rec(name)
|
|
106
|
-
except (ImportError, NotImplementedError):
|
|
107
|
-
pass
|
|
108
103
|
|
|
109
104
|
yield from rec(package_root)
|
|
110
105
|
|
|
@@ -112,10 +107,10 @@ def yield_importable(
|
|
|
112
107
|
def yield_import_all(
|
|
113
108
|
package_root: str,
|
|
114
109
|
*,
|
|
115
|
-
globals: dict[str, ta.Any] | None = None,
|
|
116
|
-
locals: dict[str, ta.Any] | None = None,
|
|
110
|
+
globals: dict[str, ta.Any] | None = None, # noqa
|
|
111
|
+
locals: dict[str, ta.Any] | None = None, # noqa
|
|
117
112
|
recursive: bool = False,
|
|
118
|
-
filter: ta.Callable[[str], bool] | None = None,
|
|
113
|
+
filter: ta.Callable[[str], bool] | None = None, # noqa
|
|
119
114
|
include_special: bool = False,
|
|
120
115
|
) -> ta.Iterator[str]:
|
|
121
116
|
for import_path in yield_importable(
|
|
@@ -132,7 +127,7 @@ def import_all(
|
|
|
132
127
|
package_root: str,
|
|
133
128
|
*,
|
|
134
129
|
recursive: bool = False,
|
|
135
|
-
filter: ta.Callable[[str], bool] | None = None,
|
|
130
|
+
filter: ta.Callable[[str], bool] | None = None, # noqa
|
|
136
131
|
include_special: bool = False,
|
|
137
132
|
) -> None:
|
|
138
133
|
for _ in yield_import_all(
|
omlish/lang/iterables.py
CHANGED
|
@@ -28,13 +28,13 @@ def exhaust(it: ta.Iterable[ta.Any]) -> None:
|
|
|
28
28
|
pass
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def peek(vs: ta.Iterable[T]) ->
|
|
31
|
+
def peek(vs: ta.Iterable[T]) -> tuple[T, ta.Iterator[T]]:
|
|
32
32
|
it = iter(vs)
|
|
33
33
|
v = next(it)
|
|
34
34
|
return v, itertools.chain(iter((v,)), it)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
Rangeable: ta.TypeAlias = int |
|
|
37
|
+
Rangeable: ta.TypeAlias = int | tuple[int] | tuple[int, int] | ta.Iterable[int]
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def asrange(i: Rangeable) -> ta.Iterable[int]:
|