omdev 0.0.0.dev155__py3-none-any.whl → 0.0.0.dev156__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.

Potentially problematic release.


This version of omdev might be problematic. Click here for more details.

omdev/scripts/interp.py CHANGED
@@ -2080,209 +2080,226 @@ SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
2080
2080
  _SUBPROCESS_SHELL_WRAP_EXECS = False
2081
2081
 
2082
2082
 
2083
- def subprocess_shell_wrap_exec(*args: str) -> ta.Tuple[str, ...]:
2084
- return ('sh', '-c', ' '.join(map(shlex.quote, args)))
2083
+ def subprocess_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
2084
+ return ('sh', '-c', ' '.join(map(shlex.quote, cmd)))
2085
2085
 
2086
2086
 
2087
- def subprocess_maybe_shell_wrap_exec(*args: str) -> ta.Tuple[str, ...]:
2087
+ def subprocess_maybe_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
2088
2088
  if _SUBPROCESS_SHELL_WRAP_EXECS or is_debugger_attached():
2089
- return subprocess_shell_wrap_exec(*args)
2089
+ return subprocess_shell_wrap_exec(*cmd)
2090
2090
  else:
2091
- return args
2092
-
2093
-
2094
- def prepare_subprocess_invocation(
2095
- *args: str,
2096
- env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
2097
- extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
2098
- quiet: bool = False,
2099
- shell: bool = False,
2100
- **kwargs: ta.Any,
2101
- ) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
2102
- log.debug('prepare_subprocess_invocation: args=%r', args)
2103
- if extra_env:
2104
- log.debug('prepare_subprocess_invocation: extra_env=%r', extra_env)
2105
-
2106
- if extra_env:
2107
- env = {**(env if env is not None else os.environ), **extra_env}
2108
-
2109
- if quiet and 'stderr' not in kwargs:
2110
- if not log.isEnabledFor(logging.DEBUG):
2111
- kwargs['stderr'] = subprocess.DEVNULL
2112
-
2113
- if not shell:
2114
- args = subprocess_maybe_shell_wrap_exec(*args)
2115
-
2116
- return args, dict(
2117
- env=env,
2118
- shell=shell,
2119
- **kwargs,
2120
- )
2091
+ return cmd
2121
2092
 
2122
2093
 
2123
2094
  ##
2124
2095
 
2125
2096
 
2126
- @contextlib.contextmanager
2127
- def subprocess_common_context(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
2128
- start_time = time.time()
2129
- try:
2130
- log.debug('subprocess_common_context.try: args=%r', args)
2131
- yield
2132
-
2133
- except Exception as exc: # noqa
2134
- log.debug('subprocess_common_context.except: exc=%r', exc)
2135
- raise
2097
+ def subprocess_close(
2098
+ proc: subprocess.Popen,
2099
+ timeout: ta.Optional[float] = None,
2100
+ ) -> None:
2101
+ # TODO: terminate, sleep, kill
2102
+ if proc.stdout:
2103
+ proc.stdout.close()
2104
+ if proc.stderr:
2105
+ proc.stderr.close()
2106
+ if proc.stdin:
2107
+ proc.stdin.close()
2136
2108
 
2137
- finally:
2138
- end_time = time.time()
2139
- elapsed_s = end_time - start_time
2140
- log.debug('subprocess_common_context.finally: elapsed_s=%f args=%r', elapsed_s, args)
2109
+ proc.wait(timeout)
2141
2110
 
2142
2111
 
2143
2112
  ##
2144
2113
 
2145
2114
 
2146
- def subprocess_check_call(
2147
- *args: str,
2148
- stdout: ta.Any = sys.stderr,
2149
- **kwargs: ta.Any,
2150
- ) -> None:
2151
- args, kwargs = prepare_subprocess_invocation(*args, stdout=stdout, **kwargs)
2152
- with subprocess_common_context(*args, **kwargs):
2153
- return subprocess.check_call(args, **kwargs) # type: ignore
2115
+ class AbstractSubprocesses(abc.ABC): # noqa
2116
+ DEFAULT_LOGGER: ta.ClassVar[ta.Optional[logging.Logger]] = log
2154
2117
 
2118
+ def __init__(
2119
+ self,
2120
+ *,
2121
+ log: ta.Optional[logging.Logger] = None,
2122
+ try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
2123
+ ) -> None:
2124
+ super().__init__()
2155
2125
 
2156
- def subprocess_check_output(
2157
- *args: str,
2158
- **kwargs: ta.Any,
2159
- ) -> bytes:
2160
- args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
2161
- with subprocess_common_context(*args, **kwargs):
2162
- return subprocess.check_output(args, **kwargs)
2126
+ self._log = log if log is not None else self.DEFAULT_LOGGER
2127
+ self._try_exceptions = try_exceptions if try_exceptions is not None else self.DEFAULT_TRY_EXCEPTIONS
2163
2128
 
2129
+ #
2164
2130
 
2165
- def subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
2166
- return subprocess_check_output(*args, **kwargs).decode().strip()
2131
+ def prepare_args(
2132
+ self,
2133
+ *cmd: str,
2134
+ env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
2135
+ extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
2136
+ quiet: bool = False,
2137
+ shell: bool = False,
2138
+ **kwargs: ta.Any,
2139
+ ) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
2140
+ if self._log:
2141
+ self._log.debug('Subprocesses.prepare_args: cmd=%r', cmd)
2142
+ if extra_env:
2143
+ self._log.debug('Subprocesses.prepare_args: extra_env=%r', extra_env)
2144
+
2145
+ if extra_env:
2146
+ env = {**(env if env is not None else os.environ), **extra_env}
2147
+
2148
+ if quiet and 'stderr' not in kwargs:
2149
+ if self._log and not self._log.isEnabledFor(logging.DEBUG):
2150
+ kwargs['stderr'] = subprocess.DEVNULL
2151
+
2152
+ if not shell:
2153
+ cmd = subprocess_maybe_shell_wrap_exec(*cmd)
2154
+
2155
+ return cmd, dict(
2156
+ env=env,
2157
+ shell=shell,
2158
+ **kwargs,
2159
+ )
2167
2160
 
2161
+ @contextlib.contextmanager
2162
+ def wrap_call(self, *cmd: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
2163
+ start_time = time.time()
2164
+ try:
2165
+ if self._log:
2166
+ self._log.debug('Subprocesses.wrap_call.try: cmd=%r', cmd)
2167
+ yield
2168
2168
 
2169
- ##
2169
+ except Exception as exc: # noqa
2170
+ if self._log:
2171
+ self._log.debug('Subprocesses.wrap_call.except: exc=%r', exc)
2172
+ raise
2170
2173
 
2174
+ finally:
2175
+ end_time = time.time()
2176
+ elapsed_s = end_time - start_time
2177
+ if self._log:
2178
+ self._log.debug('sSubprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
2171
2179
 
2172
- DEFAULT_SUBPROCESS_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
2173
- FileNotFoundError,
2174
- subprocess.CalledProcessError,
2175
- )
2180
+ @contextlib.contextmanager
2181
+ def prepare_and_wrap(
2182
+ self,
2183
+ *cmd: ta.Any,
2184
+ **kwargs: ta.Any,
2185
+ ) -> ta.Iterator[ta.Tuple[
2186
+ ta.Tuple[ta.Any, ...],
2187
+ ta.Dict[str, ta.Any],
2188
+ ]]:
2189
+ cmd, kwargs = self.prepare_args(*cmd, **kwargs)
2190
+ with self.wrap_call(*cmd, **kwargs):
2191
+ yield cmd, kwargs
2176
2192
 
2193
+ #
2177
2194
 
2178
- def _subprocess_try_run(
2179
- fn: ta.Callable[..., T],
2180
- *args: ta.Any,
2181
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
2182
- **kwargs: ta.Any,
2183
- ) -> ta.Union[T, Exception]:
2184
- try:
2185
- return fn(*args, **kwargs)
2186
- except try_exceptions as e: # noqa
2187
- if log.isEnabledFor(logging.DEBUG):
2188
- log.exception('command failed')
2189
- return e
2190
-
2191
-
2192
- def subprocess_try_call(
2193
- *args: str,
2194
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
2195
- **kwargs: ta.Any,
2196
- ) -> bool:
2197
- if isinstance(_subprocess_try_run(
2198
- subprocess_check_call,
2199
- *args,
2200
- try_exceptions=try_exceptions,
2201
- **kwargs,
2202
- ), Exception):
2203
- return False
2204
- else:
2205
- return True
2195
+ DEFAULT_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
2196
+ FileNotFoundError,
2197
+ subprocess.CalledProcessError,
2198
+ )
2206
2199
 
2200
+ def try_fn(
2201
+ self,
2202
+ fn: ta.Callable[..., T],
2203
+ *cmd: str,
2204
+ try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
2205
+ **kwargs: ta.Any,
2206
+ ) -> ta.Union[T, Exception]:
2207
+ if try_exceptions is None:
2208
+ try_exceptions = self._try_exceptions
2207
2209
 
2208
- def subprocess_try_output(
2209
- *args: str,
2210
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
2211
- **kwargs: ta.Any,
2212
- ) -> ta.Optional[bytes]:
2213
- if isinstance(ret := _subprocess_try_run(
2214
- subprocess_check_output,
2215
- *args,
2216
- try_exceptions=try_exceptions,
2217
- **kwargs,
2218
- ), Exception):
2219
- return None
2220
- else:
2221
- return ret
2210
+ try:
2211
+ return fn(*cmd, **kwargs)
2212
+
2213
+ except try_exceptions as e: # noqa
2214
+ if self._log and self._log.isEnabledFor(logging.DEBUG):
2215
+ self._log.exception('command failed')
2216
+ return e
2222
2217
 
2218
+ async def async_try_fn(
2219
+ self,
2220
+ fn: ta.Callable[..., ta.Awaitable[T]],
2221
+ *cmd: ta.Any,
2222
+ try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
2223
+ **kwargs: ta.Any,
2224
+ ) -> ta.Union[T, Exception]:
2225
+ if try_exceptions is None:
2226
+ try_exceptions = self._try_exceptions
2227
+
2228
+ try:
2229
+ return await fn(*cmd, **kwargs)
2223
2230
 
2224
- def subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
2225
- out = subprocess_try_output(*args, **kwargs)
2226
- return out.decode().strip() if out is not None else None
2231
+ except try_exceptions as e: # noqa
2232
+ if self._log and self._log.isEnabledFor(logging.DEBUG):
2233
+ self._log.exception('command failed')
2234
+ return e
2227
2235
 
2228
2236
 
2229
2237
  ##
2230
2238
 
2231
2239
 
2232
- def subprocess_close(
2233
- proc: subprocess.Popen,
2234
- timeout: ta.Optional[float] = None,
2235
- ) -> None:
2236
- # TODO: terminate, sleep, kill
2237
- if proc.stdout:
2238
- proc.stdout.close()
2239
- if proc.stderr:
2240
- proc.stderr.close()
2241
- if proc.stdin:
2242
- proc.stdin.close()
2240
+ class Subprocesses(AbstractSubprocesses):
2241
+ def check_call(
2242
+ self,
2243
+ *cmd: str,
2244
+ stdout: ta.Any = sys.stderr,
2245
+ **kwargs: ta.Any,
2246
+ ) -> None:
2247
+ with self.prepare_and_wrap(*cmd, stdout=stdout, **kwargs) as (cmd, kwargs): # noqa
2248
+ subprocess.check_call(cmd, **kwargs)
2243
2249
 
2244
- proc.wait(timeout)
2250
+ def check_output(
2251
+ self,
2252
+ *cmd: str,
2253
+ **kwargs: ta.Any,
2254
+ ) -> bytes:
2255
+ with self.prepare_and_wrap(*cmd, **kwargs) as (cmd, kwargs): # noqa
2256
+ return subprocess.check_output(cmd, **kwargs)
2245
2257
 
2258
+ def check_output_str(
2259
+ self,
2260
+ *cmd: str,
2261
+ **kwargs: ta.Any,
2262
+ ) -> str:
2263
+ return self.check_output(*cmd, **kwargs).decode().strip()
2246
2264
 
2247
- ########################################
2248
- # ../../../omlish/lite/asyncio/subprocesses.py
2265
+ #
2249
2266
 
2267
+ def try_call(
2268
+ self,
2269
+ *cmd: str,
2270
+ **kwargs: ta.Any,
2271
+ ) -> bool:
2272
+ if isinstance(self.try_fn(self.check_call, *cmd, **kwargs), Exception):
2273
+ return False
2274
+ else:
2275
+ return True
2250
2276
 
2251
- ##
2277
+ def try_output(
2278
+ self,
2279
+ *cmd: str,
2280
+ **kwargs: ta.Any,
2281
+ ) -> ta.Optional[bytes]:
2282
+ if isinstance(ret := self.try_fn(self.check_output, *cmd, **kwargs), Exception):
2283
+ return None
2284
+ else:
2285
+ return ret
2252
2286
 
2287
+ def try_output_str(
2288
+ self,
2289
+ *cmd: str,
2290
+ **kwargs: ta.Any,
2291
+ ) -> ta.Optional[str]:
2292
+ if (ret := self.try_output(*cmd, **kwargs)) is None:
2293
+ return None
2294
+ else:
2295
+ return ret.decode().strip()
2253
2296
 
2254
- @contextlib.asynccontextmanager
2255
- async def asyncio_subprocess_popen(
2256
- *cmd: str,
2257
- shell: bool = False,
2258
- timeout: ta.Optional[float] = None,
2259
- **kwargs: ta.Any,
2260
- ) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
2261
- fac: ta.Any
2262
- if shell:
2263
- fac = functools.partial(
2264
- asyncio.create_subprocess_shell,
2265
- check.single(cmd),
2266
- )
2267
- else:
2268
- fac = functools.partial(
2269
- asyncio.create_subprocess_exec,
2270
- *cmd,
2271
- )
2272
2297
 
2273
- with subprocess_common_context(
2274
- *cmd,
2275
- shell=shell,
2276
- timeout=timeout,
2277
- **kwargs,
2278
- ):
2279
- proc: asyncio.subprocess.Process
2280
- proc = await fac(**kwargs)
2281
- try:
2282
- yield proc
2298
+ subprocesses = Subprocesses()
2283
2299
 
2284
- finally:
2285
- await asyncio_maybe_timeout(proc.wait(), timeout)
2300
+
2301
+ ########################################
2302
+ # ../../../omlish/lite/asyncio/subprocesses.py
2286
2303
 
2287
2304
 
2288
2305
  ##
@@ -2398,148 +2415,147 @@ class AsyncioProcessCommunicator:
2398
2415
  return await asyncio_maybe_timeout(self._communicate(input), timeout)
2399
2416
 
2400
2417
 
2401
- async def asyncio_subprocess_communicate(
2402
- proc: asyncio.subprocess.Process,
2403
- input: ta.Any = None, # noqa
2404
- timeout: ta.Optional[float] = None,
2405
- ) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
2406
- return await AsyncioProcessCommunicator(proc).communicate(input, timeout) # noqa
2407
-
2418
+ ##
2408
2419
 
2409
- @dc.dataclass(frozen=True)
2410
- class AsyncioSubprocessOutput:
2411
- proc: asyncio.subprocess.Process
2412
- stdout: ta.Optional[bytes]
2413
- stderr: ta.Optional[bytes]
2414
2420
 
2421
+ class AsyncioSubprocesses(AbstractSubprocesses):
2422
+ async def communicate(
2423
+ self,
2424
+ proc: asyncio.subprocess.Process,
2425
+ input: ta.Any = None, # noqa
2426
+ timeout: ta.Optional[float] = None,
2427
+ ) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
2428
+ return await AsyncioProcessCommunicator(proc).communicate(input, timeout) # noqa
2415
2429
 
2416
- async def asyncio_subprocess_run(
2417
- *args: str,
2418
- input: ta.Any = None, # noqa
2419
- timeout: ta.Optional[float] = None,
2420
- check: bool = False, # noqa
2421
- capture_output: ta.Optional[bool] = None,
2422
- **kwargs: ta.Any,
2423
- ) -> AsyncioSubprocessOutput:
2424
- if capture_output:
2425
- kwargs.setdefault('stdout', subprocess.PIPE)
2426
- kwargs.setdefault('stderr', subprocess.PIPE)
2427
-
2428
- args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
2429
-
2430
- proc: asyncio.subprocess.Process
2431
- async with asyncio_subprocess_popen(*args, **kwargs) as proc:
2432
- stdout, stderr = await asyncio_subprocess_communicate(proc, input, timeout)
2433
-
2434
- if check and proc.returncode:
2435
- raise subprocess.CalledProcessError(
2436
- proc.returncode,
2437
- args,
2438
- output=stdout,
2439
- stderr=stderr,
2440
- )
2430
+ #
2441
2431
 
2442
- return AsyncioSubprocessOutput(
2443
- proc,
2444
- stdout,
2445
- stderr,
2446
- )
2432
+ @contextlib.asynccontextmanager
2433
+ async def popen(
2434
+ self,
2435
+ *cmd: str,
2436
+ shell: bool = False,
2437
+ timeout: ta.Optional[float] = None,
2438
+ **kwargs: ta.Any,
2439
+ ) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
2440
+ fac: ta.Any
2441
+ if shell:
2442
+ fac = functools.partial(
2443
+ asyncio.create_subprocess_shell,
2444
+ check.single(cmd),
2445
+ )
2446
+ else:
2447
+ fac = functools.partial(
2448
+ asyncio.create_subprocess_exec,
2449
+ *cmd,
2450
+ )
2447
2451
 
2452
+ with self.prepare_and_wrap( *cmd, shell=shell, **kwargs) as (cmd, kwargs): # noqa
2453
+ proc: asyncio.subprocess.Process = await fac(**kwargs)
2454
+ try:
2455
+ yield proc
2448
2456
 
2449
- ##
2457
+ finally:
2458
+ await asyncio_maybe_timeout(proc.wait(), timeout)
2450
2459
 
2460
+ #
2451
2461
 
2452
- async def asyncio_subprocess_check_call(
2453
- *args: str,
2454
- stdout: ta.Any = sys.stderr,
2455
- input: ta.Any = None, # noqa
2456
- timeout: ta.Optional[float] = None,
2457
- **kwargs: ta.Any,
2458
- ) -> None:
2459
- await asyncio_subprocess_run(
2460
- *args,
2461
- stdout=stdout,
2462
- input=input,
2463
- timeout=timeout,
2464
- check=True,
2465
- **kwargs,
2466
- )
2462
+ @dc.dataclass(frozen=True)
2463
+ class RunOutput:
2464
+ proc: asyncio.subprocess.Process
2465
+ stdout: ta.Optional[bytes]
2466
+ stderr: ta.Optional[bytes]
2467
2467
 
2468
+ async def run(
2469
+ self,
2470
+ *cmd: str,
2471
+ input: ta.Any = None, # noqa
2472
+ timeout: ta.Optional[float] = None,
2473
+ check: bool = False, # noqa
2474
+ capture_output: ta.Optional[bool] = None,
2475
+ **kwargs: ta.Any,
2476
+ ) -> RunOutput:
2477
+ if capture_output:
2478
+ kwargs.setdefault('stdout', subprocess.PIPE)
2479
+ kwargs.setdefault('stderr', subprocess.PIPE)
2468
2480
 
2469
- async def asyncio_subprocess_check_output(
2470
- *args: str,
2471
- input: ta.Any = None, # noqa
2472
- timeout: ta.Optional[float] = None,
2473
- **kwargs: ta.Any,
2474
- ) -> bytes:
2475
- out = await asyncio_subprocess_run(
2476
- *args,
2477
- stdout=asyncio.subprocess.PIPE,
2478
- input=input,
2479
- timeout=timeout,
2480
- check=True,
2481
- **kwargs,
2482
- )
2481
+ proc: asyncio.subprocess.Process
2482
+ async with self.popen(*cmd, **kwargs) as proc:
2483
+ stdout, stderr = await self.communicate(proc, input, timeout)
2484
+
2485
+ if check and proc.returncode:
2486
+ raise subprocess.CalledProcessError(
2487
+ proc.returncode,
2488
+ cmd,
2489
+ output=stdout,
2490
+ stderr=stderr,
2491
+ )
2483
2492
 
2484
- return check.not_none(out.stdout)
2493
+ return self.RunOutput(
2494
+ proc,
2495
+ stdout,
2496
+ stderr,
2497
+ )
2485
2498
 
2499
+ #
2486
2500
 
2487
- async def asyncio_subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
2488
- return (await asyncio_subprocess_check_output(*args, **kwargs)).decode().strip()
2501
+ async def check_call(
2502
+ self,
2503
+ *cmd: str,
2504
+ stdout: ta.Any = sys.stderr,
2505
+ **kwargs: ta.Any,
2506
+ ) -> None:
2507
+ with self.prepare_and_wrap(*cmd, stdout=stdout, check=True, **kwargs) as (cmd, kwargs): # noqa
2508
+ await self.run(*cmd, **kwargs)
2489
2509
 
2510
+ async def check_output(
2511
+ self,
2512
+ *cmd: str,
2513
+ **kwargs: ta.Any,
2514
+ ) -> bytes:
2515
+ with self.prepare_and_wrap(*cmd, stdout=subprocess.PIPE, check=True, **kwargs) as (cmd, kwargs): # noqa
2516
+ return check.not_none((await self.run(*cmd, **kwargs)).stdout)
2490
2517
 
2491
- ##
2518
+ async def check_output_str(
2519
+ self,
2520
+ *cmd: str,
2521
+ **kwargs: ta.Any,
2522
+ ) -> str:
2523
+ return (await self.check_output(*cmd, **kwargs)).decode().strip()
2492
2524
 
2525
+ #
2493
2526
 
2494
- async def _asyncio_subprocess_try_run(
2495
- fn: ta.Callable[..., ta.Awaitable[T]],
2496
- *args: ta.Any,
2497
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
2498
- **kwargs: ta.Any,
2499
- ) -> ta.Union[T, Exception]:
2500
- try:
2501
- return await fn(*args, **kwargs)
2502
- except try_exceptions as e: # noqa
2503
- if log.isEnabledFor(logging.DEBUG):
2504
- log.exception('command failed')
2505
- return e
2506
-
2507
-
2508
- async def asyncio_subprocess_try_call(
2509
- *args: str,
2510
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
2511
- **kwargs: ta.Any,
2512
- ) -> bool:
2513
- if isinstance(await _asyncio_subprocess_try_run(
2514
- asyncio_subprocess_check_call,
2515
- *args,
2516
- try_exceptions=try_exceptions,
2517
- **kwargs,
2518
- ), Exception):
2519
- return False
2520
- else:
2521
- return True
2527
+ async def try_call(
2528
+ self,
2529
+ *cmd: str,
2530
+ **kwargs: ta.Any,
2531
+ ) -> bool:
2532
+ if isinstance(await self.async_try_fn(self.check_call, *cmd, **kwargs), Exception):
2533
+ return False
2534
+ else:
2535
+ return True
2522
2536
 
2537
+ async def try_output(
2538
+ self,
2539
+ *cmd: str,
2540
+ **kwargs: ta.Any,
2541
+ ) -> ta.Optional[bytes]:
2542
+ if isinstance(ret := await self.async_try_fn(self.check_output, *cmd, **kwargs), Exception):
2543
+ return None
2544
+ else:
2545
+ return ret
2523
2546
 
2524
- async def asyncio_subprocess_try_output(
2525
- *args: str,
2526
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
2527
- **kwargs: ta.Any,
2528
- ) -> ta.Optional[bytes]:
2529
- if isinstance(ret := await _asyncio_subprocess_try_run(
2530
- asyncio_subprocess_check_output,
2531
- *args,
2532
- try_exceptions=try_exceptions,
2533
- **kwargs,
2534
- ), Exception):
2535
- return None
2536
- else:
2537
- return ret
2547
+ async def try_output_str(
2548
+ self,
2549
+ *cmd: str,
2550
+ **kwargs: ta.Any,
2551
+ ) -> ta.Optional[str]:
2552
+ if (ret := await self.try_output(*cmd, **kwargs)) is None:
2553
+ return None
2554
+ else:
2555
+ return ret.decode().strip()
2538
2556
 
2539
2557
 
2540
- async def asyncio_subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
2541
- out = await asyncio_subprocess_try_output(*args, **kwargs)
2542
- return out.decode().strip() if out is not None else None
2558
+ asyncio_subprocesses = AsyncioSubprocesses()
2543
2559
 
2544
2560
 
2545
2561
  ########################################
@@ -2616,7 +2632,7 @@ class InterpInspector:
2616
2632
  return cls._build_inspection(sys.executable, eval(cls._INSPECTION_CODE)) # noqa
2617
2633
 
2618
2634
  async def _inspect(self, exe: str) -> InterpInspection:
2619
- output = await asyncio_subprocess_check_output(exe, '-c', f'print({self._INSPECTION_CODE})', quiet=True)
2635
+ output = await asyncio_subprocesses.check_output(exe, '-c', f'print({self._INSPECTION_CODE})', quiet=True)
2620
2636
  return self._build_inspection(exe, output.decode())
2621
2637
 
2622
2638
  async def inspect(self, exe: str) -> ta.Optional[InterpInspection]:
@@ -2735,7 +2751,7 @@ class Pyenv:
2735
2751
  return self._root_kw
2736
2752
 
2737
2753
  if shutil.which('pyenv'):
2738
- return await asyncio_subprocess_check_output_str('pyenv', 'root')
2754
+ return await asyncio_subprocesses.check_output_str('pyenv', 'root')
2739
2755
 
2740
2756
  d = os.path.expanduser('~/.pyenv')
2741
2757
  if os.path.isdir(d) and os.path.isfile(os.path.join(d, 'bin', 'pyenv')):
@@ -2764,7 +2780,7 @@ class Pyenv:
2764
2780
  if await self.root() is None:
2765
2781
  return []
2766
2782
  ret = []
2767
- s = await asyncio_subprocess_check_output_str(await self.exe(), 'install', '--list')
2783
+ s = await asyncio_subprocesses.check_output_str(await self.exe(), 'install', '--list')
2768
2784
  for l in s.splitlines():
2769
2785
  if not l.startswith(' '):
2770
2786
  continue
@@ -2779,7 +2795,7 @@ class Pyenv:
2779
2795
  return False
2780
2796
  if not os.path.isdir(os.path.join(root, '.git')):
2781
2797
  return False
2782
- await asyncio_subprocess_check_call('git', 'pull', cwd=root)
2798
+ await asyncio_subprocesses.check_call('git', 'pull', cwd=root)
2783
2799
  return True
2784
2800
 
2785
2801
 
@@ -2870,7 +2886,7 @@ class DarwinPyenvInstallOpts(PyenvInstallOptsProvider):
2870
2886
  cflags = []
2871
2887
  ldflags = []
2872
2888
  for dep in self.BREW_DEPS:
2873
- dep_prefix = await asyncio_subprocess_check_output_str('brew', '--prefix', dep)
2889
+ dep_prefix = await asyncio_subprocesses.check_output_str('brew', '--prefix', dep)
2874
2890
  cflags.append(f'-I{dep_prefix}/include')
2875
2891
  ldflags.append(f'-L{dep_prefix}/lib')
2876
2892
  return PyenvInstallOpts(
@@ -2880,11 +2896,11 @@ class DarwinPyenvInstallOpts(PyenvInstallOptsProvider):
2880
2896
 
2881
2897
  @async_cached_nullary
2882
2898
  async def brew_tcl_opts(self) -> PyenvInstallOpts:
2883
- if await asyncio_subprocess_try_output('brew', '--prefix', 'tcl-tk') is None:
2899
+ if await asyncio_subprocesses.try_output('brew', '--prefix', 'tcl-tk') is None:
2884
2900
  return PyenvInstallOpts()
2885
2901
 
2886
- tcl_tk_prefix = await asyncio_subprocess_check_output_str('brew', '--prefix', 'tcl-tk')
2887
- tcl_tk_ver_str = await asyncio_subprocess_check_output_str('brew', 'ls', '--versions', 'tcl-tk')
2902
+ tcl_tk_prefix = await asyncio_subprocesses.check_output_str('brew', '--prefix', 'tcl-tk')
2903
+ tcl_tk_ver_str = await asyncio_subprocesses.check_output_str('brew', 'ls', '--versions', 'tcl-tk')
2888
2904
  tcl_tk_ver = '.'.join(tcl_tk_ver_str.split()[1].split('.')[:2])
2889
2905
 
2890
2906
  return PyenvInstallOpts(conf_opts=[
@@ -3005,7 +3021,7 @@ class PyenvVersionInstaller:
3005
3021
  *conf_args,
3006
3022
  ]
3007
3023
 
3008
- await asyncio_subprocess_check_call(
3024
+ await asyncio_subprocesses.check_call(
3009
3025
  *full_args,
3010
3026
  env=env,
3011
3027
  )