ominfra 0.0.0.dev149__tar.gz → 0.0.0.dev151__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. {ominfra-0.0.0.dev149/ominfra.egg-info → ominfra-0.0.0.dev151}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/auth.py +7 -9
  3. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/journald2aws/driver.py +4 -4
  4. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/logs.py +4 -5
  5. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/gcp/auth.py +1 -1
  6. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/configs.py +3 -4
  7. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/journald/messages.py +2 -2
  8. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/journald/tailer.py +2 -2
  9. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/base.py +2 -2
  10. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/interp.py +3 -3
  11. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/subprocess.py +3 -4
  12. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/deploy/paths.py +12 -15
  13. ominfra-0.0.0.dev151/ominfra/manage/main.py +131 -0
  14. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/_main.py +6 -7
  15. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/execution.py +7 -10
  16. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/spawning.py +3 -3
  17. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/scripts/journald2aws.py +449 -93
  18. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/scripts/manage.py +770 -186
  19. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/scripts/supervisor.py +1137 -781
  20. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/groupsimpl.py +2 -2
  21. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/http.py +5 -5
  22. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/main.py +1 -1
  23. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/processimpl.py +2 -2
  24. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/spawningimpl.py +8 -9
  25. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/supervisor.py +2 -2
  26. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151/ominfra.egg-info}/PKG-INFO +3 -3
  27. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra.egg-info/requires.txt +2 -2
  28. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/pyproject.toml +3 -3
  29. ominfra-0.0.0.dev149/ominfra/manage/main.py +0 -134
  30. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/LICENSE +0 -0
  31. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/MANIFEST.in +0 -0
  32. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/README.rst +0 -0
  33. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/.manifests.json +0 -0
  34. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/__about__.py +0 -0
  35. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/__init__.py +0 -0
  36. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/__init__.py +0 -0
  37. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/__init__.py +0 -0
  38. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/__main__.py +0 -0
  39. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/cli.py +0 -0
  40. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/dataclasses.py +0 -0
  41. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  42. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  43. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  44. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  45. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  46. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/aws/metadata.py +0 -0
  47. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/clouds/gcp/__init__.py +0 -0
  48. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/cmds.py +0 -0
  49. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/journald/__init__.py +0 -0
  50. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/journald/fields.py +0 -0
  51. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/journald/genmessages.py +0 -0
  52. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/__init__.py +0 -0
  53. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/__main__.py +0 -0
  54. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/bootstrap.py +0 -0
  55. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/bootstrap_.py +0 -0
  56. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/__init__.py +0 -0
  57. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/execution.py +0 -0
  58. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/inject.py +0 -0
  59. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/commands/marshal.py +0 -0
  60. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/config.py +0 -0
  61. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/deploy/__init__.py +0 -0
  62. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/deploy/command.py +0 -0
  63. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/deploy/inject.py +0 -0
  64. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/inject.py +0 -0
  65. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/marshal.py +0 -0
  66. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/__init__.py +0 -0
  67. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/channel.py +0 -0
  68. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/config.py +0 -0
  69. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/connection.py +0 -0
  70. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/inject.py +0 -0
  71. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/manage/remote/payload.py +0 -0
  72. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/pyremote.py +0 -0
  73. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/scripts/__init__.py +0 -0
  74. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/ssh.py +0 -0
  75. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/LICENSE.txt +0 -0
  76. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/__init__.py +0 -0
  77. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/__main__.py +0 -0
  78. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/configs.py +0 -0
  79. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/dispatchers.py +0 -0
  80. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/dispatchersimpl.py +0 -0
  81. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/events.py +0 -0
  82. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/exceptions.py +0 -0
  83. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/groups.py +0 -0
  84. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/inject.py +0 -0
  85. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/io.py +0 -0
  86. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/pipes.py +0 -0
  87. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/privileges.py +0 -0
  88. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/process.py +0 -0
  89. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/setup.py +0 -0
  90. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/setupimpl.py +0 -0
  91. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/signals.py +0 -0
  92. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/spawning.py +0 -0
  93. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/states.py +0 -0
  94. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/types.py +0 -0
  95. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/__init__.py +0 -0
  96. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/collections.py +0 -0
  97. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/diag.py +0 -0
  98. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/fds.py +0 -0
  99. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/fs.py +0 -0
  100. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/os.py +0 -0
  101. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/ostypes.py +0 -0
  102. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/signals.py +0 -0
  103. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/strings.py +0 -0
  104. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/supervisor/utils/users.py +0 -0
  105. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/tailscale/__init__.py +0 -0
  106. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/tailscale/api.py +0 -0
  107. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/tailscale/cli.py +0 -0
  108. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/threadworkers.py +0 -0
  109. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/tools/__init__.py +0 -0
  110. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra/tools/listresources.py +0 -0
  111. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra.egg-info/SOURCES.txt +0 -0
  112. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra.egg-info/dependency_links.txt +0 -0
  113. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra.egg-info/entry_points.txt +0 -0
  114. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/ominfra.egg-info/top_level.txt +0 -0
  115. {ominfra-0.0.0.dev149 → ominfra-0.0.0.dev151}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev149
3
+ Version: 0.0.0.dev151
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.dev149
16
- Requires-Dist: omlish==0.0.0.dev149
15
+ Requires-Dist: omdev==0.0.0.dev151
16
+ Requires-Dist: omlish==0.0.0.dev151
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -17,9 +17,7 @@ import hmac
17
17
  import typing as ta
18
18
  import urllib.parse
19
19
 
20
- from omlish.lite.check import check_equal
21
- from omlish.lite.check import check_non_empty_str
22
- from omlish.lite.check import check_not_isinstance
20
+ from omlish.lite.check import check
23
21
 
24
22
 
25
23
  ##
@@ -60,7 +58,7 @@ class AwsSigner:
60
58
  @staticmethod
61
59
  def _host_from_url(url: str) -> str:
62
60
  url_parts = urllib.parse.urlsplit(url)
63
- host = check_non_empty_str(url_parts.hostname)
61
+ host = check.non_empty_str(url_parts.hostname)
64
62
  default_ports = {
65
63
  'http': 80,
66
64
  'https': 443,
@@ -74,7 +72,7 @@ class AwsSigner:
74
72
  def _lower_case_http_map(d: ta.Mapping[str, ta.Sequence[str]]) -> ta.Mapping[str, ta.Sequence[str]]:
75
73
  o: ta.Dict[str, ta.List[str]] = {}
76
74
  for k, vs in d.items():
77
- o.setdefault(k.lower(), []).extend(check_not_isinstance(vs, str))
75
+ o.setdefault(k.lower(), []).extend(check.not_isinstance(vs, str))
78
76
  return o
79
77
 
80
78
  #
@@ -107,12 +105,12 @@ class AwsSigner:
107
105
  ])
108
106
 
109
107
  def _validate_request(self, req: Request) -> None:
110
- check_non_empty_str(req.method)
111
- check_equal(req.method.upper(), req.method)
108
+ check.non_empty_str(req.method)
109
+ check.equal(req.method.upper(), req.method)
112
110
  for k, vs in req.headers.items():
113
- check_equal(k.strip(), k)
111
+ check.equal(k.strip(), k)
114
112
  for v in vs:
115
- check_equal(v.strip(), v)
113
+ check.equal(v.strip(), v)
116
114
 
117
115
 
118
116
  AwsSigner._EMPTY_SHA256 = AwsSigner._sha256(b'') # noqa
@@ -38,7 +38,7 @@ import time
38
38
  import typing as ta
39
39
 
40
40
  from omlish.lite.cached import cached_nullary
41
- from omlish.lite.check import check_non_empty_str
41
+ from omlish.lite.check import check
42
42
  from omlish.lite.contextmanagers import ExitStacked
43
43
  from omlish.lite.logs import log
44
44
  from omlish.lite.pidfile import Pidfile
@@ -126,15 +126,15 @@ class JournalctlToAwsDriver(ExitStacked):
126
126
  return None
127
127
 
128
128
  return AwsSigner.Credentials(
129
- access_key_id=check_non_empty_str(self._config.aws_access_key_id),
130
- secret_access_key=check_non_empty_str(self._config.aws_secret_access_key),
129
+ access_key_id=check.non_empty_str(self._config.aws_access_key_id),
130
+ secret_access_key=check.non_empty_str(self._config.aws_secret_access_key),
131
131
  )
132
132
 
133
133
  @cached_nullary
134
134
  def _aws_log_message_builder(self) -> AwsLogMessageBuilder:
135
135
  return AwsLogMessageBuilder(
136
136
  log_group_name=self._config.aws_log_group_name,
137
- log_stream_name=check_non_empty_str(self._config.aws_log_stream_name),
137
+ log_stream_name=check.non_empty_str(self._config.aws_log_stream_name),
138
138
  region_name=self._config.aws_region_name,
139
139
  credentials=self._aws_credentials(),
140
140
  )
@@ -19,8 +19,7 @@ import dataclasses as dc
19
19
  import json
20
20
  import typing as ta
21
21
 
22
- from omlish.lite.check import check_non_empty_str
23
- from omlish.lite.check import check_single
22
+ from omlish.lite.check import check
24
23
 
25
24
  from .auth import AwsSigner
26
25
  from .auth import V4AwsSigner
@@ -97,8 +96,8 @@ class AwsLogMessageBuilder:
97
96
  ) -> None:
98
97
  super().__init__()
99
98
 
100
- self._log_group_name = check_non_empty_str(log_group_name)
101
- self._log_stream_name = check_non_empty_str(log_stream_name)
99
+ self._log_group_name = check.non_empty_str(log_group_name)
100
+ self._log_stream_name = check.non_empty_str(log_stream_name)
102
101
 
103
102
  if url is None:
104
103
  url = self.DEFAULT_URL.format(region_name=region_name)
@@ -172,7 +171,7 @@ class AwsLogMessageBuilder:
172
171
 
173
172
  post = AwsLogMessageBuilder.Post(
174
173
  url=self._url,
175
- headers={k: check_single(v) for k, v in sig_req.headers.items()},
174
+ headers={k: check.single(v) for k, v in sig_req.headers.items()},
176
175
  data=sig_req.payload,
177
176
  )
178
177
 
@@ -3,7 +3,7 @@ import time
3
3
  import typing as ta
4
4
 
5
5
  from omlish import check
6
- from omlish import http
6
+ from omlish.http import all as http
7
7
  from omlish.http import jwt
8
8
 
9
9
 
@@ -5,8 +5,7 @@ import os.path
5
5
  import typing as ta
6
6
 
7
7
  from omdev.toml.parser import toml_loads
8
- from omlish.lite.check import check_isinstance
9
- from omlish.lite.check import check_not_isinstance
8
+ from omlish.lite.check import check
10
9
  from omlish.lite.marshal import unmarshal_obj
11
10
 
12
11
 
@@ -72,7 +71,7 @@ def build_config_named_children(
72
71
  lst: ta.List[ConfigMapping] = []
73
72
  if isinstance(o, ta.Mapping):
74
73
  for k, v in o.items():
75
- check_isinstance(v, ta.Mapping)
74
+ check.isinstance(v, ta.Mapping)
76
75
  if name_key in v:
77
76
  n = v[name_key]
78
77
  if k != n:
@@ -82,7 +81,7 @@ def build_config_named_children(
82
81
  lst.append({name_key: k, **v})
83
82
 
84
83
  else:
85
- check_not_isinstance(o, str)
84
+ check.not_isinstance(o, str)
86
85
  lst.extend(o)
87
86
 
88
87
  seen = set()
@@ -5,7 +5,7 @@ import json
5
5
  import typing as ta
6
6
 
7
7
  from omlish.io.buffers import DelimitingBuffer
8
- from omlish.lite.check import check_isinstance
8
+ from omlish.lite.check import check
9
9
  from omlish.lite.logs import log
10
10
 
11
11
 
@@ -74,5 +74,5 @@ class JournalctlMessageBuilder:
74
74
  def feed(self, data: bytes) -> ta.Sequence[JournalctlMessage]:
75
75
  ret: ta.List[JournalctlMessage] = []
76
76
  for line in self._buf.feed(data):
77
- ret.append(self._make_message(check_isinstance(line, bytes)))
77
+ ret.append(self._make_message(check.isinstance(line, bytes)))
78
78
  return ret
@@ -408,7 +408,7 @@ import time
408
408
  import typing as ta
409
409
 
410
410
  from omlish.lite.cached import cached_nullary
411
- from omlish.lite.check import check_not_none
411
+ from omlish.lite.check import check
412
412
  from omlish.lite.logs import log
413
413
  from omlish.lite.subprocesses import subprocess_close
414
414
  from omlish.lite.subprocesses import subprocess_shell_wrap_exec
@@ -499,7 +499,7 @@ class JournalctlTailerWorker(ThreadWorker):
499
499
  stdout=subprocess.PIPE,
500
500
  ) as self._proc:
501
501
  try:
502
- stdout = check_not_none(self._proc.stdout)
502
+ stdout = check.not_none(self._proc.stdout)
503
503
 
504
504
  fd = stdout.fileno()
505
505
  fl = fcntl.fcntl(fd, fcntl.F_GETFL)
@@ -5,7 +5,7 @@ import logging
5
5
  import traceback
6
6
  import typing as ta
7
7
 
8
- from omlish.lite.check import check_isinstance
8
+ from omlish.lite.check import check
9
9
  from omlish.lite.strings import snake_case
10
10
 
11
11
 
@@ -24,7 +24,7 @@ class Command(abc.ABC, ta.Generic[CommandOutputT]):
24
24
 
25
25
  @ta.final
26
26
  async def execute(self, executor: 'CommandExecutor') -> CommandOutputT:
27
- return check_isinstance(await executor.execute(self), self.Output) # type: ignore[return-value]
27
+ return check.isinstance(await executor.execute(self), self.Output) # type: ignore[return-value]
28
28
 
29
29
 
30
30
  ##
@@ -4,7 +4,7 @@ import dataclasses as dc
4
4
  from omdev.interp.resolvers import DEFAULT_INTERP_RESOLVER
5
5
  from omdev.interp.types import InterpOpts
6
6
  from omdev.interp.types import InterpSpecifier
7
- from omlish.lite.check import check_not_none
7
+ from omlish.lite.check import check
8
8
 
9
9
  from ..commands.base import Command
10
10
  from ..commands.base import CommandExecutor
@@ -30,8 +30,8 @@ class InterpCommand(Command['InterpCommand.Output']):
30
30
 
31
31
  class InterpCommandExecutor(CommandExecutor[InterpCommand, InterpCommand.Output]):
32
32
  async def execute(self, cmd: InterpCommand) -> InterpCommand.Output:
33
- i = InterpSpecifier.parse(check_not_none(cmd.spec))
34
- o = check_not_none(await DEFAULT_INTERP_RESOLVER.resolve(i, install=cmd.install))
33
+ i = InterpSpecifier.parse(check.not_none(cmd.spec))
34
+ o = check.not_none(await DEFAULT_INTERP_RESOLVER.resolve(i, install=cmd.install))
35
35
  return InterpCommand.Output(
36
36
  exe=o.exe,
37
37
  version=str(o.version.version),
@@ -8,8 +8,7 @@ import typing as ta
8
8
 
9
9
  from omlish.lite.asyncio.subprocesses import asyncio_subprocess_communicate
10
10
  from omlish.lite.asyncio.subprocesses import asyncio_subprocess_popen
11
- from omlish.lite.check import check_not_isinstance
12
- from omlish.lite.check import check_not_none
11
+ from omlish.lite.check import check
13
12
  from omlish.lite.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
14
13
  from omlish.lite.subprocesses import SubprocessChannelOption
15
14
  from omlish.lite.subprocesses import subprocess_maybe_shell_wrap_exec
@@ -36,7 +35,7 @@ class SubprocessCommand(Command['SubprocessCommand.Output']):
36
35
  timeout: ta.Optional[float] = None
37
36
 
38
37
  def __post_init__(self) -> None:
39
- check_not_isinstance(self.cmd, str)
38
+ check.not_isinstance(self.cmd, str)
40
39
 
41
40
  @dc.dataclass(frozen=True)
42
41
  class Output(Command.Output):
@@ -77,7 +76,7 @@ class SubprocessCommandExecutor(CommandExecutor[SubprocessCommand, SubprocessCom
77
76
  end_time = time.time()
78
77
 
79
78
  return SubprocessCommand.Output(
80
- rc=check_not_none(proc.returncode),
79
+ rc=check.not_none(proc.returncode),
81
80
  pid=proc.pid,
82
81
 
83
82
  elapsed_s=end_time - start_time,
@@ -36,10 +36,7 @@ import dataclasses as dc
36
36
  import os.path
37
37
  import typing as ta
38
38
 
39
- from omlish.lite.check import check_equal
40
- from omlish.lite.check import check_non_empty_str
41
- from omlish.lite.check import check_not_empty
42
- from omlish.lite.check import check_not_in
39
+ from omlish.lite.check import check
43
40
 
44
41
 
45
42
  DeployPathKind = ta.Literal['dir', 'file'] # ta.TypeAlias
@@ -74,7 +71,7 @@ class DeployPathDir(DeployPathPart, abc.ABC):
74
71
  @classmethod
75
72
  def parse(cls, s: str) -> 'DeployPathDir':
76
73
  if DEPLOY_PATH_SPEC_PLACEHOLDER in s:
77
- check_equal(s, DEPLOY_PATH_SPEC_PLACEHOLDER)
74
+ check.equal(s, DEPLOY_PATH_SPEC_PLACEHOLDER)
78
75
  return SpecDeployPathDir()
79
76
  else:
80
77
  return ConstDeployPathDir(s)
@@ -88,7 +85,7 @@ class DeployPathFile(DeployPathPart, abc.ABC):
88
85
  @classmethod
89
86
  def parse(cls, s: str) -> 'DeployPathFile':
90
87
  if DEPLOY_PATH_SPEC_PLACEHOLDER in s:
91
- check_equal(s[0], DEPLOY_PATH_SPEC_PLACEHOLDER)
88
+ check.equal(s[0], DEPLOY_PATH_SPEC_PLACEHOLDER)
92
89
  return SpecDeployPathFile(s[1:])
93
90
  else:
94
91
  return ConstDeployPathFile(s)
@@ -102,9 +99,9 @@ class ConstDeployPathPart(DeployPathPart, abc.ABC):
102
99
  name: str
103
100
 
104
101
  def __post_init__(self) -> None:
105
- check_non_empty_str(self.name)
106
- check_not_in('/', self.name)
107
- check_not_in(DEPLOY_PATH_SPEC_PLACEHOLDER, self.name)
102
+ check.non_empty_str(self.name)
103
+ check.not_in('/', self.name)
104
+ check.not_in(DEPLOY_PATH_SPEC_PLACEHOLDER, self.name)
108
105
 
109
106
  def render(self) -> str:
110
107
  return self.name
@@ -135,9 +132,9 @@ class SpecDeployPathFile(SpecDeployPathPart, DeployPathFile):
135
132
  suffix: str
136
133
 
137
134
  def __post_init__(self) -> None:
138
- check_non_empty_str(self.suffix)
139
- check_not_in('/', self.suffix)
140
- check_not_in(DEPLOY_PATH_SPEC_PLACEHOLDER, self.suffix)
135
+ check.non_empty_str(self.suffix)
136
+ check.not_in('/', self.suffix)
137
+ check.not_in(DEPLOY_PATH_SPEC_PLACEHOLDER, self.suffix)
141
138
 
142
139
  def render(self) -> str:
143
140
  return DEPLOY_PATH_SPEC_PLACEHOLDER + self.suffix
@@ -151,9 +148,9 @@ class DeployPath:
151
148
  parts: ta.Sequence[DeployPathPart]
152
149
 
153
150
  def __post_init__(self) -> None:
154
- check_not_empty(self.parts)
151
+ check.not_empty(self.parts)
155
152
  for p in self.parts[:-1]:
156
- check_equal(p.kind, 'dir')
153
+ check.equal(p.kind, 'dir')
157
154
 
158
155
  @property
159
156
  def kind(self) -> ta.Literal['file', 'dir']:
@@ -173,7 +170,7 @@ class DeployPath:
173
170
  s = s[:-1]
174
171
  else:
175
172
  tail_parse = DeployPathFile.parse
176
- ps = check_non_empty_str(s).split('/')
173
+ ps = check.non_empty_str(s).split('/')
177
174
  return cls([
178
175
  *([DeployPathDir.parse(p) for p in ps[:-1]] if len(ps) > 1 else []),
179
176
  tail_parse(ps[-1]),
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env python3
2
+ # @omlish-amalg ../scripts/manage.py
3
+ # ruff: noqa: UP006 UP007
4
+ """
5
+ manage.py -s 'docker run -i python:3.12'
6
+ manage.py -s 'ssh -i /foo/bar.pem foo@bar.baz' -q --python=python3.8
7
+ """
8
+ import asyncio
9
+ import contextlib
10
+ import json
11
+ import typing as ta
12
+
13
+ from omlish.argparse.cli import ArgparseCli
14
+ from omlish.argparse.cli import argparse_arg
15
+ from omlish.argparse.cli import argparse_command
16
+ from omlish.lite.logs import log # noqa
17
+ from omlish.lite.marshal import ObjMarshalerManager
18
+ from omlish.lite.marshal import ObjMarshalOptions
19
+ from omlish.lite.pycharm import PycharmRemoteDebug
20
+
21
+ from .bootstrap import MainBootstrap
22
+ from .bootstrap_ import main_bootstrap
23
+ from .commands.base import Command
24
+ from .commands.base import CommandExecutor
25
+ from .commands.execution import LocalCommandExecutor
26
+ from .config import MainConfig
27
+ from .remote.config import RemoteConfig
28
+ from .remote.connection import RemoteExecutionConnector
29
+ from .remote.spawning import RemoteSpawning
30
+
31
+
32
+ class MainCli(ArgparseCli):
33
+ @argparse_command(
34
+ argparse_arg('--payload-file'),
35
+
36
+ argparse_arg('-s', '--shell'),
37
+ argparse_arg('-q', '--shell-quote', action='store_true'),
38
+ argparse_arg('--python', default='python3'),
39
+
40
+ argparse_arg('--pycharm-debug-port', type=int),
41
+ argparse_arg('--pycharm-debug-host'),
42
+ argparse_arg('--pycharm-debug-version'),
43
+
44
+ argparse_arg('--remote-timebomb-delay-s', type=float),
45
+
46
+ argparse_arg('--debug', action='store_true'),
47
+
48
+ argparse_arg('--local', action='store_true'),
49
+
50
+ argparse_arg('command', nargs='+'),
51
+ )
52
+ def run(self) -> None:
53
+ asyncio.run(self._async_run())
54
+
55
+ async def _async_run(self) -> None:
56
+ bs = MainBootstrap(
57
+ main_config=MainConfig(
58
+ log_level='DEBUG' if self.args.debug else 'INFO',
59
+
60
+ debug=bool(self.args.debug),
61
+ ),
62
+
63
+ remote_config=RemoteConfig(
64
+ payload_file=self.args.payload_file, # noqa
65
+
66
+ pycharm_remote_debug=PycharmRemoteDebug(
67
+ port=self.args.pycharm_debug_port,
68
+ **(dict(host=self.args.pycharm_debug_host) if self.args.pycharm_debug_host is not None else {}),
69
+ install_version=self.args.pycharm_debug_version,
70
+ ) if self.args.pycharm_debug_port is not None else None,
71
+
72
+ timebomb_delay_s=self.args.remote_timebomb_delay_s,
73
+ ),
74
+ )
75
+
76
+ #
77
+
78
+ injector = main_bootstrap(
79
+ bs,
80
+ )
81
+
82
+ #
83
+
84
+ msh = injector[ObjMarshalerManager]
85
+
86
+ cmds: ta.List[Command] = []
87
+ cmd: Command
88
+ for c in self.args.command:
89
+ if not c.startswith('{'):
90
+ c = json.dumps({c: {}})
91
+ cmd = msh.unmarshal_obj(json.loads(c), Command)
92
+ cmds.append(cmd)
93
+
94
+ #
95
+
96
+ async with contextlib.AsyncExitStack() as es:
97
+ ce: CommandExecutor
98
+
99
+ if self.args.local:
100
+ ce = injector[LocalCommandExecutor]
101
+
102
+ else:
103
+ tgt = RemoteSpawning.Target(
104
+ shell=self.args.shell,
105
+ shell_quote=self.args.shell_quote,
106
+ python=self.args.python,
107
+ )
108
+
109
+ ce = await es.enter_async_context(injector[RemoteExecutionConnector].connect(tgt, bs)) # noqa
110
+
111
+ async def run_command(cmd: Command) -> None:
112
+ res = await ce.try_execute(
113
+ cmd,
114
+ log=log,
115
+ omit_exc_object=True,
116
+ )
117
+
118
+ print(msh.marshal_obj(res, opts=ObjMarshalOptions(raw_bytes=True)))
119
+
120
+ await asyncio.gather(*[
121
+ run_command(cmd)
122
+ for cmd in cmds
123
+ ])
124
+
125
+
126
+ def _main() -> None:
127
+ MainCli().call_and_exit()
128
+
129
+
130
+ if __name__ == '__main__':
131
+ _main()
@@ -11,8 +11,7 @@ import typing as ta
11
11
  from omlish.lite.asyncio.asyncio import asyncio_open_stream_reader
12
12
  from omlish.lite.asyncio.asyncio import asyncio_open_stream_writer
13
13
  from omlish.lite.cached import cached_nullary
14
- from omlish.lite.check import check_none
15
- from omlish.lite.check import check_not_none
14
+ from omlish.lite.check import check
16
15
  from omlish.lite.deathsig import set_process_deathsig
17
16
  from omlish.lite.inject import Injector
18
17
  from omlish.lite.logs import log
@@ -64,11 +63,11 @@ class _RemoteExecutionMain:
64
63
 
65
64
  @property
66
65
  def _bootstrap(self) -> MainBootstrap:
67
- return check_not_none(self.__bootstrap)
66
+ return check.not_none(self.__bootstrap)
68
67
 
69
68
  @property
70
69
  def _injector(self) -> Injector:
71
- return check_not_none(self.__injector)
70
+ return check.not_none(self.__injector)
72
71
 
73
72
  #
74
73
 
@@ -112,12 +111,12 @@ class _RemoteExecutionMain:
112
111
  #
113
112
 
114
113
  async def _setup(self) -> None:
115
- check_none(self.__bootstrap)
116
- check_none(self.__injector)
114
+ check.none(self.__bootstrap)
115
+ check.none(self.__injector)
117
116
 
118
117
  # Bootstrap
119
118
 
120
- self.__bootstrap = check_not_none(await self._chan.recv_obj(MainBootstrap))
119
+ self.__bootstrap = check.not_none(await self._chan.recv_obj(MainBootstrap))
121
120
 
122
121
  if (prd := self._bootstrap.remote_config.pycharm_remote_debug) is not None:
123
122
  pycharm_debug_connect(prd)
@@ -6,10 +6,7 @@ import itertools
6
6
  import logging
7
7
  import typing as ta
8
8
 
9
- from omlish.lite.check import check_isinstance
10
- from omlish.lite.check import check_none
11
- from omlish.lite.check import check_not_none
12
- from omlish.lite.check import check_state
9
+ from omlish.lite.check import check
13
10
  from omlish.lite.logs import log
14
11
 
15
12
  from ..commands.base import Command
@@ -133,7 +130,7 @@ class _RemoteCommandHandler:
133
130
  ], return_when=asyncio.FIRST_COMPLETED)
134
131
 
135
132
  if recv_task in done:
136
- msg: ta.Optional[_RemoteProtocol.Message] = check_isinstance(
133
+ msg: ta.Optional[_RemoteProtocol.Message] = check.isinstance(
137
134
  recv_task.result(),
138
135
  (_RemoteProtocol.Message, type(None)),
139
136
  )
@@ -202,8 +199,8 @@ class RemoteCommandExecutor(CommandExecutor):
202
199
  #
203
200
 
204
201
  async def start(self) -> None:
205
- check_none(self._loop_task)
206
- check_state(not self._stop.is_set())
202
+ check.none(self._loop_task)
203
+ check.state(not self._stop.is_set())
207
204
  self._loop_task = asyncio.create_task(self._loop())
208
205
 
209
206
  async def aclose(self) -> None:
@@ -239,12 +236,12 @@ class RemoteCommandExecutor(CommandExecutor):
239
236
  ], return_when=asyncio.FIRST_COMPLETED)
240
237
 
241
238
  if queue_task in done:
242
- req = check_isinstance(queue_task.result(), RemoteCommandExecutor._Request)
239
+ req = check.isinstance(queue_task.result(), RemoteCommandExecutor._Request)
243
240
  queue_task = None
244
241
  await self._handle_request(req)
245
242
 
246
243
  if recv_task in done:
247
- msg: ta.Optional[_RemoteProtocol.Message] = check_isinstance(
244
+ msg: ta.Optional[_RemoteProtocol.Message] = check.isinstance(
248
245
  recv_task.result(),
249
246
  (_RemoteProtocol.Message, type(None)),
250
247
  )
@@ -312,7 +309,7 @@ class RemoteCommandExecutor(CommandExecutor):
312
309
  if (e := r.exception) is not None:
313
310
  raise RemoteCommandError(e)
314
311
  else:
315
- return check_not_none(r.output)
312
+ return check.not_none(r.output)
316
313
 
317
314
  # @ta.override
318
315
  async def try_execute(
@@ -8,7 +8,7 @@ import subprocess
8
8
  import typing as ta
9
9
 
10
10
  from omlish.lite.asyncio.subprocesses import asyncio_subprocess_popen
11
- from omlish.lite.check import check_not_none
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
14
14
  from omlish.lite.subprocesses import subprocess_maybe_shell_wrap_exec
@@ -97,8 +97,8 @@ class SubprocessRemoteSpawning(RemoteSpawning):
97
97
  ),
98
98
  timeout=timeout,
99
99
  ) as proc:
100
- stdin = check_not_none(proc.stdin)
101
- stdout = check_not_none(proc.stdout)
100
+ stdin = check.not_none(proc.stdin)
101
+ stdout = check.not_none(proc.stdout)
102
102
 
103
103
  try:
104
104
  yield RemoteSpawning.Spawned(