omlish 0.0.0.dev146__py3-none-any.whl → 0.0.0.dev148__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.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,,