omlish 0.0.0.dev146__py3-none-any.whl → 0.0.0.dev148__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 CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev146'
2
- __revision__ = '3e5441b65738d0b3c80a43abb47b62f9ef5a6bee'
1
+ __version__ = '0.0.0.dev148'
2
+ __revision__ = '01263e3c2d1b82ca19c3d1d6916041ca4276737b'
3
3
 
4
4
 
5
5
  #
File without changes
@@ -0,0 +1,63 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import asyncio.base_subprocess
3
+ import asyncio.subprocess
4
+ import typing as ta
5
+
6
+
7
+ AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
8
+
9
+
10
+ ##
11
+
12
+
13
+ ASYNCIO_DEFAULT_BUFFER_LIMIT = 2 ** 16
14
+
15
+
16
+ async def asyncio_open_stream_reader(
17
+ f: ta.IO,
18
+ loop: ta.Any = None,
19
+ *,
20
+ limit: int = ASYNCIO_DEFAULT_BUFFER_LIMIT,
21
+ ) -> asyncio.StreamReader:
22
+ if loop is None:
23
+ loop = asyncio.get_running_loop()
24
+
25
+ reader = asyncio.StreamReader(limit=limit, loop=loop)
26
+ await loop.connect_read_pipe(
27
+ lambda: asyncio.StreamReaderProtocol(reader, loop=loop),
28
+ f,
29
+ )
30
+
31
+ return reader
32
+
33
+
34
+ async def asyncio_open_stream_writer(
35
+ f: ta.IO,
36
+ loop: ta.Any = None,
37
+ ) -> asyncio.StreamWriter:
38
+ if loop is None:
39
+ loop = asyncio.get_running_loop()
40
+
41
+ writer_transport, writer_protocol = await loop.connect_write_pipe(
42
+ lambda: asyncio.streams.FlowControlMixin(loop=loop),
43
+ f,
44
+ )
45
+
46
+ return asyncio.streams.StreamWriter(
47
+ writer_transport,
48
+ writer_protocol,
49
+ None,
50
+ loop,
51
+ )
52
+
53
+
54
+ ##
55
+
56
+
57
+ def asyncio_maybe_timeout(
58
+ fut: AwaitableT,
59
+ timeout: ta.Optional[float] = None,
60
+ ) -> AwaitableT:
61
+ if timeout is not None:
62
+ fut = asyncio.wait_for(fut, timeout) # type: ignore
63
+ return fut
@@ -0,0 +1,297 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import asyncio.base_subprocess
3
+ import asyncio.subprocess
4
+ import contextlib
5
+ import functools
6
+ import logging
7
+ import subprocess
8
+ import sys
9
+ import typing as ta
10
+
11
+ from ..check import check_equal
12
+ from ..check import check_isinstance
13
+ from ..check import check_not_none
14
+ from ..check import check_single
15
+ from ..logs import log
16
+ from ..subprocesses import DEFAULT_SUBPROCESS_TRY_EXCEPTIONS
17
+ from ..subprocesses import prepare_subprocess_invocation
18
+ from ..subprocesses import subprocess_common_context
19
+ from .asyncio import asyncio_maybe_timeout
20
+
21
+
22
+ T = ta.TypeVar('T')
23
+
24
+
25
+ ##
26
+
27
+
28
+ @contextlib.asynccontextmanager
29
+ async def asyncio_subprocess_popen(
30
+ *cmd: str,
31
+ shell: bool = False,
32
+ timeout: ta.Optional[float] = None,
33
+ **kwargs: ta.Any,
34
+ ) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
35
+ fac: ta.Any
36
+ if shell:
37
+ fac = functools.partial(
38
+ asyncio.create_subprocess_shell,
39
+ check_single(cmd),
40
+ )
41
+ else:
42
+ fac = functools.partial(
43
+ asyncio.create_subprocess_exec,
44
+ *cmd,
45
+ )
46
+
47
+ with subprocess_common_context(
48
+ *cmd,
49
+ shell=shell,
50
+ timeout=timeout,
51
+ **kwargs,
52
+ ):
53
+ proc: asyncio.subprocess.Process
54
+ proc = await fac(**kwargs)
55
+ try:
56
+ yield proc
57
+
58
+ finally:
59
+ await asyncio_maybe_timeout(proc.wait(), timeout)
60
+
61
+
62
+ ##
63
+
64
+
65
+ class AsyncioProcessCommunicator:
66
+ def __init__(
67
+ self,
68
+ proc: asyncio.subprocess.Process,
69
+ loop: ta.Optional[ta.Any] = None,
70
+ ) -> None:
71
+ super().__init__()
72
+
73
+ if loop is None:
74
+ loop = asyncio.get_running_loop()
75
+
76
+ self._proc = proc
77
+ self._loop = loop
78
+
79
+ self._transport: asyncio.base_subprocess.BaseSubprocessTransport = check_isinstance(
80
+ proc._transport, # type: ignore # noqa
81
+ asyncio.base_subprocess.BaseSubprocessTransport,
82
+ )
83
+
84
+ @property
85
+ def _debug(self) -> bool:
86
+ return self._loop.get_debug()
87
+
88
+ async def _feed_stdin(self, input: bytes) -> None: # noqa
89
+ stdin = check_not_none(self._proc.stdin)
90
+ try:
91
+ if input is not None:
92
+ stdin.write(input)
93
+ if self._debug:
94
+ log.debug('%r communicate: feed stdin (%s bytes)', self, len(input))
95
+
96
+ await stdin.drain()
97
+
98
+ except (BrokenPipeError, ConnectionResetError) as exc:
99
+ # communicate() ignores BrokenPipeError and ConnectionResetError. write() and drain() can raise these
100
+ # exceptions.
101
+ if self._debug:
102
+ log.debug('%r communicate: stdin got %r', self, exc)
103
+
104
+ if self._debug:
105
+ log.debug('%r communicate: close stdin', self)
106
+
107
+ stdin.close()
108
+
109
+ async def _noop(self) -> None:
110
+ return None
111
+
112
+ async def _read_stream(self, fd: int) -> bytes:
113
+ transport: ta.Any = check_not_none(self._transport.get_pipe_transport(fd))
114
+
115
+ if fd == 2:
116
+ stream = check_not_none(self._proc.stderr)
117
+ else:
118
+ check_equal(fd, 1)
119
+ stream = check_not_none(self._proc.stdout)
120
+
121
+ if self._debug:
122
+ name = 'stdout' if fd == 1 else 'stderr'
123
+ log.debug('%r communicate: read %s', self, name)
124
+
125
+ output = await stream.read()
126
+
127
+ if self._debug:
128
+ name = 'stdout' if fd == 1 else 'stderr'
129
+ log.debug('%r communicate: close %s', self, name)
130
+
131
+ transport.close()
132
+
133
+ return output
134
+
135
+ class Communication(ta.NamedTuple):
136
+ stdout: ta.Optional[bytes]
137
+ stderr: ta.Optional[bytes]
138
+
139
+ async def _communicate(
140
+ self,
141
+ input: ta.Any = None, # noqa
142
+ ) -> Communication:
143
+ stdin_fut: ta.Any
144
+ if self._proc.stdin is not None:
145
+ stdin_fut = self._feed_stdin(input)
146
+ else:
147
+ stdin_fut = self._noop()
148
+
149
+ stdout_fut: ta.Any
150
+ if self._proc.stdout is not None:
151
+ stdout_fut = self._read_stream(1)
152
+ else:
153
+ stdout_fut = self._noop()
154
+
155
+ stderr_fut: ta.Any
156
+ if self._proc.stderr is not None:
157
+ stderr_fut = self._read_stream(2)
158
+ else:
159
+ stderr_fut = self._noop()
160
+
161
+ stdin_res, stdout_res, stderr_res = await asyncio.gather(stdin_fut, stdout_fut, stderr_fut)
162
+
163
+ await self._proc.wait()
164
+
165
+ return AsyncioProcessCommunicator.Communication(stdout_res, stderr_res)
166
+
167
+ async def communicate(
168
+ self,
169
+ input: ta.Any = None, # noqa
170
+ timeout: ta.Optional[float] = None,
171
+ ) -> Communication:
172
+ return await asyncio_maybe_timeout(self._communicate(input), timeout)
173
+
174
+
175
+ async def asyncio_subprocess_communicate(
176
+ proc: asyncio.subprocess.Process,
177
+ input: ta.Any = None, # noqa
178
+ timeout: ta.Optional[float] = None,
179
+ ) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
180
+ return await AsyncioProcessCommunicator(proc).communicate(input, timeout) # noqa
181
+
182
+
183
+ ##
184
+
185
+
186
+ async def _asyncio_subprocess_check_run(
187
+ *args: str,
188
+ input: ta.Any = None, # noqa
189
+ timeout: ta.Optional[float] = None,
190
+ **kwargs: ta.Any,
191
+ ) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
192
+ args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
193
+
194
+ proc: asyncio.subprocess.Process
195
+ async with asyncio_subprocess_popen(*args, **kwargs) as proc:
196
+ stdout, stderr = await asyncio_subprocess_communicate(proc, input, timeout)
197
+
198
+ if proc.returncode:
199
+ raise subprocess.CalledProcessError(
200
+ proc.returncode,
201
+ args,
202
+ output=stdout,
203
+ stderr=stderr,
204
+ )
205
+
206
+ return stdout, stderr
207
+
208
+
209
+ async def asyncio_subprocess_check_call(
210
+ *args: str,
211
+ stdout: ta.Any = sys.stderr,
212
+ input: ta.Any = None, # noqa
213
+ timeout: ta.Optional[float] = None,
214
+ **kwargs: ta.Any,
215
+ ) -> None:
216
+ _, _ = await _asyncio_subprocess_check_run(
217
+ *args,
218
+ stdout=stdout,
219
+ input=input,
220
+ timeout=timeout,
221
+ **kwargs,
222
+ )
223
+
224
+
225
+ async def asyncio_subprocess_check_output(
226
+ *args: str,
227
+ input: ta.Any = None, # noqa
228
+ timeout: ta.Optional[float] = None,
229
+ **kwargs: ta.Any,
230
+ ) -> bytes:
231
+ stdout, stderr = await _asyncio_subprocess_check_run(
232
+ *args,
233
+ stdout=asyncio.subprocess.PIPE,
234
+ input=input,
235
+ timeout=timeout,
236
+ **kwargs,
237
+ )
238
+
239
+ return check_not_none(stdout)
240
+
241
+
242
+ async def asyncio_subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
243
+ return (await asyncio_subprocess_check_output(*args, **kwargs)).decode().strip()
244
+
245
+
246
+ ##
247
+
248
+
249
+ async def _asyncio_subprocess_try_run(
250
+ fn: ta.Callable[..., ta.Awaitable[T]],
251
+ *args: ta.Any,
252
+ try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
253
+ **kwargs: ta.Any,
254
+ ) -> ta.Union[T, Exception]:
255
+ try:
256
+ return await fn(*args, **kwargs)
257
+ except try_exceptions as e: # noqa
258
+ if log.isEnabledFor(logging.DEBUG):
259
+ log.exception('command failed')
260
+ return e
261
+
262
+
263
+ async def asyncio_subprocess_try_call(
264
+ *args: str,
265
+ try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
266
+ **kwargs: ta.Any,
267
+ ) -> bool:
268
+ if isinstance(await _asyncio_subprocess_try_run(
269
+ asyncio_subprocess_check_call,
270
+ *args,
271
+ try_exceptions=try_exceptions,
272
+ **kwargs,
273
+ ), Exception):
274
+ return False
275
+ else:
276
+ return True
277
+
278
+
279
+ async def asyncio_subprocess_try_output(
280
+ *args: str,
281
+ try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
282
+ **kwargs: ta.Any,
283
+ ) -> ta.Optional[bytes]:
284
+ if isinstance(ret := await _asyncio_subprocess_try_run(
285
+ asyncio_subprocess_check_output,
286
+ *args,
287
+ try_exceptions=try_exceptions,
288
+ **kwargs,
289
+ ), Exception):
290
+ return None
291
+ else:
292
+ return ret
293
+
294
+
295
+ async def asyncio_subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
296
+ out = await asyncio_subprocess_try_output(*args, **kwargs)
297
+ return out.decode().strip() if out is not None else None
omlish/lite/cached.py CHANGED
@@ -7,7 +7,10 @@ T = ta.TypeVar('T')
7
7
  CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
8
8
 
9
9
 
10
- class _cached_nullary: # noqa
10
+ ##
11
+
12
+
13
+ class _AbstractCachedNullary:
11
14
  def __init__(self, fn):
12
15
  super().__init__()
13
16
  self._fn = fn
@@ -15,20 +18,42 @@ class _cached_nullary: # noqa
15
18
  functools.update_wrapper(self, fn)
16
19
 
17
20
  def __call__(self, *args, **kwargs): # noqa
18
- if self._value is self._missing:
19
- self._value = self._fn()
20
- return self._value
21
+ raise TypeError
21
22
 
22
23
  def __get__(self, instance, owner): # noqa
23
24
  bound = instance.__dict__[self._fn.__name__] = self.__class__(self._fn.__get__(instance, owner))
24
25
  return bound
25
26
 
26
27
 
28
+ ##
29
+
30
+
31
+ class _CachedNullary(_AbstractCachedNullary):
32
+ def __call__(self, *args, **kwargs): # noqa
33
+ if self._value is self._missing:
34
+ self._value = self._fn()
35
+ return self._value
36
+
37
+
27
38
  def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
28
- return _cached_nullary(fn)
39
+ return _CachedNullary(fn)
29
40
 
30
41
 
31
42
  def static_init(fn: CallableT) -> CallableT:
32
43
  fn = cached_nullary(fn)
33
44
  fn()
34
45
  return fn
46
+
47
+
48
+ ##
49
+
50
+
51
+ class _AsyncCachedNullary(_AbstractCachedNullary):
52
+ async def __call__(self, *args, **kwargs):
53
+ if self._value is self._missing:
54
+ self._value = await self._fn()
55
+ return self._value
56
+
57
+
58
+ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
59
+ return _AsyncCachedNullary(fn)
@@ -0,0 +1,22 @@
1
+ import ctypes as ct
2
+ import sys
3
+
4
+
5
+ LINUX_PR_SET_PDEATHSIG = 1 # Second arg is a signal
6
+ LINUX_PR_GET_PDEATHSIG = 2 # Second arg is a ptr to return the signal
7
+
8
+
9
+ def set_process_deathsig(sig: int) -> bool:
10
+ if sys.platform == 'linux':
11
+ libc = ct.CDLL('libc.so.6')
12
+
13
+ # int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
14
+ libc.prctl.restype = ct.c_int
15
+ libc.prctl.argtypes = [ct.c_int, ct.c_ulong, ct.c_ulong, ct.c_ulong, ct.c_ulong]
16
+
17
+ libc.prctl(LINUX_PR_SET_PDEATHSIG, sig, 0, 0, 0, 0)
18
+
19
+ return True
20
+
21
+ else:
22
+ return False
omlish/lite/pycharm.py CHANGED
@@ -36,7 +36,6 @@ def pycharm_debug_connect(prd: PycharmRemoteDebug) -> None:
36
36
  def pycharm_debug_preamble(prd: PycharmRemoteDebug) -> str:
37
37
  import inspect
38
38
  import textwrap
39
-
40
39
  return textwrap.dedent(f"""
41
40
  {inspect.getsource(pycharm_debug_connect)}
42
41
 
@@ -1,15 +1,18 @@
1
1
  # ruff: noqa: UP006 UP007
2
+ import contextlib
2
3
  import logging
3
4
  import os
4
5
  import shlex
5
6
  import subprocess
6
7
  import sys
8
+ import time
7
9
  import typing as ta
8
10
 
9
11
  from .logs import log
10
12
  from .runtime import is_debugger_attached
11
13
 
12
14
 
15
+ T = ta.TypeVar('T')
13
16
  SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull']
14
17
 
15
18
 
@@ -40,7 +43,7 @@ def subprocess_maybe_shell_wrap_exec(*args: str) -> ta.Tuple[str, ...]:
40
43
  return args
41
44
 
42
45
 
43
- def _prepare_subprocess_invocation(
46
+ def prepare_subprocess_invocation(
44
47
  *args: str,
45
48
  env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
46
49
  extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
@@ -48,9 +51,9 @@ def _prepare_subprocess_invocation(
48
51
  shell: bool = False,
49
52
  **kwargs: ta.Any,
50
53
  ) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
51
- log.debug(args)
54
+ log.debug('prepare_subprocess_invocation: args=%r', args)
52
55
  if extra_env:
53
- log.debug(extra_env)
56
+ log.debug('prepare_subprocess_invocation: extra_env=%r', extra_env)
54
57
 
55
58
  if extra_env:
56
59
  env = {**(env if env is not None else os.environ), **extra_env}
@@ -69,14 +72,46 @@ def _prepare_subprocess_invocation(
69
72
  )
70
73
 
71
74
 
72
- def subprocess_check_call(*args: str, stdout=sys.stderr, **kwargs: ta.Any) -> None:
73
- args, kwargs = _prepare_subprocess_invocation(*args, stdout=stdout, **kwargs)
74
- return subprocess.check_call(args, **kwargs) # type: ignore
75
+ ##
76
+
77
+
78
+ @contextlib.contextmanager
79
+ def subprocess_common_context(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
80
+ start_time = time.time()
81
+ try:
82
+ log.debug('subprocess_common_context.try: args=%r', args)
83
+ yield
84
+
85
+ except Exception as exc: # noqa
86
+ log.debug('subprocess_common_context.except: exc=%r', exc)
87
+ raise
88
+
89
+ finally:
90
+ end_time = time.time()
91
+ elapsed_s = end_time - start_time
92
+ log.debug('subprocess_common_context.finally: elapsed_s=%f args=%r', elapsed_s, args)
93
+
94
+
95
+ ##
96
+
97
+
98
+ def subprocess_check_call(
99
+ *args: str,
100
+ stdout: ta.Any = sys.stderr,
101
+ **kwargs: ta.Any,
102
+ ) -> None:
103
+ args, kwargs = prepare_subprocess_invocation(*args, stdout=stdout, **kwargs)
104
+ with subprocess_common_context(*args, **kwargs):
105
+ return subprocess.check_call(args, **kwargs) # type: ignore
75
106
 
76
107
 
77
- def subprocess_check_output(*args: str, **kwargs: ta.Any) -> bytes:
78
- args, kwargs = _prepare_subprocess_invocation(*args, **kwargs)
79
- return subprocess.check_output(args, **kwargs)
108
+ def subprocess_check_output(
109
+ *args: str,
110
+ **kwargs: ta.Any,
111
+ ) -> bytes:
112
+ args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
113
+ with subprocess_common_context(*args, **kwargs):
114
+ return subprocess.check_output(args, **kwargs)
80
115
 
81
116
 
82
117
  def subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
@@ -92,16 +127,31 @@ DEFAULT_SUBPROCESS_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
92
127
  )
93
128
 
94
129
 
95
- def subprocess_try_call(
96
- *args: str,
130
+ def _subprocess_try_run(
131
+ fn: ta.Callable[..., T],
132
+ *args: ta.Any,
97
133
  try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
98
134
  **kwargs: ta.Any,
99
- ) -> bool:
135
+ ) -> ta.Union[T, Exception]:
100
136
  try:
101
- subprocess_check_call(*args, **kwargs)
137
+ return fn(*args, **kwargs)
102
138
  except try_exceptions as e: # noqa
103
139
  if log.isEnabledFor(logging.DEBUG):
104
140
  log.exception('command failed')
141
+ return e
142
+
143
+
144
+ def subprocess_try_call(
145
+ *args: str,
146
+ try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
147
+ **kwargs: ta.Any,
148
+ ) -> bool:
149
+ if isinstance(_subprocess_try_run(
150
+ subprocess_check_call,
151
+ *args,
152
+ try_exceptions=try_exceptions,
153
+ **kwargs,
154
+ ), Exception):
105
155
  return False
106
156
  else:
107
157
  return True
@@ -112,12 +162,15 @@ def subprocess_try_output(
112
162
  try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
113
163
  **kwargs: ta.Any,
114
164
  ) -> ta.Optional[bytes]:
115
- try:
116
- return subprocess_check_output(*args, **kwargs)
117
- except try_exceptions as e: # noqa
118
- if log.isEnabledFor(logging.DEBUG):
119
- log.exception('command failed')
165
+ if isinstance(ret := _subprocess_try_run(
166
+ subprocess_check_output,
167
+ *args,
168
+ try_exceptions=try_exceptions,
169
+ **kwargs,
170
+ ), Exception):
120
171
  return None
172
+ else:
173
+ return ret
121
174
 
122
175
 
123
176
  def subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
omlish/manifests/load.py CHANGED
@@ -31,6 +31,8 @@ class ManifestLoader:
31
31
  self._cls_cache: ta.Dict[str, type] = {}
32
32
  self._raw_cache: ta.Dict[str, ta.Optional[ta.Sequence[Manifest]]] = {}
33
33
 
34
+ #
35
+
34
36
  @classmethod
35
37
  def from_entry_point(
36
38
  cls,
@@ -52,6 +54,8 @@ class ManifestLoader:
52
54
 
53
55
  return cls(module_remap=rm, **kwargs)
54
56
 
57
+ #
58
+
55
59
  def load_cls(self, key: str) -> type:
56
60
  try:
57
61
  return self._cls_cache[key]
@@ -153,6 +157,8 @@ class ManifestLoader:
153
157
 
154
158
  return lst
155
159
 
160
+ #
161
+
156
162
  ENTRY_POINT_GROUP = 'omlish.manifests'
157
163
 
158
164
  def discover(self) -> ta.Sequence[str]:
@@ -142,7 +142,12 @@ class AsyncsPlugin:
142
142
  if len(bes) > 1 and set(bes) != {'trio', 'trio_asyncio'}:
143
143
  raise Exception(f'{item.nodeid}: multiple async backends specified: {bes}')
144
144
  elif is_async_function(item.obj) and not bes:
145
- raise Exception(f'{item.nodeid}: async def function and no async plugin specified')
145
+ from _pytest.unittest import UnitTestCase # noqa
146
+ if isinstance(item.parent, UnitTestCase):
147
+ # unittest handles these itself.
148
+ pass
149
+ else:
150
+ raise Exception(f'{item.nodeid}: async def function and no async plugin specified')
146
151
 
147
152
  if 'trio_asyncio' in bes:
148
153
  obj = item.obj
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev146
3
+ Version: 0.0.0.dev148
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=RX24SRc6DCEg77PUVnaXOKCWa5TF_c9RQJdGIf7gl9c,1135
2
- omlish/__about__.py,sha256=G3zss6e134zxU5xmjngBc8mskjSdZxwZFcH8cUO87Sc,3409
2
+ omlish/__about__.py,sha256=SGKzVFr0tcTK7dCoK2Y4-o8CVkBHmsj2aDPhw4bLYqc,3409
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/argparse.py,sha256=cqKGAqcxuxv_s62z0gq29L9KAvg_3-_rFvXKjVpRJjo,8126
5
5
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
@@ -311,9 +311,10 @@ omlish/lifecycles/manager.py,sha256=Au66KaO-fI-SEJALaPUJsCHYW2GE20xextk1wKn2BEU,
311
311
  omlish/lifecycles/states.py,sha256=zqMOU2ZU-MDNnWuwauM3_anIAiXM8LoBDElDEraptFg,1292
312
312
  omlish/lifecycles/transitions.py,sha256=qQtFby-h4VzbvgaUqT2NnbNumlcOx9FVVADP9t83xj4,1939
313
313
  omlish/lite/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
314
- omlish/lite/cached.py,sha256=rrc_JEv3sKJIEmCBB6g7DwPvkb1hNFmhg0mxkvuXDJw,848
314
+ omlish/lite/cached.py,sha256=hBW77-F7ZLtFqbLwVrlqaJ4-iFHMQleMWZXaZN1IubA,1308
315
315
  omlish/lite/check.py,sha256=pQC412ffe_Zh7eHa4C1UYn6fA71Ls1vpVM0ZIOroPAY,1765
316
316
  omlish/lite/contextmanagers.py,sha256=DRarS2gx15tbse1YzyI8ZLdBmWYjFgmKPe-i4CSNDYg,1458
317
+ omlish/lite/deathsig.py,sha256=Etz04WX6R2PXQ-BgqJyVJ0C5Pqym6Ds6PAG7p1cqr5o,626
317
318
  omlish/lite/docker.py,sha256=Dj_7lQjs2sFPc_SmUn5CpJF3LnQQnckEBYGBKz8u5tE,392
318
319
  omlish/lite/inject.py,sha256=aRRmFb6azTKF208ogYwVCEopNZx7496Ta1GZmL_IKBA,23716
319
320
  omlish/lite/io.py,sha256=3ECgUXdRnXyS6pGTSoVr6oB4moI38EpWxTq08zaTM-U,5339
@@ -323,7 +324,7 @@ omlish/lite/logs.py,sha256=1pcGu0ekhVCcLUckLSP16VccnAoprjtl5Vkdfm7y1Wg,6184
323
324
  omlish/lite/marshal.py,sha256=1wqZWKapZ5rFgDxSkb447Xv2ce2SFEpiB1EMg1nh2BI,13530
324
325
  omlish/lite/maybes.py,sha256=7OlHJ8Q2r4wQ-aRbZSlJY7x0e8gDvufFdlohGEIJ3P4,833
325
326
  omlish/lite/pidfile.py,sha256=PRSDOAXmNkNwxh-Vwif0Nrs8RAmWroiNhLKIbdjwzBc,1723
326
- omlish/lite/pycharm.py,sha256=CUArgzaG8ZZ0evN7tdrML5WXyF-G_BvF_s3Z4SI2LA0,1164
327
+ omlish/lite/pycharm.py,sha256=pUOJevrPClSqTCEOkQBO11LKX2003tfDcp18a03QFrc,1163
327
328
  omlish/lite/reflect.py,sha256=ad_ya_zZJOQB8HoNjs9yc66R54zgflwJVPJqiBXMzqA,1681
328
329
  omlish/lite/resources.py,sha256=YNSmX1Ohck1aoWRs55a-o5ChVbFJIQhtbqE-XwF55Oc,326
329
330
  omlish/lite/runtime.py,sha256=lVw5_yuQNHXZLwGf_l59u8IrAtBLZWPTml6owQ55uro,439
@@ -331,8 +332,11 @@ omlish/lite/secrets.py,sha256=3Mz3V2jf__XU9qNHcH56sBSw95L3U2UPL24bjvobG0c,816
331
332
  omlish/lite/socket.py,sha256=7OYgkXTcQv0wq7TQuLnl9y6dJA1ZT6Vbc1JH59QlxgY,1792
332
333
  omlish/lite/socketserver.py,sha256=Esy9dAo9dPnNavNx5hW52YZi5hv504a8XQUudMrPs2A,1595
333
334
  omlish/lite/strings.py,sha256=QURcE4-1pKVW8eT_5VCJpXaHDWR2dW2pYOChTJnZDiQ,1504
334
- omlish/lite/subprocesses.py,sha256=1we1S-YQ9kbH36hPWLoh6zKZUARRnq2__ewtX_dVdWU,3633
335
+ omlish/lite/subprocesses.py,sha256=RTs8HJ1Lz8YOZTHw12Ja8KW7Eq4oyDFJZDiG0PSUBKY,4918
335
336
  omlish/lite/typing.py,sha256=U3-JaEnkDSYxK4tsu_MzUn3RP6qALBe5FXQXpD-licE,1090
337
+ omlish/lite/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
338
+ omlish/lite/asyncio/asyncio.py,sha256=tsqQSLl5rG4GZHPYOBqI7V2yuw45ZVuGZEHe-J4QEhE,1320
339
+ omlish/lite/asyncio/subprocesses.py,sha256=crG4FlkVIA19sO2QtIagOCtXk8ak9rLaHgbTjGDy3mk,8274
336
340
  omlish/lite/fdio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
337
341
  omlish/lite/fdio/corohttp.py,sha256=FHdakDTGI2UYbCihahuwleyailclxQMUGhpkz3suww4,4080
338
342
  omlish/lite/fdio/handlers.py,sha256=Wr0O2cvIC8NuLs3yoDHj9ZG4n1g_oVEeT87B0WDsg0Y,1341
@@ -352,7 +356,7 @@ omlish/logs/handlers.py,sha256=UpzUf3kWBBzWOnrtljoZsLjISw3Ix-ePz3Nsmp6lRgE,255
352
356
  omlish/logs/noisy.py,sha256=Ubc-eTH6ZbGYsLfUUi69JAotwuUwzb-SJBeGo_0dIZI,348
353
357
  omlish/logs/utils.py,sha256=MgGovbP0zUrZ3FGD3qYNQWn-l0jy0Y0bStcQvv5BOmQ,391
354
358
  omlish/manifests/__init__.py,sha256=P2B0dpT8D7l5lJwRGPA92IcQj6oeXfd90X5-q9BJrKg,51
355
- omlish/manifests/load.py,sha256=Wn0Orrs65rLdXneT7tlixX5Q5OXW460-zzw6IkAye7k,4788
359
+ omlish/manifests/load.py,sha256=8R-S5CyQpAbxDHt5wcNF6mAYri8bGndn6R2uEVOh52Y,4809
356
360
  omlish/manifests/types.py,sha256=d8bv5tknCJqclRfxCpao_8XxHo2yofhLpVHQTB-MfNw,260
357
361
  omlish/marshal/__init__.py,sha256=iVA7n31L08Bdub6HKPvYOXVvDhk2CMA6rPeKDL_u1to,2298
358
362
  omlish/marshal/any.py,sha256=e82OyYK3Emm1P1ClnsnxP7fIWC2iNVyW0H5nK4mLmWM,779
@@ -487,7 +491,7 @@ omlish/testing/pytest/inject/__init__.py,sha256=pdRKv1HcDmJ_yArKJbYITPXXZthRSGgB
487
491
  omlish/testing/pytest/inject/harness.py,sha256=v4DaKJ0KL8oQjzIMK43Gh8GHP4hiI6-lY37O9lyOHRk,5724
488
492
  omlish/testing/pytest/plugins/__init__.py,sha256=ys1zXrYrNm7Uo6YOIVJ6Bd3dQo6kv387k7MbTYlqZSI,467
489
493
  omlish/testing/pytest/plugins/_registry.py,sha256=IK04KlBgiOJxKAyCCgjpX2R-9tE-btalYJkgjLc8Te8,77
490
- omlish/testing/pytest/plugins/asyncs.py,sha256=SV6oKCy50CGkzLGYX-CT4MfWNqsrH8ONEbIWC3tFcHA,5324
494
+ omlish/testing/pytest/plugins/asyncs.py,sha256=CG-cWWxCtxVIyKJKEjxfFV0MVwYBHPo1mb-umCGz9X8,5532
491
495
  omlish/testing/pytest/plugins/depskip.py,sha256=xithY-OMtjwhv8mcRNkv-WI_PSQtHldQ8H1s60MIXkk,2673
492
496
  omlish/testing/pytest/plugins/logging.py,sha256=1zs6Xe54wiaSjabCviaFXwKkoN97CKm3mA5mEoUeJGs,380
493
497
  omlish/testing/pytest/plugins/managermarks.py,sha256=AP3ty-QB-8O5DkulwUOudBlUOvXMHhBfNyY-0yCmejk,1520
@@ -504,9 +508,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
504
508
  omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
505
509
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
506
510
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
507
- omlish-0.0.0.dev146.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
508
- omlish-0.0.0.dev146.dist-info/METADATA,sha256=V8cPQmzScS8Lnw8b-HzO9Pg_uvOnOaPZxPJ_yrzxTc8,4264
509
- omlish-0.0.0.dev146.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
510
- omlish-0.0.0.dev146.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
511
- omlish-0.0.0.dev146.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
512
- omlish-0.0.0.dev146.dist-info/RECORD,,
511
+ omlish-0.0.0.dev148.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
512
+ omlish-0.0.0.dev148.dist-info/METADATA,sha256=78h6hQTFkljP4Axca6bTAYdlPCtJVukJDCFxbRrx__4,4264
513
+ omlish-0.0.0.dev148.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
514
+ omlish-0.0.0.dev148.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
515
+ omlish-0.0.0.dev148.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
516
+ omlish-0.0.0.dev148.dist-info/RECORD,,