omlish 0.0.0.dev212__py3-none-any.whl → 0.0.0.dev213__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/__about__.py +2 -2
- omlish/asyncs/ioproxy/__init__.py +1 -0
- omlish/asyncs/ioproxy/io.py +242 -0
- omlish/asyncs/ioproxy/proxier.py +154 -0
- omlish/asyncs/ioproxy/proxy.py +141 -0
- omlish/asyncs/ioproxy/typing.py +108 -0
- omlish/check.py +1 -0
- omlish/configs/processing/matching.py +9 -1
- omlish/io/abc.py +1 -0
- omlish/lite/check.py +23 -0
- omlish/lite/contextmanagers.py +39 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev213.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev213.dist-info}/RECORD +17 -12
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev213.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev213.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev213.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev213.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
# @omlish-lite
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import io
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
from .proxy import AsyncIoProxy
|
6
|
+
from .proxy import _register_async_io_proxy_cls
|
7
|
+
|
8
|
+
|
9
|
+
SelfT = ta.TypeVar('SelfT')
|
10
|
+
|
11
|
+
|
12
|
+
##
|
13
|
+
|
14
|
+
|
15
|
+
@_register_async_io_proxy_cls
|
16
|
+
class IOBaseAsyncIoProxy(AsyncIoProxy, proxied_cls=io.IOBase):
|
17
|
+
# https://github.com/python/cpython/blob/e65a1eb93ae35f9fbab1508606e3fbc89123629f/Lib/_pyio.py#L305
|
18
|
+
|
19
|
+
##
|
20
|
+
# Positioning
|
21
|
+
|
22
|
+
async def seek(self, pos, whence=0):
|
23
|
+
raise TypeError
|
24
|
+
|
25
|
+
async def tell(self):
|
26
|
+
raise TypeError
|
27
|
+
|
28
|
+
async def truncate(self, pos=None):
|
29
|
+
raise TypeError
|
30
|
+
|
31
|
+
##
|
32
|
+
# Flush and close
|
33
|
+
|
34
|
+
async def flush(self):
|
35
|
+
raise TypeError
|
36
|
+
|
37
|
+
async def close(self):
|
38
|
+
raise TypeError
|
39
|
+
|
40
|
+
##
|
41
|
+
# Inquiries
|
42
|
+
|
43
|
+
def seekable(self):
|
44
|
+
raise TypeError
|
45
|
+
|
46
|
+
def readable(self):
|
47
|
+
raise TypeError
|
48
|
+
|
49
|
+
def writable(self):
|
50
|
+
raise TypeError
|
51
|
+
|
52
|
+
@property
|
53
|
+
def closed(self):
|
54
|
+
raise TypeError
|
55
|
+
|
56
|
+
##
|
57
|
+
# Context manager
|
58
|
+
|
59
|
+
async def __aenter__(self: SelfT) -> SelfT:
|
60
|
+
raise TypeError
|
61
|
+
|
62
|
+
async def __aexit__(self, exc_type, exc_value, exc_tb):
|
63
|
+
raise TypeError
|
64
|
+
|
65
|
+
##
|
66
|
+
# Lower-level APIs
|
67
|
+
|
68
|
+
def fileno(self):
|
69
|
+
raise TypeError
|
70
|
+
|
71
|
+
def isatty(self):
|
72
|
+
raise TypeError
|
73
|
+
|
74
|
+
##
|
75
|
+
# Readline[s] and writelines
|
76
|
+
|
77
|
+
async def readline(self, size=-1):
|
78
|
+
raise TypeError
|
79
|
+
|
80
|
+
# def __iter__(self):
|
81
|
+
# raise TypeError
|
82
|
+
|
83
|
+
# def __next__(self):
|
84
|
+
# raise TypeError
|
85
|
+
|
86
|
+
async def readlines(self, hint=None):
|
87
|
+
raise TypeError
|
88
|
+
|
89
|
+
async def writelines(self, lines):
|
90
|
+
raise TypeError
|
91
|
+
|
92
|
+
|
93
|
+
@_register_async_io_proxy_cls
|
94
|
+
class RawIOBaseAsyncIoProxy(IOBaseAsyncIoProxy, proxied_cls=io.RawIOBase):
|
95
|
+
async def read(self, size=-1):
|
96
|
+
raise TypeError
|
97
|
+
|
98
|
+
async def readall(self):
|
99
|
+
raise TypeError
|
100
|
+
|
101
|
+
async def readinto(self, b):
|
102
|
+
raise TypeError
|
103
|
+
|
104
|
+
async def write(self, b):
|
105
|
+
raise TypeError
|
106
|
+
|
107
|
+
|
108
|
+
@_register_async_io_proxy_cls
|
109
|
+
class BufferedIOBaseAsyncIoProxy(IOBaseAsyncIoProxy, proxied_cls=io.BufferedIOBase):
|
110
|
+
async def read(self, size=-1):
|
111
|
+
raise TypeError
|
112
|
+
|
113
|
+
async def read1(self, size=-1):
|
114
|
+
raise TypeError
|
115
|
+
|
116
|
+
async def readinto(self, b):
|
117
|
+
raise TypeError
|
118
|
+
|
119
|
+
async def readinto1(self, b):
|
120
|
+
raise TypeError
|
121
|
+
|
122
|
+
async def write(self, b):
|
123
|
+
raise TypeError
|
124
|
+
|
125
|
+
async def detach(self):
|
126
|
+
raise TypeError
|
127
|
+
|
128
|
+
|
129
|
+
class BufferedIOMixinAsyncIoProxy(BufferedIOBaseAsyncIoProxy):
|
130
|
+
@property
|
131
|
+
def raw(self):
|
132
|
+
raise TypeError
|
133
|
+
|
134
|
+
@property
|
135
|
+
def name(self):
|
136
|
+
raise TypeError
|
137
|
+
|
138
|
+
@property
|
139
|
+
def mode(self):
|
140
|
+
raise TypeError
|
141
|
+
|
142
|
+
|
143
|
+
@_register_async_io_proxy_cls
|
144
|
+
class BytesIOAsyncIoProxy(BufferedIOBaseAsyncIoProxy, proxied_cls=io.BytesIO):
|
145
|
+
async def getvalue(self):
|
146
|
+
raise TypeError
|
147
|
+
|
148
|
+
async def getbuffer(self):
|
149
|
+
raise TypeError
|
150
|
+
|
151
|
+
|
152
|
+
@_register_async_io_proxy_cls
|
153
|
+
class BufferedReaderAsyncIoProxy(BufferedIOMixinAsyncIoProxy, proxied_cls=io.BufferedReader):
|
154
|
+
async def peek(self, size=0):
|
155
|
+
raise TypeError
|
156
|
+
|
157
|
+
|
158
|
+
@_register_async_io_proxy_cls
|
159
|
+
class BufferedWriterAsyncIoProxy(BufferedIOMixinAsyncIoProxy, proxied_cls=io.BufferedWriter):
|
160
|
+
pass
|
161
|
+
|
162
|
+
|
163
|
+
@_register_async_io_proxy_cls
|
164
|
+
class BufferedRWPairAsyncIoProxy(BufferedIOBaseAsyncIoProxy, proxied_cls=io.BufferedRWPair):
|
165
|
+
async def peek(self, size=0):
|
166
|
+
raise TypeError
|
167
|
+
|
168
|
+
|
169
|
+
@_register_async_io_proxy_cls
|
170
|
+
class BufferedRandomAsyncIoProxy(BufferedWriterAsyncIoProxy, BufferedReaderAsyncIoProxy, proxied_cls=io.BufferedRandom):
|
171
|
+
pass
|
172
|
+
|
173
|
+
|
174
|
+
@_register_async_io_proxy_cls
|
175
|
+
class FileIOAsyncIoProxy(RawIOBaseAsyncIoProxy, proxied_cls=io.FileIO):
|
176
|
+
@property
|
177
|
+
def closefd(self):
|
178
|
+
raise TypeError
|
179
|
+
|
180
|
+
@property
|
181
|
+
def mode(self):
|
182
|
+
raise TypeError
|
183
|
+
|
184
|
+
|
185
|
+
@_register_async_io_proxy_cls
|
186
|
+
class TextIOBaseAsyncIoProxy(IOBaseAsyncIoProxy, proxied_cls=io.TextIOBase):
|
187
|
+
async def read(self, size=-1):
|
188
|
+
raise TypeError
|
189
|
+
|
190
|
+
async def write(self, s):
|
191
|
+
raise TypeError
|
192
|
+
|
193
|
+
async def detach(self):
|
194
|
+
raise TypeError
|
195
|
+
|
196
|
+
@property
|
197
|
+
def encoding(self):
|
198
|
+
raise TypeError
|
199
|
+
|
200
|
+
@property
|
201
|
+
def newlines(self):
|
202
|
+
raise TypeError
|
203
|
+
|
204
|
+
@property
|
205
|
+
def errors(self):
|
206
|
+
raise TypeError
|
207
|
+
|
208
|
+
|
209
|
+
@_register_async_io_proxy_cls
|
210
|
+
class TextIOWrapperAsyncIoProxy(TextIOBaseAsyncIoProxy, proxied_cls=io.TextIOWrapper):
|
211
|
+
@property
|
212
|
+
def line_buffering(self):
|
213
|
+
raise TypeError
|
214
|
+
|
215
|
+
@property
|
216
|
+
def write_through(self):
|
217
|
+
raise TypeError
|
218
|
+
|
219
|
+
@property
|
220
|
+
def buffer(self):
|
221
|
+
raise TypeError
|
222
|
+
|
223
|
+
async def reconfigure(
|
224
|
+
self,
|
225
|
+
*,
|
226
|
+
encoding=None,
|
227
|
+
errors=None,
|
228
|
+
newline=Ellipsis,
|
229
|
+
line_buffering=None,
|
230
|
+
write_through=None,
|
231
|
+
):
|
232
|
+
raise TypeError
|
233
|
+
|
234
|
+
@property
|
235
|
+
def name(self):
|
236
|
+
raise TypeError
|
237
|
+
|
238
|
+
|
239
|
+
@_register_async_io_proxy_cls
|
240
|
+
class StringIOAsyncIoProxy(TextIOWrapperAsyncIoProxy, proxied_cls=io.StringIO):
|
241
|
+
async def getvalue(self):
|
242
|
+
raise TypeError
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import io
|
3
|
+
import types
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from .io import BufferedIOBaseAsyncIoProxy
|
7
|
+
from .io import BufferedRandomAsyncIoProxy
|
8
|
+
from .io import BufferedReaderAsyncIoProxy
|
9
|
+
from .io import BufferedRWPairAsyncIoProxy
|
10
|
+
from .io import BufferedWriterAsyncIoProxy
|
11
|
+
from .io import BytesIOAsyncIoProxy
|
12
|
+
from .io import FileIOAsyncIoProxy
|
13
|
+
from .io import IOBaseAsyncIoProxy
|
14
|
+
from .io import RawIOBaseAsyncIoProxy
|
15
|
+
from .io import StringIOAsyncIoProxy
|
16
|
+
from .io import TextIOBaseAsyncIoProxy
|
17
|
+
from .io import TextIOWrapperAsyncIoProxy
|
18
|
+
from .proxy import AsyncIoProxyRunner
|
19
|
+
from .proxy import AsyncIoProxyTarget
|
20
|
+
from .proxy import async_io_proxy_cls_for
|
21
|
+
from .proxy import async_io_proxy_fn
|
22
|
+
from .typing import TypingBinaryIOAsyncIoProxy
|
23
|
+
from .typing import TypingIOAsyncIoProxy
|
24
|
+
from .typing import TypingTextIOAsyncIoProxy
|
25
|
+
|
26
|
+
|
27
|
+
##
|
28
|
+
|
29
|
+
|
30
|
+
@ta.final
|
31
|
+
class AsyncIoProxier:
|
32
|
+
def __init__(self, runner_policy: ta.Callable[[ta.Any], AsyncIoProxyRunner]) -> None:
|
33
|
+
super().__init__()
|
34
|
+
|
35
|
+
self._runner_policy = runner_policy
|
36
|
+
|
37
|
+
def get_runner(self, obj: ta.Any) -> AsyncIoProxyRunner:
|
38
|
+
return self._runner_policy(obj)
|
39
|
+
|
40
|
+
##
|
41
|
+
|
42
|
+
def target_obj(self, obj: ta.Any) -> AsyncIoProxyTarget:
|
43
|
+
runner = self.get_runner(obj)
|
44
|
+
return AsyncIoProxyTarget(obj, runner)
|
45
|
+
|
46
|
+
def proxy_obj_with_cls(self, obj, proxy_cls):
|
47
|
+
target = self.target_obj(obj)
|
48
|
+
proxy = proxy_cls(target)
|
49
|
+
return proxy
|
50
|
+
|
51
|
+
def maybe_proxy_obj(self, obj):
|
52
|
+
if (proxy_cls := async_io_proxy_cls_for(obj)) is None:
|
53
|
+
return obj
|
54
|
+
return self.proxy_obj_with_cls(obj, proxy_cls)
|
55
|
+
|
56
|
+
##
|
57
|
+
|
58
|
+
@ta.overload
|
59
|
+
def proxy_obj(self, obj: io.StringIO) -> StringIOAsyncIoProxy: # type: ignore[overload-overlap] # 1
|
60
|
+
...
|
61
|
+
|
62
|
+
@ta.overload
|
63
|
+
def proxy_obj(self, obj: io.TextIOWrapper) -> TextIOWrapperAsyncIoProxy: # type: ignore[overload-overlap] # 2
|
64
|
+
...
|
65
|
+
|
66
|
+
@ta.overload
|
67
|
+
def proxy_obj(self, obj: io.TextIOBase) -> TextIOBaseAsyncIoProxy: # 3
|
68
|
+
...
|
69
|
+
|
70
|
+
@ta.overload
|
71
|
+
def proxy_obj(self, obj: io.FileIO) -> FileIOAsyncIoProxy: # type: ignore[overload-overlap] # 4
|
72
|
+
...
|
73
|
+
|
74
|
+
@ta.overload
|
75
|
+
def proxy_obj(self, obj: io.BufferedRandom) -> BufferedRandomAsyncIoProxy: # type: ignore[overload-overlap] # 5
|
76
|
+
...
|
77
|
+
|
78
|
+
@ta.overload
|
79
|
+
def proxy_obj(self, obj: io.BufferedRWPair) -> BufferedRWPairAsyncIoProxy: # 6
|
80
|
+
...
|
81
|
+
|
82
|
+
@ta.overload
|
83
|
+
def proxy_obj(self, obj: io.BufferedWriter) -> BufferedWriterAsyncIoProxy: # type: ignore[overload-overlap] # 7
|
84
|
+
...
|
85
|
+
|
86
|
+
@ta.overload
|
87
|
+
def proxy_obj(self, obj: io.BufferedReader) -> BufferedReaderAsyncIoProxy: # type: ignore[overload-overlap] # 8
|
88
|
+
...
|
89
|
+
|
90
|
+
@ta.overload
|
91
|
+
def proxy_obj(self, obj: io.BytesIO) -> BytesIOAsyncIoProxy: # type: ignore[overload-overlap] # 9
|
92
|
+
...
|
93
|
+
|
94
|
+
@ta.overload
|
95
|
+
def proxy_obj(self, obj: io.BufferedIOBase) -> BufferedIOBaseAsyncIoProxy: # 10
|
96
|
+
...
|
97
|
+
|
98
|
+
@ta.overload
|
99
|
+
def proxy_obj(self, obj: io.RawIOBase) -> RawIOBaseAsyncIoProxy: # 11
|
100
|
+
...
|
101
|
+
|
102
|
+
@ta.overload
|
103
|
+
def proxy_obj(self, obj: io.IOBase) -> IOBaseAsyncIoProxy: # 12
|
104
|
+
...
|
105
|
+
|
106
|
+
#
|
107
|
+
|
108
|
+
@ta.overload
|
109
|
+
def proxy_obj(self, obj: ta.TextIO) -> TypingTextIOAsyncIoProxy: # 13
|
110
|
+
...
|
111
|
+
|
112
|
+
@ta.overload
|
113
|
+
def proxy_obj(self, obj: ta.BinaryIO) -> TypingBinaryIOAsyncIoProxy: # 14
|
114
|
+
...
|
115
|
+
|
116
|
+
@ta.overload
|
117
|
+
def proxy_obj(self, obj: ta.IO) -> TypingIOAsyncIoProxy: # 15
|
118
|
+
...
|
119
|
+
|
120
|
+
#
|
121
|
+
|
122
|
+
def proxy_obj(self, obj):
|
123
|
+
if (proxy_cls := async_io_proxy_cls_for(obj)) is None:
|
124
|
+
raise TypeError(obj)
|
125
|
+
return self.proxy_obj_with_cls(obj, proxy_cls)
|
126
|
+
|
127
|
+
##
|
128
|
+
|
129
|
+
def proxy_fn(self, fn, *, wrap_result='auto'):
|
130
|
+
if wrap_result == 'auto':
|
131
|
+
result_wrapper = self.maybe_proxy_obj
|
132
|
+
elif wrap_result is True:
|
133
|
+
result_wrapper = self.proxy_obj
|
134
|
+
elif wrap_result is False:
|
135
|
+
result_wrapper = None
|
136
|
+
else:
|
137
|
+
raise TypeError(wrap_result)
|
138
|
+
runner = self.get_runner(fn)
|
139
|
+
return async_io_proxy_fn(fn, runner, result_wrapper=result_wrapper)
|
140
|
+
|
141
|
+
##
|
142
|
+
|
143
|
+
FN_TYPES: ta.Tuple[type, ...] = (
|
144
|
+
types.BuiltinFunctionType,
|
145
|
+
types.BuiltinMethodType,
|
146
|
+
types.FunctionType,
|
147
|
+
types.MethodType,
|
148
|
+
)
|
149
|
+
|
150
|
+
def proxy(self, obj):
|
151
|
+
if isinstance(obj, self.FN_TYPES):
|
152
|
+
return self.proxy_fn(obj)
|
153
|
+
else:
|
154
|
+
return self.proxy_obj(obj)
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import dataclasses as dc
|
3
|
+
import functools
|
4
|
+
import inspect
|
5
|
+
import typing as ta
|
6
|
+
|
7
|
+
from ...lite.check import check
|
8
|
+
|
9
|
+
|
10
|
+
AsyncIoProxyRunner = ta.Callable[[ta.Callable], ta.Awaitable] # ta.TypeAlias
|
11
|
+
|
12
|
+
|
13
|
+
##
|
14
|
+
|
15
|
+
|
16
|
+
_ASYNC_IO_PROXY_WRAPPER_NAME_ATTRS = ('__name__', '__qualname__')
|
17
|
+
_ASYNC_IO_PROXY_WRAPPER_ASSIGNMENTS = tuple(
|
18
|
+
a
|
19
|
+
for a in functools.WRAPPER_ASSIGNMENTS
|
20
|
+
if a not in _ASYNC_IO_PROXY_WRAPPER_NAME_ATTRS
|
21
|
+
)
|
22
|
+
|
23
|
+
|
24
|
+
def async_io_proxy_fn(fn, runner, *, result_wrapper=None):
|
25
|
+
@functools.wraps(fn, assigned=_ASYNC_IO_PROXY_WRAPPER_ASSIGNMENTS)
|
26
|
+
async def run(*args, **kwargs):
|
27
|
+
ret = await runner(functools.partial(fn, *args, **kwargs))
|
28
|
+
if result_wrapper is not None:
|
29
|
+
ret = result_wrapper(ret)
|
30
|
+
return ret
|
31
|
+
|
32
|
+
for na in _ASYNC_IO_PROXY_WRAPPER_NAME_ATTRS:
|
33
|
+
setattr(run, na, f'{getattr(run, na)}:{getattr(fn, na)}')
|
34
|
+
|
35
|
+
return run
|
36
|
+
|
37
|
+
|
38
|
+
##
|
39
|
+
|
40
|
+
|
41
|
+
@dc.dataclass(frozen=True)
|
42
|
+
class AsyncIoProxyTarget:
|
43
|
+
obj: ta.Any
|
44
|
+
runner: AsyncIoProxyRunner
|
45
|
+
|
46
|
+
|
47
|
+
class AsyncIoProxy:
|
48
|
+
def __init__(self, target: AsyncIoProxyTarget) -> None:
|
49
|
+
super().__init__()
|
50
|
+
|
51
|
+
self._target = check.isinstance(target, AsyncIoProxyTarget)
|
52
|
+
|
53
|
+
#
|
54
|
+
|
55
|
+
class _Descriptor:
|
56
|
+
def __init__(self, name) -> None:
|
57
|
+
super().__init__()
|
58
|
+
|
59
|
+
self._name = name
|
60
|
+
|
61
|
+
def __get__(self, instance, owner=None):
|
62
|
+
if instance is None:
|
63
|
+
return self
|
64
|
+
|
65
|
+
target: AsyncIoProxyTarget = instance._target # noqa
|
66
|
+
v = self._get(target, instance)
|
67
|
+
|
68
|
+
setattr(instance, self._name, v)
|
69
|
+
return v
|
70
|
+
|
71
|
+
def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
|
72
|
+
raise NotImplementedError
|
73
|
+
|
74
|
+
class _Property(_Descriptor):
|
75
|
+
def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
|
76
|
+
return getattr(target.obj, self._name)
|
77
|
+
|
78
|
+
class _Method(_Descriptor):
|
79
|
+
def __call__(self, instance, *args, **kwargs):
|
80
|
+
return self.__get__(instance)(*args, **kwargs)
|
81
|
+
|
82
|
+
class _SyncMethod(_Method):
|
83
|
+
def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
|
84
|
+
return getattr(target.obj, self._name)
|
85
|
+
|
86
|
+
class _AsyncMethod(_Method):
|
87
|
+
SPECIAL_METHOD_NAMES: ta.ClassVar[ta.Mapping[str, str]] = {
|
88
|
+
'__aenter__': '__enter__',
|
89
|
+
'__aexit__': '__exit__',
|
90
|
+
}
|
91
|
+
|
92
|
+
def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
|
93
|
+
fa = self.SPECIAL_METHOD_NAMES.get(self._name, self._name)
|
94
|
+
fn = getattr(target.obj, fa)
|
95
|
+
if fa == '__enter__':
|
96
|
+
result_wrapper = lambda _: instance
|
97
|
+
else:
|
98
|
+
result_wrapper = None
|
99
|
+
run = async_io_proxy_fn(fn, target.runner, result_wrapper=result_wrapper)
|
100
|
+
return run
|
101
|
+
|
102
|
+
#
|
103
|
+
|
104
|
+
__proxied_cls__: ta.ClassVar[type]
|
105
|
+
|
106
|
+
def __init_subclass__(cls, *, proxied_cls=None, **kwargs): # noqa
|
107
|
+
super().__init_subclass__()
|
108
|
+
|
109
|
+
cls.__proxied_cls__ = check.isinstance(proxied_cls, (type, None))
|
110
|
+
|
111
|
+
for n, v in dict(cls.__dict__).items():
|
112
|
+
if n.startswith('_') and n not in cls._AsyncMethod.SPECIAL_METHOD_NAMES:
|
113
|
+
continue
|
114
|
+
|
115
|
+
if isinstance(v, property):
|
116
|
+
setattr(cls, n, cls._Property(n))
|
117
|
+
|
118
|
+
elif callable(v):
|
119
|
+
if inspect.iscoroutinefunction(v):
|
120
|
+
setattr(cls, n, cls._AsyncMethod(n))
|
121
|
+
else:
|
122
|
+
setattr(cls, n, cls._SyncMethod(n))
|
123
|
+
|
124
|
+
else:
|
125
|
+
raise TypeError(v)
|
126
|
+
|
127
|
+
|
128
|
+
##
|
129
|
+
|
130
|
+
|
131
|
+
@functools.singledispatch
|
132
|
+
def async_io_proxy_cls_for(obj: ta.Any) -> ta.Optional[ta.Type[AsyncIoProxy]]:
|
133
|
+
return None
|
134
|
+
|
135
|
+
|
136
|
+
def _register_async_io_proxy_cls(cls):
|
137
|
+
async_io_proxy_cls_for.register(
|
138
|
+
check.isinstance(cls.__dict__['__proxied_cls__'], type),
|
139
|
+
lambda obj: cls,
|
140
|
+
)
|
141
|
+
return cls
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from .proxy import AsyncIoProxy
|
5
|
+
from .proxy import _register_async_io_proxy_cls
|
6
|
+
|
7
|
+
|
8
|
+
SelfT = ta.TypeVar('SelfT')
|
9
|
+
|
10
|
+
AnyStrT = ta.TypeVar('AnyStrT', bytes, str)
|
11
|
+
|
12
|
+
|
13
|
+
##
|
14
|
+
|
15
|
+
|
16
|
+
@_register_async_io_proxy_cls
|
17
|
+
class TypingIOAsyncIoProxy(AsyncIoProxy, ta.Generic[AnyStrT], proxied_cls=ta.IO):
|
18
|
+
@property
|
19
|
+
def mode(self) -> str:
|
20
|
+
raise TypeError
|
21
|
+
|
22
|
+
@property
|
23
|
+
def name(self) -> str:
|
24
|
+
raise TypeError
|
25
|
+
|
26
|
+
async def close(self) -> None:
|
27
|
+
raise TypeError
|
28
|
+
|
29
|
+
@property
|
30
|
+
def closed(self) -> bool:
|
31
|
+
raise TypeError
|
32
|
+
|
33
|
+
def fileno(self) -> int:
|
34
|
+
raise TypeError
|
35
|
+
|
36
|
+
async def flush(self) -> None:
|
37
|
+
raise TypeError
|
38
|
+
|
39
|
+
def isatty(self) -> bool:
|
40
|
+
raise TypeError
|
41
|
+
|
42
|
+
async def read(self, n: int = -1) -> AnyStrT:
|
43
|
+
raise TypeError
|
44
|
+
|
45
|
+
def readable(self) -> bool:
|
46
|
+
raise TypeError
|
47
|
+
|
48
|
+
async def readline(self, limit: int = -1) -> AnyStrT:
|
49
|
+
raise TypeError
|
50
|
+
|
51
|
+
async def readlines(self, hint: int = -1) -> ta.List[AnyStrT]:
|
52
|
+
raise TypeError
|
53
|
+
|
54
|
+
async def seek(self, offset: int, whence: int = 0) -> int:
|
55
|
+
raise TypeError
|
56
|
+
|
57
|
+
def seekable(self) -> bool:
|
58
|
+
raise TypeError
|
59
|
+
|
60
|
+
async def tell(self) -> int:
|
61
|
+
raise TypeError
|
62
|
+
|
63
|
+
async def truncate(self, size: ta.Optional[int] = None) -> int:
|
64
|
+
raise TypeError
|
65
|
+
|
66
|
+
def writable(self) -> bool:
|
67
|
+
raise TypeError
|
68
|
+
|
69
|
+
async def write(self, s: AnyStrT) -> int:
|
70
|
+
raise TypeError
|
71
|
+
|
72
|
+
async def writelines(self, lines: ta.List[AnyStrT]) -> None:
|
73
|
+
raise TypeError
|
74
|
+
|
75
|
+
async def __aenter__(self: SelfT) -> SelfT:
|
76
|
+
raise TypeError
|
77
|
+
|
78
|
+
async def __aexit__(self, exc_type, exc_value, exc_tb):
|
79
|
+
raise TypeError
|
80
|
+
|
81
|
+
|
82
|
+
@_register_async_io_proxy_cls
|
83
|
+
class TypingBinaryIOAsyncIoProxy(TypingIOAsyncIoProxy[bytes], proxied_cls=ta.BinaryIO):
|
84
|
+
def write(self, s: ta.Union[bytes, bytearray]) -> int: # type: ignore[override]
|
85
|
+
raise TypeError
|
86
|
+
|
87
|
+
|
88
|
+
@_register_async_io_proxy_cls
|
89
|
+
class TypingTextIOAsyncIoProxy(TypingIOAsyncIoProxy[str], proxied_cls=ta.TextIO):
|
90
|
+
# @property
|
91
|
+
# def buffer(self) -> BinaryIO:
|
92
|
+
# pass
|
93
|
+
|
94
|
+
@property
|
95
|
+
def encoding(self) -> str:
|
96
|
+
raise TypeError
|
97
|
+
|
98
|
+
@property
|
99
|
+
def errors(self) -> ta.Optional[str]:
|
100
|
+
raise TypeError
|
101
|
+
|
102
|
+
@property
|
103
|
+
def line_buffering(self) -> bool:
|
104
|
+
raise TypeError
|
105
|
+
|
106
|
+
@property
|
107
|
+
def newlines(self) -> ta.Any:
|
108
|
+
raise TypeError
|
omlish/check.py
CHANGED
@@ -29,8 +29,16 @@ class MatchingConfigRewriter(ConfigRewriter):
|
|
29
29
|
self._paths = frozenset(check.isinstance(p, tuple) for p in paths)
|
30
30
|
self._recurse = recurse
|
31
31
|
|
32
|
+
def match_path(self, path: ConfigRewriterPath) -> bool:
|
33
|
+
for test in self._paths:
|
34
|
+
if len(test) != len(path):
|
35
|
+
continue
|
36
|
+
if all(t is None or p == t for p, t in zip(path, test)):
|
37
|
+
return True
|
38
|
+
return False
|
39
|
+
|
32
40
|
def rewrite(self, ctx: ConfigRewriter.Context[T]) -> T:
|
33
|
-
if ctx.path
|
41
|
+
if self.match_path(ctx.path):
|
34
42
|
no = self._fn(ctx.obj)
|
35
43
|
if not self._recurse:
|
36
44
|
return no
|
omlish/io/abc.py
CHANGED
omlish/lite/check.py
CHANGED
@@ -49,6 +49,17 @@ class Checks:
|
|
49
49
|
|
50
50
|
#
|
51
51
|
|
52
|
+
def register_on_raise_breakpoint_if_env_var_set(self, key: str) -> None:
|
53
|
+
import os
|
54
|
+
|
55
|
+
def on_raise(exc: Exception) -> None: # noqa
|
56
|
+
if key in os.environ:
|
57
|
+
breakpoint() # noqa
|
58
|
+
|
59
|
+
self.register_on_raise(on_raise)
|
60
|
+
|
61
|
+
#
|
62
|
+
|
52
63
|
def set_exception_factory(self, factory: CheckExceptionFactory) -> None:
|
53
64
|
self._exception_factory = factory
|
54
65
|
|
@@ -364,6 +375,18 @@ class Checks:
|
|
364
375
|
|
365
376
|
return v
|
366
377
|
|
378
|
+
def not_equal(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
|
379
|
+
if o == v:
|
380
|
+
self._raise(
|
381
|
+
ValueError,
|
382
|
+
'Must not be equal',
|
383
|
+
msg,
|
384
|
+
Checks._ArgsKwargs(v, o),
|
385
|
+
render_fmt='%s == %s',
|
386
|
+
)
|
387
|
+
|
388
|
+
return v
|
389
|
+
|
367
390
|
def is_(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
|
368
391
|
if o is not v:
|
369
392
|
self._raise(
|
omlish/lite/contextmanagers.py
CHANGED
@@ -7,6 +7,7 @@ from .check import check
|
|
7
7
|
|
8
8
|
T = ta.TypeVar('T')
|
9
9
|
ExitStackedT = ta.TypeVar('ExitStackedT', bound='ExitStacked')
|
10
|
+
AsyncExitStackedT = ta.TypeVar('AsyncExitStackedT', bound='AsyncExitStacked')
|
10
11
|
|
11
12
|
|
12
13
|
##
|
@@ -35,6 +36,33 @@ class ExitStacked:
|
|
35
36
|
return es.enter_context(cm)
|
36
37
|
|
37
38
|
|
39
|
+
class AsyncExitStacked:
|
40
|
+
_exit_stack: ta.Optional[contextlib.AsyncExitStack] = None
|
41
|
+
|
42
|
+
async def __aenter__(self: AsyncExitStackedT) -> AsyncExitStackedT:
|
43
|
+
check.state(self._exit_stack is None)
|
44
|
+
es = self._exit_stack = contextlib.AsyncExitStack()
|
45
|
+
await es.__aenter__()
|
46
|
+
return self
|
47
|
+
|
48
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
49
|
+
if (es := self._exit_stack) is None:
|
50
|
+
return None
|
51
|
+
await self._async_exit_contexts()
|
52
|
+
return await es.__aexit__(exc_type, exc_val, exc_tb)
|
53
|
+
|
54
|
+
async def _async_exit_contexts(self) -> None:
|
55
|
+
pass
|
56
|
+
|
57
|
+
def _enter_context(self, cm: ta.ContextManager[T]) -> T:
|
58
|
+
es = check.not_none(self._exit_stack)
|
59
|
+
return es.enter_context(cm)
|
60
|
+
|
61
|
+
async def _enter_async_context(self, cm: ta.AsyncContextManager[T]) -> T:
|
62
|
+
es = check.not_none(self._exit_stack)
|
63
|
+
return await es.enter_async_context(cm)
|
64
|
+
|
65
|
+
|
38
66
|
##
|
39
67
|
|
40
68
|
|
@@ -46,6 +74,17 @@ def defer(fn: ta.Callable) -> ta.Generator[ta.Callable, None, None]:
|
|
46
74
|
fn()
|
47
75
|
|
48
76
|
|
77
|
+
@contextlib.asynccontextmanager
|
78
|
+
async def adefer(fn: ta.Callable) -> ta.AsyncGenerator[ta.Callable, None]:
|
79
|
+
try:
|
80
|
+
yield fn
|
81
|
+
finally:
|
82
|
+
await fn()
|
83
|
+
|
84
|
+
|
85
|
+
##
|
86
|
+
|
87
|
+
|
49
88
|
@contextlib.contextmanager
|
50
89
|
def attr_setting(obj, attr, val, *, default=None): # noqa
|
51
90
|
not_set = object()
|
@@ -1,9 +1,9 @@
|
|
1
1
|
omlish/.manifests.json,sha256=dyIpveH7Z8OnQp2pTn6NVv7LCDXVrozJWAzbk8PBavg,7950
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=rTnrIQNQ5FRbHCr1olR3EzpCFMG4gqKht36KMpz3fPk,3409
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
|
5
5
|
omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
|
6
|
-
omlish/check.py,sha256=
|
6
|
+
omlish/check.py,sha256=THqm6jD1a0skAO5EC8SOVg58yq96Vk5wcuruBkCYxyU,2016
|
7
7
|
omlish/datetimes.py,sha256=HajeM1kBvwlTa-uR1TTZHmZ3zTPnnUr1uGGQhiO1XQ0,2152
|
8
8
|
omlish/defs.py,sha256=9uUjJuVIbCBL3g14fyzAp-9gH935MFofvlfOGwcBIaM,4913
|
9
9
|
omlish/dynamic.py,sha256=35C_cCX_Vq2HrHzGk5T-zbrMvmUdiIiwDzDNixczoDo,6541
|
@@ -108,6 +108,11 @@ omlish/asyncs/bluelet/events.py,sha256=iXpRWmy64YcshT_nuyiJ39jbketZdtj8LrdlX3Jmp
|
|
108
108
|
omlish/asyncs/bluelet/files.py,sha256=pgcLV_3oGbpqQmOrii8SeizyYLp8XKofQJhqM82RlKw,2389
|
109
109
|
omlish/asyncs/bluelet/runner.py,sha256=F6Ep0th09f-FkIRJfMN3_u-iG21jNNv11WyqnHyITYU,15475
|
110
110
|
omlish/asyncs/bluelet/sockets.py,sha256=RrC2vU52dOEBYKzvoh1qA39uUE8p3uCB_oxnhaP1AeA,6752
|
111
|
+
omlish/asyncs/ioproxy/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
112
|
+
omlish/asyncs/ioproxy/io.py,sha256=nIvaKi5CEMrycj1N_gfBeMwILNfFA_H1rklgR87xKCM,4987
|
113
|
+
omlish/asyncs/ioproxy/proxier.py,sha256=yhHud-00DuGZeSlJHJs6dpsXUpsmuD1Kw0vw9gTsdpU,4456
|
114
|
+
omlish/asyncs/ioproxy/proxy.py,sha256=cPzwHRlptaRPAKC5XdqwnBEObGNfSUsI4JWaUgFoZ64,3905
|
115
|
+
omlish/asyncs/ioproxy/typing.py,sha256=Aa9ysSEFww_P39Bza0p-CehRpvwg0UvcopeQ-L_isyc,2440
|
111
116
|
omlish/bootstrap/__init__.py,sha256=-Rtsg7uPQNhh1dIT9nqrz96XlqizwoLnWf-FwOEstJI,730
|
112
117
|
omlish/bootstrap/__main__.py,sha256=4jCwsaogp0FrJjJZ85hzF4-WqluPeheHbfeoKynKvNs,194
|
113
118
|
omlish/bootstrap/base.py,sha256=d8hqn4hp1XMMi5PgcJBQXPKmW47epu8CxBlqDZiRZb4,1073
|
@@ -159,7 +164,7 @@ omlish/configs/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
159
164
|
omlish/configs/processing/all.py,sha256=roIQ7EZJXSzsyUxNHNJaZsXcD2jdT46Ly1XXfG8xEcI,722
|
160
165
|
omlish/configs/processing/flattening.py,sha256=1duZH5zbrGuoYqaJco5LN5qx6e76QP5pHbIyItkQsFY,5021
|
161
166
|
omlish/configs/processing/inheritance.py,sha256=lFD8eWRE0cG0Z3-eCu7pMsP2skWhUNaoAtWi9fNfn8k,1218
|
162
|
-
omlish/configs/processing/matching.py,sha256=
|
167
|
+
omlish/configs/processing/matching.py,sha256=R64RxpPB1uX5Ztvvk2dQ2xi_xwlaxkxQgZwtDVR9spY,1514
|
163
168
|
omlish/configs/processing/names.py,sha256=weHmaTclzgM9lUn3aBtw-kwZ3mc2N-CZlFg3Kd_UsKo,1093
|
164
169
|
omlish/configs/processing/rewriting.py,sha256=v7PfHtuTn5v_5Y6Au7oMN2Z0nxAMy1iYyO5CXnTvZhs,4226
|
165
170
|
omlish/configs/processing/strings.py,sha256=qFS2oh6z02IaM_q4lTKLdufzkJqAJ6J-Qjrz5S-QJoM,826
|
@@ -325,7 +330,7 @@ omlish/inject/impl/providers.py,sha256=QnwhsujJFIHC0JTgd2Wlo1kP53i3CWTrj1nKU2DNx
|
|
325
330
|
omlish/inject/impl/proxy.py,sha256=1ko0VaKqzu9UG8bIldp9xtUrAVUOFTKWKTjOCqIGr4s,1636
|
326
331
|
omlish/inject/impl/scopes.py,sha256=hKnzNieB-fJSFEXDP_QG1mCfIKoVFIfFlf9LiIt5tk4,5920
|
327
332
|
omlish/io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
328
|
-
omlish/io/abc.py,sha256=
|
333
|
+
omlish/io/abc.py,sha256=M40QB2udYpCEqmlxCcHv6FlJYJY6ymmJQBlaklYv0U8,1256
|
329
334
|
omlish/io/buffers.py,sha256=qo1hCqTfKvlbSmddneporqCtW0rZJ_Mv2GrQTI1Hbk0,5636
|
330
335
|
omlish/io/pyio.py,sha256=q4RBFVpBE5PYjnGPGT-_4pcZb7dFJmLJ4LtI8OoDRQY,95433
|
331
336
|
omlish/io/trampoline.py,sha256=oUKTQg1F5xQS1431Kt7MbK-NZpX509ubcXU-s86xJr8,7171
|
@@ -392,9 +397,9 @@ omlish/lifecycles/states.py,sha256=zqMOU2ZU-MDNnWuwauM3_anIAiXM8LoBDElDEraptFg,1
|
|
392
397
|
omlish/lifecycles/transitions.py,sha256=qQtFby-h4VzbvgaUqT2NnbNumlcOx9FVVADP9t83xj4,1939
|
393
398
|
omlish/lite/__init__.py,sha256=ISLhM4q0LR1XXTCaHdZOZxBRyIsoZqYm4u0bf1BPcVk,148
|
394
399
|
omlish/lite/cached.py,sha256=O7ozcoDNFm1Hg2wtpHEqYSp_i_nCLNOP6Ueq_Uk-7mU,1300
|
395
|
-
omlish/lite/check.py,sha256=
|
400
|
+
omlish/lite/check.py,sha256=OLwtE2x6nlbGx4vS3Rda7zMHpgqzDSLJminTAX2lqLA,13529
|
396
401
|
omlish/lite/configs.py,sha256=Ev_19sbII67pTWzInYjYqa9VyTiZBvyjhZqyG8TtufE,908
|
397
|
-
omlish/lite/contextmanagers.py,sha256=
|
402
|
+
omlish/lite/contextmanagers.py,sha256=ciaMl0D3QDHToM7M28-kwZ-Q48LtwgCxiud3nekgutA,2863
|
398
403
|
omlish/lite/dataclasses.py,sha256=M6UD4VwGo0Ky7RNzKWbO0IOy7iBZVCIbTiC6EYbFnX8,1035
|
399
404
|
omlish/lite/inject.py,sha256=qBUftFeXMiRgANYbNS2e7TePMYyFAcuLgsJiLyMTW5o,28769
|
400
405
|
omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
|
@@ -609,9 +614,9 @@ omlish/text/indent.py,sha256=YjtJEBYWuk8--b9JU_T6q4yxV85_TR7VEVr5ViRCFwk,1336
|
|
609
614
|
omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
|
610
615
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
611
616
|
omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
|
612
|
-
omlish-0.0.0.
|
613
|
-
omlish-0.0.0.
|
614
|
-
omlish-0.0.0.
|
615
|
-
omlish-0.0.0.
|
616
|
-
omlish-0.0.0.
|
617
|
-
omlish-0.0.0.
|
617
|
+
omlish-0.0.0.dev213.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
618
|
+
omlish-0.0.0.dev213.dist-info/METADATA,sha256=IpkbQXwChAhIh8w_W3662VHEfMYUAs1Kcq1NRDjAr6Q,4264
|
619
|
+
omlish-0.0.0.dev213.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
620
|
+
omlish-0.0.0.dev213.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
621
|
+
omlish-0.0.0.dev213.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
622
|
+
omlish-0.0.0.dev213.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|