omlish 0.0.0.dev211__py3-none-any.whl → 0.0.0.dev213__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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.dev211.dist-info → omlish-0.0.0.dev213.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev211.dist-info → omlish-0.0.0.dev213.dist-info}/RECORD +17 -12
- {omlish-0.0.0.dev211.dist-info → omlish-0.0.0.dev213.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev211.dist-info → omlish-0.0.0.dev213.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev211.dist-info → omlish-0.0.0.dev213.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev211.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
|