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 CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev211'
2
- __revision__ = '429bd6e544b5a0e15db5196c05605127719166d9'
1
+ __version__ = '0.0.0.dev213'
2
+ __revision__ = '03c9d6a7f92cec54535af989bf531b8598a896c0'
3
3
 
4
4
 
5
5
  #
@@ -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
@@ -85,6 +85,7 @@ not_none = check.not_none
85
85
  #
86
86
 
87
87
  equal = check.equal
88
+ not_equal = check.not_equal
88
89
  is_ = check.is_
89
90
  is_not = check.is_not
90
91
  callable = check.callable # noqa
@@ -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 in self._paths:
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
@@ -1,5 +1,6 @@
1
1
  # ruff: noqa: ANN204
2
2
 
3
+
3
4
  class IOBase:
4
5
  def seek(self, pos, whence=0): ...
5
6
 
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(
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omlish
3
- Version: 0.0.0.dev211
3
+ Version: 0.0.0.dev213
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,9 +1,9 @@
1
1
  omlish/.manifests.json,sha256=dyIpveH7Z8OnQp2pTn6NVv7LCDXVrozJWAzbk8PBavg,7950
2
- omlish/__about__.py,sha256=M0cCQiz1nNSIVpsNpftgCI4sNi-sYqMT_ZA_wP4FTWY,3409
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=RzMJhp8_dDnpHXnPiHDyZTW13KGDTopeuMgpwKCowPs,1988
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=JMS9r58pMCBbpewOhPY5oPtBu3uD6z6YBfZq4jnLwBE,1236
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=Cxs8KB1B_69rxpUYxI-MTsilAmNooJJn3w07DKqYKkE,1255
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=0PD-GKtaDqDX6jU5KbzbMvH-vl6jH82xgYfplmfTQkg,12941
400
+ omlish/lite/check.py,sha256=OLwtE2x6nlbGx4vS3Rda7zMHpgqzDSLJminTAX2lqLA,13529
396
401
  omlish/lite/configs.py,sha256=Ev_19sbII67pTWzInYjYqa9VyTiZBvyjhZqyG8TtufE,908
397
- omlish/lite/contextmanagers.py,sha256=m9JO--p7L7mSl4cycXysH-1AO27weDKjP3DZG61cwwM,1683
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.dev211.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
613
- omlish-0.0.0.dev211.dist-info/METADATA,sha256=5eXBkL9XUJsMuIZofsOEhTgJU-bOtX_KH188PXyq2aw,4264
614
- omlish-0.0.0.dev211.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
615
- omlish-0.0.0.dev211.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
616
- omlish-0.0.0.dev211.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
617
- omlish-0.0.0.dev211.dist-info/RECORD,,
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,,