ominfra 0.0.0.dev155__tar.gz → 0.0.0.dev156__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. {ominfra-0.0.0.dev155/ominfra.egg-info → ominfra-0.0.0.dev156}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/subprocess.py +3 -4
  3. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/git.py +3 -3
  4. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/venvs.py +4 -4
  5. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/spawning.py +2 -2
  6. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/system/packages.py +13 -15
  7. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/scripts/journald2aws.py +181 -127
  8. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/scripts/manage.py +330 -314
  9. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156/ominfra.egg-info}/PKG-INFO +3 -3
  10. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra.egg-info/requires.txt +2 -2
  11. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/pyproject.toml +3 -3
  12. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/LICENSE +0 -0
  13. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/MANIFEST.in +0 -0
  14. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/README.rst +0 -0
  15. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/.manifests.json +0 -0
  16. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/__about__.py +0 -0
  17. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/__init__.py +0 -0
  18. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/__init__.py +0 -0
  19. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/__init__.py +0 -0
  20. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/__main__.py +0 -0
  21. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/auth.py +0 -0
  22. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/cli.py +0 -0
  23. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/dataclasses.py +0 -0
  24. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  25. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  26. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  27. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  28. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  29. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  30. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/logs.py +0 -0
  31. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/aws/metadata.py +0 -0
  32. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/gcp/__init__.py +0 -0
  33. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/clouds/gcp/auth.py +0 -0
  34. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/cmds.py +0 -0
  35. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/configs.py +0 -0
  36. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/journald/__init__.py +0 -0
  37. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/journald/fields.py +0 -0
  38. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/journald/genmessages.py +0 -0
  39. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/journald/messages.py +0 -0
  40. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/journald/tailer.py +0 -0
  41. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/__init__.py +0 -0
  42. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/__main__.py +0 -0
  43. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/bootstrap.py +0 -0
  44. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/bootstrap_.py +0 -0
  45. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/__init__.py +0 -0
  46. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/base.py +0 -0
  47. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/inject.py +0 -0
  48. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/local.py +0 -0
  49. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/marshal.py +0 -0
  50. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/ping.py +0 -0
  51. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/commands/types.py +0 -0
  52. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/config.py +0 -0
  53. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/__init__.py +0 -0
  54. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/apps.py +0 -0
  55. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/commands.py +0 -0
  56. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/config.py +0 -0
  57. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/inject.py +0 -0
  58. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/interp.py +0 -0
  59. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/paths.py +0 -0
  60. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/deploy/types.py +0 -0
  61. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/inject.py +0 -0
  62. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/main.py +0 -0
  63. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/marshal.py +0 -0
  64. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/__init__.py +0 -0
  65. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/_main.py +0 -0
  66. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/channel.py +0 -0
  67. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/config.py +0 -0
  68. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/connection.py +0 -0
  69. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/execution.py +0 -0
  70. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/inject.py +0 -0
  71. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/remote/payload.py +0 -0
  72. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/system/__init__.py +0 -0
  73. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/system/commands.py +0 -0
  74. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/system/config.py +0 -0
  75. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/system/inject.py +0 -0
  76. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/system/platforms.py +0 -0
  77. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/targets/__init__.py +0 -0
  78. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/targets/connection.py +0 -0
  79. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/targets/inject.py +0 -0
  80. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/manage/targets/targets.py +0 -0
  81. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/pyremote.py +0 -0
  82. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/scripts/__init__.py +0 -0
  83. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/scripts/supervisor.py +0 -0
  84. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/ssh.py +0 -0
  85. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/LICENSE.txt +0 -0
  86. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/__init__.py +0 -0
  87. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/__main__.py +0 -0
  88. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/configs.py +0 -0
  89. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/dispatchers.py +0 -0
  90. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/dispatchersimpl.py +0 -0
  91. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/events.py +0 -0
  92. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/exceptions.py +0 -0
  93. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/groups.py +0 -0
  94. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/groupsimpl.py +0 -0
  95. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/http.py +0 -0
  96. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/inject.py +0 -0
  97. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/io.py +0 -0
  98. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/main.py +0 -0
  99. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/pipes.py +0 -0
  100. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/privileges.py +0 -0
  101. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/process.py +0 -0
  102. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/processimpl.py +0 -0
  103. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/setup.py +0 -0
  104. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/setupimpl.py +0 -0
  105. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/signals.py +0 -0
  106. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/spawning.py +0 -0
  107. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/spawningimpl.py +0 -0
  108. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/states.py +0 -0
  109. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/supervisor.py +0 -0
  110. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/types.py +0 -0
  111. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/__init__.py +0 -0
  112. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/collections.py +0 -0
  113. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/diag.py +0 -0
  114. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/fds.py +0 -0
  115. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/fs.py +0 -0
  116. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/os.py +0 -0
  117. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/ostypes.py +0 -0
  118. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/signals.py +0 -0
  119. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/strings.py +0 -0
  120. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/supervisor/utils/users.py +0 -0
  121. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/tailscale/__init__.py +0 -0
  122. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/tailscale/api.py +0 -0
  123. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/tailscale/cli.py +0 -0
  124. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/threadworkers.py +0 -0
  125. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/tools/__init__.py +0 -0
  126. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra/tools/listresources.py +0 -0
  127. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra.egg-info/SOURCES.txt +0 -0
  128. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra.egg-info/dependency_links.txt +0 -0
  129. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra.egg-info/entry_points.txt +0 -0
  130. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/ominfra.egg-info/top_level.txt +0 -0
  131. {ominfra-0.0.0.dev155 → ominfra-0.0.0.dev156}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev155
3
+ Version: 0.0.0.dev156
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.dev155
16
- Requires-Dist: omlish==0.0.0.dev155
15
+ Requires-Dist: omdev==0.0.0.dev156
16
+ Requires-Dist: omlish==0.0.0.dev156
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -6,8 +6,7 @@ import subprocess
6
6
  import time
7
7
  import typing as ta
8
8
 
9
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_communicate
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_popen
9
+ from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
11
10
  from omlish.lite.check import check
12
11
  from omlish.lite.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
12
  from omlish.lite.subprocesses import SubprocessChannelOption
@@ -51,7 +50,7 @@ class SubprocessCommand(Command['SubprocessCommand.Output']):
51
50
  class SubprocessCommandExecutor(CommandExecutor[SubprocessCommand, SubprocessCommand.Output]):
52
51
  async def execute(self, cmd: SubprocessCommand) -> SubprocessCommand.Output:
53
52
  proc: asyncio.subprocess.Process
54
- async with asyncio_subprocess_popen(
53
+ async with asyncio_subprocesses.popen(
55
54
  *subprocess_maybe_shell_wrap_exec(*cmd.cmd),
56
55
 
57
56
  shell=cmd.shell,
@@ -65,7 +64,7 @@ class SubprocessCommandExecutor(CommandExecutor[SubprocessCommand, SubprocessCom
65
64
  timeout=cmd.timeout,
66
65
  ) as proc:
67
66
  start_time = time.time()
68
- stdout, stderr = await asyncio_subprocess_communicate(
67
+ stdout, stderr = await asyncio_subprocesses.communicate(
69
68
  proc,
70
69
  input=cmd.input,
71
70
  timeout=cmd.timeout,
@@ -13,7 +13,7 @@ import functools
13
13
  import os.path
14
14
  import typing as ta
15
15
 
16
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_check_call
16
+ from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
17
17
  from omlish.lite.cached import async_cached_nullary
18
18
  from omlish.lite.check import check
19
19
 
@@ -92,7 +92,7 @@ class DeployGitManager(DeployPathOwner):
92
92
  return f'https://{self._repo.host}/{self._repo.path}'
93
93
 
94
94
  async def _call(self, *cmd: str) -> None:
95
- await asyncio_subprocess_check_call(
95
+ await asyncio_subprocesses.check_call(
96
96
  *cmd,
97
97
  cwd=self._dir,
98
98
  )
@@ -118,7 +118,7 @@ class DeployGitManager(DeployPathOwner):
118
118
  # FIXME: temp dir swap
119
119
  os.makedirs(dst_dir)
120
120
 
121
- dst_call = functools.partial(asyncio_subprocess_check_call, cwd=dst_dir)
121
+ dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_dir)
122
122
  await dst_call('git', 'init')
123
123
 
124
124
  await dst_call('git', 'remote', 'add', 'local', self._dir)
@@ -7,7 +7,7 @@ TODO:
7
7
  import os.path
8
8
  import typing as ta
9
9
 
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_check_call
10
+ from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
11
11
 
12
12
  from .paths import DeployPath
13
13
  from .paths import DeployPathOwner
@@ -40,7 +40,7 @@ class DeployVenvManager(DeployPathOwner):
40
40
  ) -> None:
41
41
  sys_exe = 'python3'
42
42
 
43
- await asyncio_subprocess_check_call(sys_exe, '-m', 'venv', venv_dir)
43
+ await asyncio_subprocesses.check_call(sys_exe, '-m', 'venv', venv_dir)
44
44
 
45
45
  #
46
46
 
@@ -52,12 +52,12 @@ class DeployVenvManager(DeployPathOwner):
52
52
 
53
53
  if os.path.isfile(reqs_txt):
54
54
  if use_uv:
55
- await asyncio_subprocess_check_call(venv_exe, '-m', 'pip', 'install', 'uv')
55
+ await asyncio_subprocesses.check_call(venv_exe, '-m', 'pip', 'install', 'uv')
56
56
  pip_cmd = ['-m', 'uv', 'pip']
57
57
  else:
58
58
  pip_cmd = ['-m', 'pip']
59
59
 
60
- await asyncio_subprocess_check_call(venv_exe, *pip_cmd,'install', '-r', reqs_txt)
60
+ await asyncio_subprocesses.check_call(venv_exe, *pip_cmd,'install', '-r', reqs_txt)
61
61
 
62
62
  async def setup_app_venv(self, app_tag: DeployAppTag) -> None:
63
63
  await self.setup_venv(
@@ -7,7 +7,7 @@ import shlex
7
7
  import subprocess
8
8
  import typing as ta
9
9
 
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_popen
10
+ from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
11
11
  from omlish.lite.check import check
12
12
  from omlish.lite.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
13
  from omlish.lite.subprocesses import SubprocessChannelOption
@@ -86,7 +86,7 @@ class SubprocessRemoteSpawning(RemoteSpawning):
86
86
  if not debug:
87
87
  cmd = subprocess_maybe_shell_wrap_exec(*cmd)
88
88
 
89
- async with asyncio_subprocess_popen(
89
+ async with asyncio_subprocesses.popen(
90
90
  *cmd,
91
91
  shell=pc.shell,
92
92
  stdin=subprocess.PIPE,
@@ -9,9 +9,7 @@ import json
9
9
  import os
10
10
  import typing as ta
11
11
 
12
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_check_call
13
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_check_output
14
- from omlish.lite.asyncio.subprocesses import asyncio_subprocess_run
12
+ from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
15
13
  from omlish.lite.check import check
16
14
 
17
15
 
@@ -44,10 +42,10 @@ class SystemPackageManager(abc.ABC):
44
42
 
45
43
  class BrewSystemPackageManager(SystemPackageManager):
46
44
  async def update(self) -> None:
47
- await asyncio_subprocess_check_call('brew', 'update')
45
+ await asyncio_subprocesses.check_call('brew', 'update')
48
46
 
49
47
  async def upgrade(self) -> None:
50
- await asyncio_subprocess_check_call('brew', 'upgrade')
48
+ await asyncio_subprocesses.check_call('brew', 'upgrade')
51
49
 
52
50
  async def install(self, *packages: SystemPackageOrStr) -> None:
53
51
  es: ta.List[str] = []
@@ -56,11 +54,11 @@ class BrewSystemPackageManager(SystemPackageManager):
56
54
  es.append(p.name + (f'@{p.version}' if p.version is not None else ''))
57
55
  else:
58
56
  es.append(p)
59
- await asyncio_subprocess_check_call('brew', 'install', *es)
57
+ await asyncio_subprocesses.check_call('brew', 'install', *es)
60
58
 
61
59
  async def query(self, *packages: SystemPackageOrStr) -> ta.Mapping[str, SystemPackage]:
62
60
  pns = [p.name if isinstance(p, SystemPackage) else p for p in packages]
63
- o = await asyncio_subprocess_check_output('brew', 'info', '--json', *pns)
61
+ o = await asyncio_subprocesses.check_output('brew', 'info', '--json', *pns)
64
62
  j = json.loads(o.decode())
65
63
  d: ta.Dict[str, SystemPackage] = {}
66
64
  for e in j:
@@ -79,18 +77,18 @@ class AptSystemPackageManager(SystemPackageManager):
79
77
  }
80
78
 
81
79
  async def update(self) -> None:
82
- await asyncio_subprocess_check_call('sudo', 'apt', 'update', env={**os.environ, **self._APT_ENV})
80
+ await asyncio_subprocesses.check_call('sudo', 'apt', 'update', env={**os.environ, **self._APT_ENV})
83
81
 
84
82
  async def upgrade(self) -> None:
85
- await asyncio_subprocess_check_call('sudo', 'apt', 'upgrade', '-y', env={**os.environ, **self._APT_ENV})
83
+ await asyncio_subprocesses.check_call('sudo', 'apt', 'upgrade', '-y', env={**os.environ, **self._APT_ENV})
86
84
 
87
85
  async def install(self, *packages: SystemPackageOrStr) -> None:
88
86
  pns = [p.name if isinstance(p, SystemPackage) else p for p in packages] # FIXME: versions
89
- await asyncio_subprocess_check_call('sudo', 'apt', 'install', '-y', *pns, env={**os.environ, **self._APT_ENV})
87
+ await asyncio_subprocesses.check_call('sudo', 'apt', 'install', '-y', *pns, env={**os.environ, **self._APT_ENV})
90
88
 
91
89
  async def query(self, *packages: SystemPackageOrStr) -> ta.Mapping[str, SystemPackage]:
92
90
  pns = [p.name if isinstance(p, SystemPackage) else p for p in packages]
93
- out = await asyncio_subprocess_run(
91
+ out = await asyncio_subprocesses.run(
94
92
  'dpkg-query', '-W', '-f=${Package}=${Version}\n', *pns,
95
93
  capture_output=True,
96
94
  check=False,
@@ -107,20 +105,20 @@ class AptSystemPackageManager(SystemPackageManager):
107
105
 
108
106
  class YumSystemPackageManager(SystemPackageManager):
109
107
  async def update(self) -> None:
110
- await asyncio_subprocess_check_call('sudo', 'yum', 'check-update')
108
+ await asyncio_subprocesses.check_call('sudo', 'yum', 'check-update')
111
109
 
112
110
  async def upgrade(self) -> None:
113
- await asyncio_subprocess_check_call('sudo', 'yum', 'update')
111
+ await asyncio_subprocesses.check_call('sudo', 'yum', 'update')
114
112
 
115
113
  async def install(self, *packages: SystemPackageOrStr) -> None:
116
114
  pns = [p.name if isinstance(p, SystemPackage) else p for p in packages] # FIXME: versions
117
- await asyncio_subprocess_check_call('sudo', 'yum', 'install', *pns)
115
+ await asyncio_subprocesses.check_call('sudo', 'yum', 'install', *pns)
118
116
 
119
117
  async def query(self, *packages: SystemPackageOrStr) -> ta.Mapping[str, SystemPackage]:
120
118
  pns = [p.name if isinstance(p, SystemPackage) else p for p in packages]
121
119
  d: ta.Dict[str, SystemPackage] = {}
122
120
  for pn in pns:
123
- out = await asyncio_subprocess_run(
121
+ out = await asyncio_subprocesses.run(
124
122
  'rpm', '-q', pn,
125
123
  capture_output=True,
126
124
  )
@@ -3593,168 +3593,222 @@ SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
3593
3593
  _SUBPROCESS_SHELL_WRAP_EXECS = False
3594
3594
 
3595
3595
 
3596
- def subprocess_shell_wrap_exec(*args: str) -> ta.Tuple[str, ...]:
3597
- return ('sh', '-c', ' '.join(map(shlex.quote, args)))
3596
+ def subprocess_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
3597
+ return ('sh', '-c', ' '.join(map(shlex.quote, cmd)))
3598
3598
 
3599
3599
 
3600
- def subprocess_maybe_shell_wrap_exec(*args: str) -> ta.Tuple[str, ...]:
3600
+ def subprocess_maybe_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
3601
3601
  if _SUBPROCESS_SHELL_WRAP_EXECS or is_debugger_attached():
3602
- return subprocess_shell_wrap_exec(*args)
3602
+ return subprocess_shell_wrap_exec(*cmd)
3603
3603
  else:
3604
- return args
3605
-
3606
-
3607
- def prepare_subprocess_invocation(
3608
- *args: str,
3609
- env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
3610
- extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
3611
- quiet: bool = False,
3612
- shell: bool = False,
3613
- **kwargs: ta.Any,
3614
- ) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
3615
- log.debug('prepare_subprocess_invocation: args=%r', args)
3616
- if extra_env:
3617
- log.debug('prepare_subprocess_invocation: extra_env=%r', extra_env)
3618
-
3619
- if extra_env:
3620
- env = {**(env if env is not None else os.environ), **extra_env}
3621
-
3622
- if quiet and 'stderr' not in kwargs:
3623
- if not log.isEnabledFor(logging.DEBUG):
3624
- kwargs['stderr'] = subprocess.DEVNULL
3625
-
3626
- if not shell:
3627
- args = subprocess_maybe_shell_wrap_exec(*args)
3628
-
3629
- return args, dict(
3630
- env=env,
3631
- shell=shell,
3632
- **kwargs,
3633
- )
3604
+ return cmd
3634
3605
 
3635
3606
 
3636
3607
  ##
3637
3608
 
3638
3609
 
3639
- @contextlib.contextmanager
3640
- def subprocess_common_context(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
3641
- start_time = time.time()
3642
- try:
3643
- log.debug('subprocess_common_context.try: args=%r', args)
3644
- yield
3645
-
3646
- except Exception as exc: # noqa
3647
- log.debug('subprocess_common_context.except: exc=%r', exc)
3648
- raise
3610
+ def subprocess_close(
3611
+ proc: subprocess.Popen,
3612
+ timeout: ta.Optional[float] = None,
3613
+ ) -> None:
3614
+ # TODO: terminate, sleep, kill
3615
+ if proc.stdout:
3616
+ proc.stdout.close()
3617
+ if proc.stderr:
3618
+ proc.stderr.close()
3619
+ if proc.stdin:
3620
+ proc.stdin.close()
3649
3621
 
3650
- finally:
3651
- end_time = time.time()
3652
- elapsed_s = end_time - start_time
3653
- log.debug('subprocess_common_context.finally: elapsed_s=%f args=%r', elapsed_s, args)
3622
+ proc.wait(timeout)
3654
3623
 
3655
3624
 
3656
3625
  ##
3657
3626
 
3658
3627
 
3659
- def subprocess_check_call(
3660
- *args: str,
3661
- stdout: ta.Any = sys.stderr,
3662
- **kwargs: ta.Any,
3663
- ) -> None:
3664
- args, kwargs = prepare_subprocess_invocation(*args, stdout=stdout, **kwargs)
3665
- with subprocess_common_context(*args, **kwargs):
3666
- return subprocess.check_call(args, **kwargs) # type: ignore
3628
+ class AbstractSubprocesses(abc.ABC): # noqa
3629
+ DEFAULT_LOGGER: ta.ClassVar[ta.Optional[logging.Logger]] = log
3630
+
3631
+ def __init__(
3632
+ self,
3633
+ *,
3634
+ log: ta.Optional[logging.Logger] = None,
3635
+ try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
3636
+ ) -> None:
3637
+ super().__init__()
3667
3638
 
3639
+ self._log = log if log is not None else self.DEFAULT_LOGGER
3640
+ self._try_exceptions = try_exceptions if try_exceptions is not None else self.DEFAULT_TRY_EXCEPTIONS
3668
3641
 
3669
- def subprocess_check_output(
3670
- *args: str,
3671
- **kwargs: ta.Any,
3672
- ) -> bytes:
3673
- args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
3674
- with subprocess_common_context(*args, **kwargs):
3675
- return subprocess.check_output(args, **kwargs)
3642
+ #
3676
3643
 
3644
+ def prepare_args(
3645
+ self,
3646
+ *cmd: str,
3647
+ env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
3648
+ extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
3649
+ quiet: bool = False,
3650
+ shell: bool = False,
3651
+ **kwargs: ta.Any,
3652
+ ) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
3653
+ if self._log:
3654
+ self._log.debug('Subprocesses.prepare_args: cmd=%r', cmd)
3655
+ if extra_env:
3656
+ self._log.debug('Subprocesses.prepare_args: extra_env=%r', extra_env)
3677
3657
 
3678
- def subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
3679
- return subprocess_check_output(*args, **kwargs).decode().strip()
3658
+ if extra_env:
3659
+ env = {**(env if env is not None else os.environ), **extra_env}
3680
3660
 
3661
+ if quiet and 'stderr' not in kwargs:
3662
+ if self._log and not self._log.isEnabledFor(logging.DEBUG):
3663
+ kwargs['stderr'] = subprocess.DEVNULL
3681
3664
 
3682
- ##
3665
+ if not shell:
3666
+ cmd = subprocess_maybe_shell_wrap_exec(*cmd)
3683
3667
 
3668
+ return cmd, dict(
3669
+ env=env,
3670
+ shell=shell,
3671
+ **kwargs,
3672
+ )
3684
3673
 
3685
- DEFAULT_SUBPROCESS_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
3686
- FileNotFoundError,
3687
- subprocess.CalledProcessError,
3688
- )
3674
+ @contextlib.contextmanager
3675
+ def wrap_call(self, *cmd: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
3676
+ start_time = time.time()
3677
+ try:
3678
+ if self._log:
3679
+ self._log.debug('Subprocesses.wrap_call.try: cmd=%r', cmd)
3680
+ yield
3689
3681
 
3682
+ except Exception as exc: # noqa
3683
+ if self._log:
3684
+ self._log.debug('Subprocesses.wrap_call.except: exc=%r', exc)
3685
+ raise
3690
3686
 
3691
- def _subprocess_try_run(
3692
- fn: ta.Callable[..., T],
3693
- *args: ta.Any,
3694
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
3695
- **kwargs: ta.Any,
3696
- ) -> ta.Union[T, Exception]:
3697
- try:
3698
- return fn(*args, **kwargs)
3699
- except try_exceptions as e: # noqa
3700
- if log.isEnabledFor(logging.DEBUG):
3701
- log.exception('command failed')
3702
- return e
3703
-
3704
-
3705
- def subprocess_try_call(
3706
- *args: str,
3707
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
3708
- **kwargs: ta.Any,
3709
- ) -> bool:
3710
- if isinstance(_subprocess_try_run(
3711
- subprocess_check_call,
3712
- *args,
3713
- try_exceptions=try_exceptions,
3714
- **kwargs,
3715
- ), Exception):
3716
- return False
3717
- else:
3718
- return True
3687
+ finally:
3688
+ end_time = time.time()
3689
+ elapsed_s = end_time - start_time
3690
+ if self._log:
3691
+ self._log.debug('sSubprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
3719
3692
 
3693
+ @contextlib.contextmanager
3694
+ def prepare_and_wrap(
3695
+ self,
3696
+ *cmd: ta.Any,
3697
+ **kwargs: ta.Any,
3698
+ ) -> ta.Iterator[ta.Tuple[
3699
+ ta.Tuple[ta.Any, ...],
3700
+ ta.Dict[str, ta.Any],
3701
+ ]]:
3702
+ cmd, kwargs = self.prepare_args(*cmd, **kwargs)
3703
+ with self.wrap_call(*cmd, **kwargs):
3704
+ yield cmd, kwargs
3720
3705
 
3721
- def subprocess_try_output(
3722
- *args: str,
3723
- try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
3724
- **kwargs: ta.Any,
3725
- ) -> ta.Optional[bytes]:
3726
- if isinstance(ret := _subprocess_try_run(
3727
- subprocess_check_output,
3728
- *args,
3729
- try_exceptions=try_exceptions,
3730
- **kwargs,
3731
- ), Exception):
3732
- return None
3733
- else:
3734
- return ret
3706
+ #
3707
+
3708
+ DEFAULT_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
3709
+ FileNotFoundError,
3710
+ subprocess.CalledProcessError,
3711
+ )
3735
3712
 
3713
+ def try_fn(
3714
+ self,
3715
+ fn: ta.Callable[..., T],
3716
+ *cmd: str,
3717
+ try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
3718
+ **kwargs: ta.Any,
3719
+ ) -> ta.Union[T, Exception]:
3720
+ if try_exceptions is None:
3721
+ try_exceptions = self._try_exceptions
3736
3722
 
3737
- def subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
3738
- out = subprocess_try_output(*args, **kwargs)
3739
- return out.decode().strip() if out is not None else None
3723
+ try:
3724
+ return fn(*cmd, **kwargs)
3725
+
3726
+ except try_exceptions as e: # noqa
3727
+ if self._log and self._log.isEnabledFor(logging.DEBUG):
3728
+ self._log.exception('command failed')
3729
+ return e
3730
+
3731
+ async def async_try_fn(
3732
+ self,
3733
+ fn: ta.Callable[..., ta.Awaitable[T]],
3734
+ *cmd: ta.Any,
3735
+ try_exceptions: ta.Optional[ta.Tuple[ta.Type[Exception], ...]] = None,
3736
+ **kwargs: ta.Any,
3737
+ ) -> ta.Union[T, Exception]:
3738
+ if try_exceptions is None:
3739
+ try_exceptions = self._try_exceptions
3740
+
3741
+ try:
3742
+ return await fn(*cmd, **kwargs)
3743
+
3744
+ except try_exceptions as e: # noqa
3745
+ if self._log and self._log.isEnabledFor(logging.DEBUG):
3746
+ self._log.exception('command failed')
3747
+ return e
3740
3748
 
3741
3749
 
3742
3750
  ##
3743
3751
 
3744
3752
 
3745
- def subprocess_close(
3746
- proc: subprocess.Popen,
3747
- timeout: ta.Optional[float] = None,
3748
- ) -> None:
3749
- # TODO: terminate, sleep, kill
3750
- if proc.stdout:
3751
- proc.stdout.close()
3752
- if proc.stderr:
3753
- proc.stderr.close()
3754
- if proc.stdin:
3755
- proc.stdin.close()
3753
+ class Subprocesses(AbstractSubprocesses):
3754
+ def check_call(
3755
+ self,
3756
+ *cmd: str,
3757
+ stdout: ta.Any = sys.stderr,
3758
+ **kwargs: ta.Any,
3759
+ ) -> None:
3760
+ with self.prepare_and_wrap(*cmd, stdout=stdout, **kwargs) as (cmd, kwargs): # noqa
3761
+ subprocess.check_call(cmd, **kwargs)
3756
3762
 
3757
- proc.wait(timeout)
3763
+ def check_output(
3764
+ self,
3765
+ *cmd: str,
3766
+ **kwargs: ta.Any,
3767
+ ) -> bytes:
3768
+ with self.prepare_and_wrap(*cmd, **kwargs) as (cmd, kwargs): # noqa
3769
+ return subprocess.check_output(cmd, **kwargs)
3770
+
3771
+ def check_output_str(
3772
+ self,
3773
+ *cmd: str,
3774
+ **kwargs: ta.Any,
3775
+ ) -> str:
3776
+ return self.check_output(*cmd, **kwargs).decode().strip()
3777
+
3778
+ #
3779
+
3780
+ def try_call(
3781
+ self,
3782
+ *cmd: str,
3783
+ **kwargs: ta.Any,
3784
+ ) -> bool:
3785
+ if isinstance(self.try_fn(self.check_call, *cmd, **kwargs), Exception):
3786
+ return False
3787
+ else:
3788
+ return True
3789
+
3790
+ def try_output(
3791
+ self,
3792
+ *cmd: str,
3793
+ **kwargs: ta.Any,
3794
+ ) -> ta.Optional[bytes]:
3795
+ if isinstance(ret := self.try_fn(self.check_output, *cmd, **kwargs), Exception):
3796
+ return None
3797
+ else:
3798
+ return ret
3799
+
3800
+ def try_output_str(
3801
+ self,
3802
+ *cmd: str,
3803
+ **kwargs: ta.Any,
3804
+ ) -> ta.Optional[str]:
3805
+ if (ret := self.try_output(*cmd, **kwargs)) is None:
3806
+ return None
3807
+ else:
3808
+ return ret.decode().strip()
3809
+
3810
+
3811
+ subprocesses = Subprocesses()
3758
3812
 
3759
3813
 
3760
3814
  ########################################