ominfra 0.0.0.dev224__py3-none-any.whl → 0.0.0.dev226__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.
- ominfra/clouds/aws/journald2aws/driver.py +1 -1
- ominfra/journald/tailer.py +2 -2
- ominfra/manage/commands/subprocess.py +3 -3
- ominfra/manage/remote/spawning.py +2 -2
- ominfra/scripts/journald2aws.py +114 -487
- ominfra/scripts/manage.py +3152 -2851
- ominfra/scripts/supervisor.py +5 -139
- {ominfra-0.0.0.dev224.dist-info → ominfra-0.0.0.dev226.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev224.dist-info → ominfra-0.0.0.dev226.dist-info}/RECORD +13 -13
- {ominfra-0.0.0.dev224.dist-info → ominfra-0.0.0.dev226.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev224.dist-info → ominfra-0.0.0.dev226.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev224.dist-info → ominfra-0.0.0.dev226.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev224.dist-info → ominfra-0.0.0.dev226.dist-info}/top_level.txt +0 -0
ominfra/scripts/journald2aws.py
CHANGED
@@ -86,9 +86,6 @@ AsyncExitStackedT = ta.TypeVar('AsyncExitStackedT', bound='AsyncExitStacked')
|
|
86
86
|
# ../../../threadworkers.py
|
87
87
|
ThreadWorkerT = ta.TypeVar('ThreadWorkerT', bound='ThreadWorker')
|
88
88
|
|
89
|
-
# ../../../../omlish/subprocesses.py
|
90
|
-
SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlias
|
91
|
-
|
92
89
|
|
93
90
|
########################################
|
94
91
|
# ../../../../../omlish/configs/types.py
|
@@ -1945,42 +1942,117 @@ class ProxyLogHandler(ProxyLogFilterer, logging.Handler):
|
|
1945
1942
|
|
1946
1943
|
|
1947
1944
|
########################################
|
1948
|
-
# ../../../../../omlish/os/pidfile.py
|
1945
|
+
# ../../../../../omlish/os/pidfiles/pidfile.py
|
1946
|
+
"""
|
1947
|
+
TODO:
|
1948
|
+
- reliable pid retrieval
|
1949
|
+
- contents are *ignored*, just advisory
|
1950
|
+
- check double-check:
|
1951
|
+
- 1) get pid of flock holder
|
1952
|
+
- 2) get pidfd to that
|
1953
|
+
- 3) recheck current pid of flock holder == that pid
|
1954
|
+
- racy as to if it's a different actual process as initial check, just with same pid, but due to 'identity' / semantic
|
1955
|
+
meaning of the named pidfile the processes are considered equivalent
|
1956
|
+
- read_checked(), contextmanager
|
1957
|
+
"""
|
1958
|
+
|
1959
|
+
|
1960
|
+
##
|
1949
1961
|
|
1950
1962
|
|
1951
1963
|
class Pidfile:
|
1952
|
-
def __init__(
|
1964
|
+
def __init__(
|
1965
|
+
self,
|
1966
|
+
path: str,
|
1967
|
+
*,
|
1968
|
+
inheritable: bool = True,
|
1969
|
+
) -> None:
|
1953
1970
|
super().__init__()
|
1971
|
+
|
1954
1972
|
self._path = path
|
1973
|
+
self._inheritable = inheritable
|
1955
1974
|
|
1956
|
-
|
1975
|
+
@property
|
1976
|
+
def path(self) -> str:
|
1977
|
+
return self._path
|
1978
|
+
|
1979
|
+
@property
|
1980
|
+
def inheritable(self) -> bool:
|
1981
|
+
return self._inheritable
|
1957
1982
|
|
1958
1983
|
def __repr__(self) -> str:
|
1959
1984
|
return f'{self.__class__.__name__}({self._path!r})'
|
1960
1985
|
|
1986
|
+
#
|
1987
|
+
|
1988
|
+
_f: ta.TextIO
|
1989
|
+
|
1990
|
+
def fileno(self) -> ta.Optional[int]:
|
1991
|
+
if hasattr(self, '_f'):
|
1992
|
+
return self._f.fileno()
|
1993
|
+
else:
|
1994
|
+
return None
|
1995
|
+
|
1996
|
+
#
|
1997
|
+
|
1961
1998
|
def __enter__(self) -> 'Pidfile':
|
1962
1999
|
fd = os.open(self._path, os.O_RDWR | os.O_CREAT, 0o600)
|
2000
|
+
|
1963
2001
|
try:
|
1964
|
-
|
2002
|
+
if self._inheritable:
|
2003
|
+
os.set_inheritable(fd, True)
|
2004
|
+
|
1965
2005
|
f = os.fdopen(fd, 'r+')
|
2006
|
+
|
1966
2007
|
except Exception:
|
1967
2008
|
try:
|
1968
2009
|
os.close(fd)
|
1969
2010
|
except Exception: # noqa
|
1970
2011
|
pass
|
1971
2012
|
raise
|
2013
|
+
|
1972
2014
|
self._f = f
|
1973
2015
|
return self
|
1974
2016
|
|
1975
2017
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
2018
|
+
self.close()
|
2019
|
+
|
2020
|
+
#
|
2021
|
+
|
2022
|
+
def __getstate__(self):
|
2023
|
+
state = self.__dict__.copy()
|
2024
|
+
|
2025
|
+
if '_f' in state:
|
2026
|
+
# self._inheritable may be decoupled from actual file inheritability - for example when using the manager.
|
2027
|
+
if os.get_inheritable(fd := state.pop('_f').fileno()):
|
2028
|
+
state['__fd'] = fd
|
2029
|
+
|
2030
|
+
return state
|
2031
|
+
|
2032
|
+
def __setstate__(self, state):
|
2033
|
+
if '_f' in state:
|
2034
|
+
raise RuntimeError
|
2035
|
+
|
2036
|
+
if '__fd' in state:
|
2037
|
+
state['_f'] = os.fdopen(state.pop('__fd'), 'r+')
|
2038
|
+
|
2039
|
+
self.__dict__.update(state)
|
2040
|
+
|
2041
|
+
#
|
2042
|
+
|
2043
|
+
def close(self) -> bool:
|
2044
|
+
if not hasattr(self, '_f'):
|
2045
|
+
return False
|
2046
|
+
|
2047
|
+
self._f.close()
|
2048
|
+
del self._f
|
2049
|
+
return True
|
1979
2050
|
|
1980
2051
|
def try_lock(self) -> bool:
|
1981
2052
|
try:
|
1982
2053
|
fcntl.flock(self._f, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
1983
2054
|
return True
|
2055
|
+
|
1984
2056
|
except OSError:
|
1985
2057
|
return False
|
1986
2058
|
|
@@ -1988,27 +2060,57 @@ class Pidfile:
|
|
1988
2060
|
if not self.try_lock():
|
1989
2061
|
raise RuntimeError('Could not get lock')
|
1990
2062
|
|
2063
|
+
#
|
2064
|
+
|
1991
2065
|
def write(self, pid: ta.Optional[int] = None) -> None:
|
1992
2066
|
self.ensure_locked()
|
2067
|
+
|
1993
2068
|
if pid is None:
|
1994
2069
|
pid = os.getpid()
|
2070
|
+
|
2071
|
+
self._f.seek(0)
|
2072
|
+
self._f.truncate()
|
1995
2073
|
self._f.write(f'{pid}\n')
|
1996
2074
|
self._f.flush()
|
1997
2075
|
|
1998
2076
|
def clear(self) -> None:
|
1999
2077
|
self.ensure_locked()
|
2078
|
+
|
2000
2079
|
self._f.seek(0)
|
2001
2080
|
self._f.truncate()
|
2002
2081
|
|
2003
2082
|
def read(self) -> int:
|
2004
2083
|
if self.try_lock():
|
2005
2084
|
raise RuntimeError('Got lock')
|
2085
|
+
|
2006
2086
|
self._f.seek(0)
|
2007
2087
|
return int(self._f.read())
|
2008
2088
|
|
2009
2089
|
def kill(self, sig: int = signal.SIGTERM) -> None:
|
2010
2090
|
pid = self.read()
|
2011
|
-
os.kill(pid, sig)
|
2091
|
+
os.kill(pid, sig)
|
2092
|
+
|
2093
|
+
|
2094
|
+
########################################
|
2095
|
+
# ../../../../../omlish/subprocesses/utils.py
|
2096
|
+
|
2097
|
+
|
2098
|
+
##
|
2099
|
+
|
2100
|
+
|
2101
|
+
def subprocess_close(
|
2102
|
+
proc: subprocess.Popen,
|
2103
|
+
timeout: ta.Optional[float] = None,
|
2104
|
+
) -> None:
|
2105
|
+
# TODO: terminate, sleep, kill
|
2106
|
+
if proc.stdout:
|
2107
|
+
proc.stdout.close()
|
2108
|
+
if proc.stderr:
|
2109
|
+
proc.stderr.close()
|
2110
|
+
if proc.stdin:
|
2111
|
+
proc.stdin.close()
|
2112
|
+
|
2113
|
+
proc.wait(timeout)
|
2012
2114
|
|
2013
2115
|
|
2014
2116
|
########################################
|
@@ -4245,23 +4347,7 @@ def configure_standard_logging(
|
|
4245
4347
|
|
4246
4348
|
|
4247
4349
|
########################################
|
4248
|
-
# ../../../../../omlish/subprocesses.py
|
4249
|
-
|
4250
|
-
|
4251
|
-
##
|
4252
|
-
|
4253
|
-
|
4254
|
-
# Valid channel type kwarg values:
|
4255
|
-
# - A special flag negative int
|
4256
|
-
# - A positive fd int
|
4257
|
-
# - A file-like object
|
4258
|
-
# - None
|
4259
|
-
|
4260
|
-
SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
|
4261
|
-
'pipe': subprocess.PIPE,
|
4262
|
-
'stdout': subprocess.STDOUT,
|
4263
|
-
'devnull': subprocess.DEVNULL,
|
4264
|
-
}
|
4350
|
+
# ../../../../../omlish/subprocesses/wrap.py
|
4265
4351
|
|
4266
4352
|
|
4267
4353
|
##
|
@@ -4281,465 +4367,6 @@ def subprocess_maybe_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
|
|
4281
4367
|
return cmd
|
4282
4368
|
|
4283
4369
|
|
4284
|
-
##
|
4285
|
-
|
4286
|
-
|
4287
|
-
def subprocess_close(
|
4288
|
-
proc: subprocess.Popen,
|
4289
|
-
timeout: ta.Optional[float] = None,
|
4290
|
-
) -> None:
|
4291
|
-
# TODO: terminate, sleep, kill
|
4292
|
-
if proc.stdout:
|
4293
|
-
proc.stdout.close()
|
4294
|
-
if proc.stderr:
|
4295
|
-
proc.stderr.close()
|
4296
|
-
if proc.stdin:
|
4297
|
-
proc.stdin.close()
|
4298
|
-
|
4299
|
-
proc.wait(timeout)
|
4300
|
-
|
4301
|
-
|
4302
|
-
##
|
4303
|
-
|
4304
|
-
|
4305
|
-
class VerboseCalledProcessError(subprocess.CalledProcessError):
|
4306
|
-
@classmethod
|
4307
|
-
def from_std(cls, e: subprocess.CalledProcessError) -> 'VerboseCalledProcessError':
|
4308
|
-
return cls(
|
4309
|
-
e.returncode,
|
4310
|
-
e.cmd,
|
4311
|
-
output=e.output,
|
4312
|
-
stderr=e.stderr,
|
4313
|
-
)
|
4314
|
-
|
4315
|
-
def __str__(self) -> str:
|
4316
|
-
msg = super().__str__()
|
4317
|
-
if self.output is not None:
|
4318
|
-
msg += f' Output: {self.output!r}'
|
4319
|
-
if self.stderr is not None:
|
4320
|
-
msg += f' Stderr: {self.stderr!r}'
|
4321
|
-
return msg
|
4322
|
-
|
4323
|
-
|
4324
|
-
class BaseSubprocesses(abc.ABC): # noqa
|
4325
|
-
DEFAULT_LOGGER: ta.ClassVar[ta.Optional[logging.Logger]] = None
|
4326
|
-
|
4327
|
-
def __init__(
|
4328
|
-
self,
|
4329
|
-
*,
|
4330
|
-
log: ta.Optional[logging.Logger] = None,
|
4331
|
-
try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
|
4332
|
-
) -> None:
|
4333
|
-
super().__init__()
|
4334
|
-
|
4335
|
-
self._log = log if log is not None else self.DEFAULT_LOGGER
|
4336
|
-
self._try_exceptions = try_exceptions if try_exceptions is not None else self.DEFAULT_TRY_EXCEPTIONS
|
4337
|
-
|
4338
|
-
def set_logger(self, log: ta.Optional[logging.Logger]) -> None:
|
4339
|
-
self._log = log
|
4340
|
-
|
4341
|
-
#
|
4342
|
-
|
4343
|
-
def prepare_args(
|
4344
|
-
self,
|
4345
|
-
*cmd: str,
|
4346
|
-
env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
|
4347
|
-
extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
|
4348
|
-
quiet: bool = False,
|
4349
|
-
shell: bool = False,
|
4350
|
-
**kwargs: ta.Any,
|
4351
|
-
) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
|
4352
|
-
if self._log:
|
4353
|
-
self._log.debug('Subprocesses.prepare_args: cmd=%r', cmd)
|
4354
|
-
if extra_env:
|
4355
|
-
self._log.debug('Subprocesses.prepare_args: extra_env=%r', extra_env)
|
4356
|
-
|
4357
|
-
#
|
4358
|
-
|
4359
|
-
if extra_env:
|
4360
|
-
env = {**(env if env is not None else os.environ), **extra_env}
|
4361
|
-
|
4362
|
-
#
|
4363
|
-
|
4364
|
-
if quiet and 'stderr' not in kwargs:
|
4365
|
-
if self._log and not self._log.isEnabledFor(logging.DEBUG):
|
4366
|
-
kwargs['stderr'] = subprocess.DEVNULL
|
4367
|
-
|
4368
|
-
for chk in ('stdout', 'stderr'):
|
4369
|
-
try:
|
4370
|
-
chv = kwargs[chk]
|
4371
|
-
except KeyError:
|
4372
|
-
continue
|
4373
|
-
kwargs[chk] = SUBPROCESS_CHANNEL_OPTION_VALUES.get(chv, chv)
|
4374
|
-
|
4375
|
-
#
|
4376
|
-
|
4377
|
-
if not shell:
|
4378
|
-
cmd = subprocess_maybe_shell_wrap_exec(*cmd)
|
4379
|
-
|
4380
|
-
#
|
4381
|
-
|
4382
|
-
return cmd, dict(
|
4383
|
-
env=env,
|
4384
|
-
shell=shell,
|
4385
|
-
**kwargs,
|
4386
|
-
)
|
4387
|
-
|
4388
|
-
@contextlib.contextmanager
|
4389
|
-
def wrap_call(
|
4390
|
-
self,
|
4391
|
-
*cmd: ta.Any,
|
4392
|
-
raise_verbose: bool = False,
|
4393
|
-
**kwargs: ta.Any,
|
4394
|
-
) -> ta.Iterator[None]:
|
4395
|
-
start_time = time.time()
|
4396
|
-
try:
|
4397
|
-
if self._log:
|
4398
|
-
self._log.debug('Subprocesses.wrap_call.try: cmd=%r', cmd)
|
4399
|
-
|
4400
|
-
yield
|
4401
|
-
|
4402
|
-
except Exception as exc: # noqa
|
4403
|
-
if self._log:
|
4404
|
-
self._log.debug('Subprocesses.wrap_call.except: exc=%r', exc)
|
4405
|
-
|
4406
|
-
if (
|
4407
|
-
raise_verbose and
|
4408
|
-
isinstance(exc, subprocess.CalledProcessError) and
|
4409
|
-
not isinstance(exc, VerboseCalledProcessError) and
|
4410
|
-
(exc.output is not None or exc.stderr is not None)
|
4411
|
-
):
|
4412
|
-
raise VerboseCalledProcessError.from_std(exc) from exc
|
4413
|
-
|
4414
|
-
raise
|
4415
|
-
|
4416
|
-
finally:
|
4417
|
-
end_time = time.time()
|
4418
|
-
elapsed_s = end_time - start_time
|
4419
|
-
|
4420
|
-
if self._log:
|
4421
|
-
self._log.debug('Subprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
|
4422
|
-
|
4423
|
-
@contextlib.contextmanager
|
4424
|
-
def prepare_and_wrap(
|
4425
|
-
self,
|
4426
|
-
*cmd: ta.Any,
|
4427
|
-
raise_verbose: bool = False,
|
4428
|
-
**kwargs: ta.Any,
|
4429
|
-
) -> ta.Iterator[ta.Tuple[
|
4430
|
-
ta.Tuple[ta.Any, ...],
|
4431
|
-
ta.Dict[str, ta.Any],
|
4432
|
-
]]:
|
4433
|
-
cmd, kwargs = self.prepare_args(*cmd, **kwargs)
|
4434
|
-
|
4435
|
-
with self.wrap_call(
|
4436
|
-
*cmd,
|
4437
|
-
raise_verbose=raise_verbose,
|
4438
|
-
**kwargs,
|
4439
|
-
):
|
4440
|
-
yield cmd, kwargs
|
4441
|
-
|
4442
|
-
#
|
4443
|
-
|
4444
|
-
DEFAULT_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
|
4445
|
-
FileNotFoundError,
|
4446
|
-
subprocess.CalledProcessError,
|
4447
|
-
)
|
4448
|
-
|
4449
|
-
def try_fn(
|
4450
|
-
self,
|
4451
|
-
fn: ta.Callable[..., T],
|
4452
|
-
*cmd: str,
|
4453
|
-
try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
|
4454
|
-
**kwargs: ta.Any,
|
4455
|
-
) -> ta.Union[T, Exception]:
|
4456
|
-
if try_exceptions is None:
|
4457
|
-
try_exceptions = self._try_exceptions
|
4458
|
-
|
4459
|
-
try:
|
4460
|
-
return fn(*cmd, **kwargs)
|
4461
|
-
|
4462
|
-
except try_exceptions as e: # noqa
|
4463
|
-
if self._log and self._log.isEnabledFor(logging.DEBUG):
|
4464
|
-
self._log.exception('command failed')
|
4465
|
-
return e
|
4466
|
-
|
4467
|
-
async def async_try_fn(
|
4468
|
-
self,
|
4469
|
-
fn: ta.Callable[..., ta.Awaitable[T]],
|
4470
|
-
*cmd: ta.Any,
|
4471
|
-
try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
|
4472
|
-
**kwargs: ta.Any,
|
4473
|
-
) -> ta.Union[T, Exception]:
|
4474
|
-
if try_exceptions is None:
|
4475
|
-
try_exceptions = self._try_exceptions
|
4476
|
-
|
4477
|
-
try:
|
4478
|
-
return await fn(*cmd, **kwargs)
|
4479
|
-
|
4480
|
-
except try_exceptions as e: # noqa
|
4481
|
-
if self._log and self._log.isEnabledFor(logging.DEBUG):
|
4482
|
-
self._log.exception('command failed')
|
4483
|
-
return e
|
4484
|
-
|
4485
|
-
|
4486
|
-
##
|
4487
|
-
|
4488
|
-
|
4489
|
-
@dc.dataclass(frozen=True)
|
4490
|
-
class SubprocessRun:
|
4491
|
-
cmd: ta.Sequence[str]
|
4492
|
-
input: ta.Any = None
|
4493
|
-
timeout: ta.Optional[float] = None
|
4494
|
-
check: bool = False
|
4495
|
-
capture_output: ta.Optional[bool] = None
|
4496
|
-
kwargs: ta.Optional[ta.Mapping[str, ta.Any]] = None
|
4497
|
-
|
4498
|
-
@classmethod
|
4499
|
-
def of(
|
4500
|
-
cls,
|
4501
|
-
*cmd: str,
|
4502
|
-
input: ta.Any = None, # noqa
|
4503
|
-
timeout: ta.Optional[float] = None,
|
4504
|
-
check: bool = False,
|
4505
|
-
capture_output: ta.Optional[bool] = None,
|
4506
|
-
**kwargs: ta.Any,
|
4507
|
-
) -> 'SubprocessRun':
|
4508
|
-
return cls(
|
4509
|
-
cmd=cmd,
|
4510
|
-
input=input,
|
4511
|
-
timeout=timeout,
|
4512
|
-
check=check,
|
4513
|
-
capture_output=capture_output,
|
4514
|
-
kwargs=kwargs,
|
4515
|
-
)
|
4516
|
-
|
4517
|
-
|
4518
|
-
@dc.dataclass(frozen=True)
|
4519
|
-
class SubprocessRunOutput(ta.Generic[T]):
|
4520
|
-
proc: T
|
4521
|
-
|
4522
|
-
returncode: int # noqa
|
4523
|
-
|
4524
|
-
stdout: ta.Optional[bytes] = None
|
4525
|
-
stderr: ta.Optional[bytes] = None
|
4526
|
-
|
4527
|
-
|
4528
|
-
class AbstractSubprocesses(BaseSubprocesses, abc.ABC):
|
4529
|
-
@abc.abstractmethod
|
4530
|
-
def run_(self, run: SubprocessRun) -> SubprocessRunOutput:
|
4531
|
-
raise NotImplementedError
|
4532
|
-
|
4533
|
-
def run(
|
4534
|
-
self,
|
4535
|
-
*cmd: str,
|
4536
|
-
input: ta.Any = None, # noqa
|
4537
|
-
timeout: ta.Optional[float] = None,
|
4538
|
-
check: bool = False,
|
4539
|
-
capture_output: ta.Optional[bool] = None,
|
4540
|
-
**kwargs: ta.Any,
|
4541
|
-
) -> SubprocessRunOutput:
|
4542
|
-
return self.run_(SubprocessRun(
|
4543
|
-
cmd=cmd,
|
4544
|
-
input=input,
|
4545
|
-
timeout=timeout,
|
4546
|
-
check=check,
|
4547
|
-
capture_output=capture_output,
|
4548
|
-
kwargs=kwargs,
|
4549
|
-
))
|
4550
|
-
|
4551
|
-
#
|
4552
|
-
|
4553
|
-
@abc.abstractmethod
|
4554
|
-
def check_call(
|
4555
|
-
self,
|
4556
|
-
*cmd: str,
|
4557
|
-
stdout: ta.Any = sys.stderr,
|
4558
|
-
**kwargs: ta.Any,
|
4559
|
-
) -> None:
|
4560
|
-
raise NotImplementedError
|
4561
|
-
|
4562
|
-
@abc.abstractmethod
|
4563
|
-
def check_output(
|
4564
|
-
self,
|
4565
|
-
*cmd: str,
|
4566
|
-
**kwargs: ta.Any,
|
4567
|
-
) -> bytes:
|
4568
|
-
raise NotImplementedError
|
4569
|
-
|
4570
|
-
#
|
4571
|
-
|
4572
|
-
def check_output_str(
|
4573
|
-
self,
|
4574
|
-
*cmd: str,
|
4575
|
-
**kwargs: ta.Any,
|
4576
|
-
) -> str:
|
4577
|
-
return self.check_output(*cmd, **kwargs).decode().strip()
|
4578
|
-
|
4579
|
-
#
|
4580
|
-
|
4581
|
-
def try_call(
|
4582
|
-
self,
|
4583
|
-
*cmd: str,
|
4584
|
-
**kwargs: ta.Any,
|
4585
|
-
) -> bool:
|
4586
|
-
if isinstance(self.try_fn(self.check_call, *cmd, **kwargs), Exception):
|
4587
|
-
return False
|
4588
|
-
else:
|
4589
|
-
return True
|
4590
|
-
|
4591
|
-
def try_output(
|
4592
|
-
self,
|
4593
|
-
*cmd: str,
|
4594
|
-
**kwargs: ta.Any,
|
4595
|
-
) -> ta.Optional[bytes]:
|
4596
|
-
if isinstance(ret := self.try_fn(self.check_output, *cmd, **kwargs), Exception):
|
4597
|
-
return None
|
4598
|
-
else:
|
4599
|
-
return ret
|
4600
|
-
|
4601
|
-
def try_output_str(
|
4602
|
-
self,
|
4603
|
-
*cmd: str,
|
4604
|
-
**kwargs: ta.Any,
|
4605
|
-
) -> ta.Optional[str]:
|
4606
|
-
if (ret := self.try_output(*cmd, **kwargs)) is None:
|
4607
|
-
return None
|
4608
|
-
else:
|
4609
|
-
return ret.decode().strip()
|
4610
|
-
|
4611
|
-
|
4612
|
-
##
|
4613
|
-
|
4614
|
-
|
4615
|
-
class Subprocesses(AbstractSubprocesses):
|
4616
|
-
def run_(self, run: SubprocessRun) -> SubprocessRunOutput[subprocess.CompletedProcess]:
|
4617
|
-
proc = subprocess.run(
|
4618
|
-
run.cmd,
|
4619
|
-
input=run.input,
|
4620
|
-
timeout=run.timeout,
|
4621
|
-
check=run.check,
|
4622
|
-
capture_output=run.capture_output or False,
|
4623
|
-
**(run.kwargs or {}),
|
4624
|
-
)
|
4625
|
-
|
4626
|
-
return SubprocessRunOutput(
|
4627
|
-
proc=proc,
|
4628
|
-
|
4629
|
-
returncode=proc.returncode,
|
4630
|
-
|
4631
|
-
stdout=proc.stdout, # noqa
|
4632
|
-
stderr=proc.stderr, # noqa
|
4633
|
-
)
|
4634
|
-
|
4635
|
-
def check_call(
|
4636
|
-
self,
|
4637
|
-
*cmd: str,
|
4638
|
-
stdout: ta.Any = sys.stderr,
|
4639
|
-
**kwargs: ta.Any,
|
4640
|
-
) -> None:
|
4641
|
-
with self.prepare_and_wrap(*cmd, stdout=stdout, **kwargs) as (cmd, kwargs): # noqa
|
4642
|
-
subprocess.check_call(cmd, **kwargs)
|
4643
|
-
|
4644
|
-
def check_output(
|
4645
|
-
self,
|
4646
|
-
*cmd: str,
|
4647
|
-
**kwargs: ta.Any,
|
4648
|
-
) -> bytes:
|
4649
|
-
with self.prepare_and_wrap(*cmd, **kwargs) as (cmd, kwargs): # noqa
|
4650
|
-
return subprocess.check_output(cmd, **kwargs)
|
4651
|
-
|
4652
|
-
|
4653
|
-
subprocesses = Subprocesses()
|
4654
|
-
|
4655
|
-
|
4656
|
-
##
|
4657
|
-
|
4658
|
-
|
4659
|
-
class AbstractAsyncSubprocesses(BaseSubprocesses):
|
4660
|
-
@abc.abstractmethod
|
4661
|
-
async def run_(self, run: SubprocessRun) -> SubprocessRunOutput:
|
4662
|
-
raise NotImplementedError
|
4663
|
-
|
4664
|
-
def run(
|
4665
|
-
self,
|
4666
|
-
*cmd: str,
|
4667
|
-
input: ta.Any = None, # noqa
|
4668
|
-
timeout: ta.Optional[float] = None,
|
4669
|
-
check: bool = False,
|
4670
|
-
capture_output: ta.Optional[bool] = None,
|
4671
|
-
**kwargs: ta.Any,
|
4672
|
-
) -> ta.Awaitable[SubprocessRunOutput]:
|
4673
|
-
return self.run_(SubprocessRun(
|
4674
|
-
cmd=cmd,
|
4675
|
-
input=input,
|
4676
|
-
timeout=timeout,
|
4677
|
-
check=check,
|
4678
|
-
capture_output=capture_output,
|
4679
|
-
kwargs=kwargs,
|
4680
|
-
))
|
4681
|
-
|
4682
|
-
#
|
4683
|
-
|
4684
|
-
@abc.abstractmethod
|
4685
|
-
async def check_call(
|
4686
|
-
self,
|
4687
|
-
*cmd: str,
|
4688
|
-
stdout: ta.Any = sys.stderr,
|
4689
|
-
**kwargs: ta.Any,
|
4690
|
-
) -> None:
|
4691
|
-
raise NotImplementedError
|
4692
|
-
|
4693
|
-
@abc.abstractmethod
|
4694
|
-
async def check_output(
|
4695
|
-
self,
|
4696
|
-
*cmd: str,
|
4697
|
-
**kwargs: ta.Any,
|
4698
|
-
) -> bytes:
|
4699
|
-
raise NotImplementedError
|
4700
|
-
|
4701
|
-
#
|
4702
|
-
|
4703
|
-
async def check_output_str(
|
4704
|
-
self,
|
4705
|
-
*cmd: str,
|
4706
|
-
**kwargs: ta.Any,
|
4707
|
-
) -> str:
|
4708
|
-
return (await self.check_output(*cmd, **kwargs)).decode().strip()
|
4709
|
-
|
4710
|
-
#
|
4711
|
-
|
4712
|
-
async def try_call(
|
4713
|
-
self,
|
4714
|
-
*cmd: str,
|
4715
|
-
**kwargs: ta.Any,
|
4716
|
-
) -> bool:
|
4717
|
-
if isinstance(await self.async_try_fn(self.check_call, *cmd, **kwargs), Exception):
|
4718
|
-
return False
|
4719
|
-
else:
|
4720
|
-
return True
|
4721
|
-
|
4722
|
-
async def try_output(
|
4723
|
-
self,
|
4724
|
-
*cmd: str,
|
4725
|
-
**kwargs: ta.Any,
|
4726
|
-
) -> ta.Optional[bytes]:
|
4727
|
-
if isinstance(ret := await self.async_try_fn(self.check_output, *cmd, **kwargs), Exception):
|
4728
|
-
return None
|
4729
|
-
else:
|
4730
|
-
return ret
|
4731
|
-
|
4732
|
-
async def try_output_str(
|
4733
|
-
self,
|
4734
|
-
*cmd: str,
|
4735
|
-
**kwargs: ta.Any,
|
4736
|
-
) -> ta.Optional[str]:
|
4737
|
-
if (ret := await self.try_output(*cmd, **kwargs)) is None:
|
4738
|
-
return None
|
4739
|
-
else:
|
4740
|
-
return ret.decode().strip()
|
4741
|
-
|
4742
|
-
|
4743
4370
|
########################################
|
4744
4371
|
# ../poster.py
|
4745
4372
|
"""
|