ominfra 0.0.0.dev216__py3-none-any.whl → 0.0.0.dev217__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.
@@ -4235,6 +4235,12 @@ def configure_standard_logging(
4235
4235
  ##
4236
4236
 
4237
4237
 
4238
+ # Valid channel type kwarg values:
4239
+ # - A special flag negative int
4240
+ # - A positive fd int
4241
+ # - A file-like object
4242
+ # - None
4243
+
4238
4244
  SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
4239
4245
  'pipe': subprocess.PIPE,
4240
4246
  'stdout': subprocess.STDOUT,
@@ -4280,6 +4286,25 @@ def subprocess_close(
4280
4286
  ##
4281
4287
 
4282
4288
 
4289
+ class VerboseCalledProcessError(subprocess.CalledProcessError):
4290
+ @classmethod
4291
+ def from_std(cls, e: subprocess.CalledProcessError) -> 'VerboseCalledProcessError':
4292
+ return cls(
4293
+ e.returncode,
4294
+ e.cmd,
4295
+ output=e.output,
4296
+ stderr=e.stderr,
4297
+ )
4298
+
4299
+ def __str__(self) -> str:
4300
+ msg = super().__str__()
4301
+ if self.output is not None:
4302
+ msg += f' Output: {self.output!r}'
4303
+ if self.stderr is not None:
4304
+ msg += f' Stderr: {self.stderr!r}'
4305
+ return msg
4306
+
4307
+
4283
4308
  class BaseSubprocesses(abc.ABC): # noqa
4284
4309
  DEFAULT_LOGGER: ta.ClassVar[ta.Optional[logging.Logger]] = None
4285
4310
 
@@ -4313,16 +4338,31 @@ class BaseSubprocesses(abc.ABC): # noqa
4313
4338
  if extra_env:
4314
4339
  self._log.debug('Subprocesses.prepare_args: extra_env=%r', extra_env)
4315
4340
 
4341
+ #
4342
+
4316
4343
  if extra_env:
4317
4344
  env = {**(env if env is not None else os.environ), **extra_env}
4318
4345
 
4346
+ #
4347
+
4319
4348
  if quiet and 'stderr' not in kwargs:
4320
4349
  if self._log and not self._log.isEnabledFor(logging.DEBUG):
4321
4350
  kwargs['stderr'] = subprocess.DEVNULL
4322
4351
 
4352
+ for chk in ('stdout', 'stderr'):
4353
+ try:
4354
+ chv = kwargs[chk]
4355
+ except KeyError:
4356
+ continue
4357
+ kwargs[chk] = SUBPROCESS_CHANNEL_OPTION_VALUES.get(chv, chv)
4358
+
4359
+ #
4360
+
4323
4361
  if not shell:
4324
4362
  cmd = subprocess_maybe_shell_wrap_exec(*cmd)
4325
4363
 
4364
+ #
4365
+
4326
4366
  return cmd, dict(
4327
4367
  env=env,
4328
4368
  shell=shell,
@@ -4330,35 +4370,57 @@ class BaseSubprocesses(abc.ABC): # noqa
4330
4370
  )
4331
4371
 
4332
4372
  @contextlib.contextmanager
4333
- def wrap_call(self, *cmd: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
4373
+ def wrap_call(
4374
+ self,
4375
+ *cmd: ta.Any,
4376
+ raise_verbose: bool = False,
4377
+ **kwargs: ta.Any,
4378
+ ) -> ta.Iterator[None]:
4334
4379
  start_time = time.time()
4335
4380
  try:
4336
4381
  if self._log:
4337
4382
  self._log.debug('Subprocesses.wrap_call.try: cmd=%r', cmd)
4383
+
4338
4384
  yield
4339
4385
 
4340
4386
  except Exception as exc: # noqa
4341
4387
  if self._log:
4342
4388
  self._log.debug('Subprocesses.wrap_call.except: exc=%r', exc)
4389
+
4390
+ if (
4391
+ raise_verbose and
4392
+ isinstance(exc, subprocess.CalledProcessError) and
4393
+ not isinstance(exc, VerboseCalledProcessError) and
4394
+ (exc.output is not None or exc.stderr is not None)
4395
+ ):
4396
+ raise VerboseCalledProcessError.from_std(exc) from exc
4397
+
4343
4398
  raise
4344
4399
 
4345
4400
  finally:
4346
4401
  end_time = time.time()
4347
4402
  elapsed_s = end_time - start_time
4403
+
4348
4404
  if self._log:
4349
- self._log.debug('sSubprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
4405
+ self._log.debug('Subprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
4350
4406
 
4351
4407
  @contextlib.contextmanager
4352
4408
  def prepare_and_wrap(
4353
4409
  self,
4354
4410
  *cmd: ta.Any,
4411
+ raise_verbose: bool = False,
4355
4412
  **kwargs: ta.Any,
4356
4413
  ) -> ta.Iterator[ta.Tuple[
4357
4414
  ta.Tuple[ta.Any, ...],
4358
4415
  ta.Dict[str, ta.Any],
4359
4416
  ]]:
4360
4417
  cmd, kwargs = self.prepare_args(*cmd, **kwargs)
4361
- with self.wrap_call(*cmd, **kwargs):
4418
+
4419
+ with self.wrap_call(
4420
+ *cmd,
4421
+ raise_verbose=raise_verbose,
4422
+ **kwargs,
4423
+ ):
4362
4424
  yield cmd, kwargs
4363
4425
 
4364
4426
  #
ominfra/scripts/manage.py CHANGED
@@ -8172,6 +8172,12 @@ def configure_standard_logging(
8172
8172
  ##
8173
8173
 
8174
8174
 
8175
+ # Valid channel type kwarg values:
8176
+ # - A special flag negative int
8177
+ # - A positive fd int
8178
+ # - A file-like object
8179
+ # - None
8180
+
8175
8181
  SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
8176
8182
  'pipe': subprocess.PIPE,
8177
8183
  'stdout': subprocess.STDOUT,
@@ -8217,6 +8223,25 @@ def subprocess_close(
8217
8223
  ##
8218
8224
 
8219
8225
 
8226
+ class VerboseCalledProcessError(subprocess.CalledProcessError):
8227
+ @classmethod
8228
+ def from_std(cls, e: subprocess.CalledProcessError) -> 'VerboseCalledProcessError':
8229
+ return cls(
8230
+ e.returncode,
8231
+ e.cmd,
8232
+ output=e.output,
8233
+ stderr=e.stderr,
8234
+ )
8235
+
8236
+ def __str__(self) -> str:
8237
+ msg = super().__str__()
8238
+ if self.output is not None:
8239
+ msg += f' Output: {self.output!r}'
8240
+ if self.stderr is not None:
8241
+ msg += f' Stderr: {self.stderr!r}'
8242
+ return msg
8243
+
8244
+
8220
8245
  class BaseSubprocesses(abc.ABC): # noqa
8221
8246
  DEFAULT_LOGGER: ta.ClassVar[ta.Optional[logging.Logger]] = None
8222
8247
 
@@ -8250,16 +8275,31 @@ class BaseSubprocesses(abc.ABC): # noqa
8250
8275
  if extra_env:
8251
8276
  self._log.debug('Subprocesses.prepare_args: extra_env=%r', extra_env)
8252
8277
 
8278
+ #
8279
+
8253
8280
  if extra_env:
8254
8281
  env = {**(env if env is not None else os.environ), **extra_env}
8255
8282
 
8283
+ #
8284
+
8256
8285
  if quiet and 'stderr' not in kwargs:
8257
8286
  if self._log and not self._log.isEnabledFor(logging.DEBUG):
8258
8287
  kwargs['stderr'] = subprocess.DEVNULL
8259
8288
 
8289
+ for chk in ('stdout', 'stderr'):
8290
+ try:
8291
+ chv = kwargs[chk]
8292
+ except KeyError:
8293
+ continue
8294
+ kwargs[chk] = SUBPROCESS_CHANNEL_OPTION_VALUES.get(chv, chv)
8295
+
8296
+ #
8297
+
8260
8298
  if not shell:
8261
8299
  cmd = subprocess_maybe_shell_wrap_exec(*cmd)
8262
8300
 
8301
+ #
8302
+
8263
8303
  return cmd, dict(
8264
8304
  env=env,
8265
8305
  shell=shell,
@@ -8267,35 +8307,57 @@ class BaseSubprocesses(abc.ABC): # noqa
8267
8307
  )
8268
8308
 
8269
8309
  @contextlib.contextmanager
8270
- def wrap_call(self, *cmd: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
8310
+ def wrap_call(
8311
+ self,
8312
+ *cmd: ta.Any,
8313
+ raise_verbose: bool = False,
8314
+ **kwargs: ta.Any,
8315
+ ) -> ta.Iterator[None]:
8271
8316
  start_time = time.time()
8272
8317
  try:
8273
8318
  if self._log:
8274
8319
  self._log.debug('Subprocesses.wrap_call.try: cmd=%r', cmd)
8320
+
8275
8321
  yield
8276
8322
 
8277
8323
  except Exception as exc: # noqa
8278
8324
  if self._log:
8279
8325
  self._log.debug('Subprocesses.wrap_call.except: exc=%r', exc)
8326
+
8327
+ if (
8328
+ raise_verbose and
8329
+ isinstance(exc, subprocess.CalledProcessError) and
8330
+ not isinstance(exc, VerboseCalledProcessError) and
8331
+ (exc.output is not None or exc.stderr is not None)
8332
+ ):
8333
+ raise VerboseCalledProcessError.from_std(exc) from exc
8334
+
8280
8335
  raise
8281
8336
 
8282
8337
  finally:
8283
8338
  end_time = time.time()
8284
8339
  elapsed_s = end_time - start_time
8340
+
8285
8341
  if self._log:
8286
- self._log.debug('sSubprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
8342
+ self._log.debug('Subprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
8287
8343
 
8288
8344
  @contextlib.contextmanager
8289
8345
  def prepare_and_wrap(
8290
8346
  self,
8291
8347
  *cmd: ta.Any,
8348
+ raise_verbose: bool = False,
8292
8349
  **kwargs: ta.Any,
8293
8350
  ) -> ta.Iterator[ta.Tuple[
8294
8351
  ta.Tuple[ta.Any, ...],
8295
8352
  ta.Dict[str, ta.Any],
8296
8353
  ]]:
8297
8354
  cmd, kwargs = self.prepare_args(*cmd, **kwargs)
8298
- with self.wrap_call(*cmd, **kwargs):
8355
+
8356
+ with self.wrap_call(
8357
+ *cmd,
8358
+ raise_verbose=raise_verbose,
8359
+ **kwargs,
8360
+ ):
8299
8361
  yield cmd, kwargs
8300
8362
 
8301
8363
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ominfra
3
- Version: 0.0.0.dev216
3
+ Version: 0.0.0.dev217
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: >=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omdev==0.0.0.dev216
16
- Requires-Dist: omlish==0.0.0.dev216
15
+ Requires-Dist: omdev==0.0.0.dev217
16
+ Requires-Dist: omlish==0.0.0.dev217
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -112,8 +112,8 @@ ominfra/manage/targets/connection.py,sha256=rVI1YJxFClcF-sdttqWyIz9_XjPI01GUdwxY
112
112
  ominfra/manage/targets/inject.py,sha256=P4597xWM-V3I_gCt2O71OLhYQkkXtuJvkYRsIbhhMcE,1561
113
113
  ominfra/manage/targets/targets.py,sha256=7GP6UAZyJFEhpkJN6UQdpr_WN3p7C76v-s445y-WB6U,1885
114
114
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
- ominfra/scripts/journald2aws.py,sha256=bFtGEkYYTfrwh_tP8yfdTrPwLvGnPIuJk9TXtoh2HTI,169937
116
- ominfra/scripts/manage.py,sha256=tLPoozkPT8SQqolTOPWvktxtGmpkcP2D1WveWl5bPVk,361314
115
+ ominfra/scripts/journald2aws.py,sha256=CM1nZMpecXJpcg7icJUCJ-_DX-7CduQurxZQ7EmhQmA,171450
116
+ ominfra/scripts/manage.py,sha256=MaUur1_dDdMHt5YnE6Waxa_v70kydHzKCBHXAuTmKd0,362827
117
117
  ominfra/scripts/supervisor.py,sha256=Laa7EM9tsLzjzb2Pkg2DVeUJX7OpsWLHuwlA9WP0cNM,295534
118
118
  ominfra/supervisor/LICENSE.txt,sha256=ZrHY15PVR98y26Yg6iQfa-SXnUaYTDhrUsPVcEO5OKM,1874
119
119
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -156,9 +156,9 @@ ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
156
156
  ominfra/tailscale/cli.py,sha256=3FnJbgpLw6gInTfhERd1mDy9ijjMUGxkdYVo43Tnxx4,3555
157
157
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
158
  ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
159
- ominfra-0.0.0.dev216.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
- ominfra-0.0.0.dev216.dist-info/METADATA,sha256=Y0FMZP4JOwYVxzV7r07WQy-vBFgLUNg3W4903Ivusi4,731
161
- ominfra-0.0.0.dev216.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
162
- ominfra-0.0.0.dev216.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
- ominfra-0.0.0.dev216.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
- ominfra-0.0.0.dev216.dist-info/RECORD,,
159
+ ominfra-0.0.0.dev217.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
+ ominfra-0.0.0.dev217.dist-info/METADATA,sha256=iTe6sIvgKblZxtFkb4vMZGGDzVFpVoV0l2bXB-3Jf5k,731
161
+ ominfra-0.0.0.dev217.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
162
+ ominfra-0.0.0.dev217.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
+ ominfra-0.0.0.dev217.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
+ ominfra-0.0.0.dev217.dist-info/RECORD,,