ominfra 0.0.0.dev150__tar.gz → 0.0.0.dev152__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {ominfra-0.0.0.dev150/ominfra.egg-info → ominfra-0.0.0.dev152}/PKG-INFO +3 -3
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/journald2aws/driver.py +1 -1
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/main.py +5 -7
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/_main.py +1 -1
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/scripts/journald2aws.py +69 -69
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/scripts/manage.py +84 -46
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/scripts/supervisor.py +158 -158
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/main.py +1 -1
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152/ominfra.egg-info}/PKG-INFO +3 -3
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra.egg-info/requires.txt +2 -2
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/pyproject.toml +3 -3
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/LICENSE +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/MANIFEST.in +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/README.rst +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/.manifests.json +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/__about__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/__main__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/auth.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/cli.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/dataclasses.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/journald2aws/main.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/logs.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/aws/metadata.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/gcp/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/clouds/gcp/auth.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/cmds.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/configs.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/journald/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/journald/fields.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/journald/genmessages.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/journald/messages.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/journald/tailer.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/__main__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/bootstrap.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/bootstrap_.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/base.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/execution.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/inject.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/interp.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/marshal.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/commands/subprocess.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/config.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/deploy/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/deploy/command.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/deploy/inject.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/deploy/paths.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/inject.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/marshal.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/channel.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/config.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/connection.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/execution.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/inject.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/payload.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/manage/remote/spawning.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/pyremote.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/scripts/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/ssh.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/LICENSE.txt +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/__main__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/configs.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/dispatchers.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/dispatchersimpl.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/events.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/exceptions.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/groups.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/groupsimpl.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/http.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/inject.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/io.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/pipes.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/privileges.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/process.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/processimpl.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/setup.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/setupimpl.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/signals.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/spawning.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/spawningimpl.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/states.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/supervisor.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/types.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/collections.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/diag.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/fds.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/fs.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/os.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/ostypes.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/signals.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/strings.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/supervisor/utils/users.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/tailscale/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/tailscale/api.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/tailscale/cli.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/threadworkers.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/tools/__init__.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra/tools/listresources.py +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra.egg-info/SOURCES.txt +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra.egg-info/dependency_links.txt +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra.egg-info/entry_points.txt +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/ominfra.egg-info/top_level.txt +0 -0
- {ominfra-0.0.0.dev150 → ominfra-0.0.0.dev152}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ominfra
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev152
|
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.
|
16
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omdev==0.0.0.dev152
|
16
|
+
Requires-Dist: omlish==0.0.0.dev152
|
17
17
|
Provides-Extra: all
|
18
18
|
Requires-Dist: paramiko~=3.5; extra == "all"
|
19
19
|
Requires-Dist: asyncssh~=2.18; extra == "all"
|
@@ -41,8 +41,8 @@ from omlish.lite.cached import cached_nullary
|
|
41
41
|
from omlish.lite.check import check
|
42
42
|
from omlish.lite.contextmanagers import ExitStacked
|
43
43
|
from omlish.lite.logs import log
|
44
|
-
from omlish.lite.pidfile import Pidfile
|
45
44
|
from omlish.lite.runtime import is_debugger_attached
|
45
|
+
from omlish.os.pidfile import Pidfile
|
46
46
|
|
47
47
|
from ....journald.messages import JournalctlMessage # noqa
|
48
48
|
from ....journald.tailer import JournalctlTailerWorker
|
@@ -8,6 +8,7 @@ manage.py -s 'ssh -i /foo/bar.pem foo@bar.baz' -q --python=python3.8
|
|
8
8
|
import asyncio
|
9
9
|
import contextlib
|
10
10
|
import json
|
11
|
+
import sys
|
11
12
|
import typing as ta
|
12
13
|
|
13
14
|
from omlish.argparse.cli import ArgparseCli
|
@@ -31,7 +32,7 @@ from .remote.spawning import RemoteSpawning
|
|
31
32
|
|
32
33
|
class MainCli(ArgparseCli):
|
33
34
|
@argparse_command(
|
34
|
-
argparse_arg('--
|
35
|
+
argparse_arg('--_payload-file'),
|
35
36
|
|
36
37
|
argparse_arg('-s', '--shell'),
|
37
38
|
argparse_arg('-q', '--shell-quote', action='store_true'),
|
@@ -49,10 +50,7 @@ class MainCli(ArgparseCli):
|
|
49
50
|
|
50
51
|
argparse_arg('command', nargs='+'),
|
51
52
|
)
|
52
|
-
def run(self) -> None:
|
53
|
-
asyncio.run(self._async_run())
|
54
|
-
|
55
|
-
async def _async_run(self) -> None:
|
53
|
+
async def run(self) -> None:
|
56
54
|
bs = MainBootstrap(
|
57
55
|
main_config=MainConfig(
|
58
56
|
log_level='DEBUG' if self.args.debug else 'INFO',
|
@@ -61,7 +59,7 @@ class MainCli(ArgparseCli):
|
|
61
59
|
),
|
62
60
|
|
63
61
|
remote_config=RemoteConfig(
|
64
|
-
payload_file=self.args.
|
62
|
+
payload_file=self.args._payload_file, # noqa
|
65
63
|
|
66
64
|
pycharm_remote_debug=PycharmRemoteDebug(
|
67
65
|
port=self.args.pycharm_debug_port,
|
@@ -124,7 +122,7 @@ class MainCli(ArgparseCli):
|
|
124
122
|
|
125
123
|
|
126
124
|
def _main() -> None:
|
127
|
-
MainCli().
|
125
|
+
sys.exit(asyncio.run(MainCli().async_cli_run()))
|
128
126
|
|
129
127
|
|
130
128
|
if __name__ == '__main__':
|
@@ -12,11 +12,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
14
|
from omlish.lite.check import check
|
15
|
-
from omlish.lite.deathsig import set_process_deathsig
|
16
15
|
from omlish.lite.inject import Injector
|
17
16
|
from omlish.lite.logs import log
|
18
17
|
from omlish.lite.marshal import ObjMarshalerManager
|
19
18
|
from omlish.lite.pycharm import pycharm_debug_connect
|
19
|
+
from omlish.os.deathsig import set_process_deathsig
|
20
20
|
|
21
21
|
from ...pyremote import pyremote_bootstrap_finalize
|
22
22
|
from ..bootstrap import MainBootstrap
|
@@ -64,7 +64,7 @@ CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
|
|
64
64
|
# ../../../../omlish/lite/check.py
|
65
65
|
SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
|
66
66
|
CheckMessage = ta.Union[str, ta.Callable[..., ta.Optional[str]], None] # ta.TypeAlias
|
67
|
-
CheckLateConfigureFn = ta.Callable[['Checks'], None]
|
67
|
+
CheckLateConfigureFn = ta.Callable[['Checks'], None] # ta.TypeAlias
|
68
68
|
CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
|
69
69
|
CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
|
70
70
|
CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
|
@@ -79,7 +79,7 @@ ConfigMapping = ta.Mapping[str, ta.Any]
|
|
79
79
|
ThreadWorkerT = ta.TypeVar('ThreadWorkerT', bound='ThreadWorker')
|
80
80
|
|
81
81
|
# ../../../../omlish/lite/subprocesses.py
|
82
|
-
SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull']
|
82
|
+
SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlias
|
83
83
|
|
84
84
|
|
85
85
|
########################################
|
@@ -1439,73 +1439,6 @@ json_dump_compact: ta.Callable[..., bytes] = functools.partial(json.dump, **JSON
|
|
1439
1439
|
json_dumps_compact: ta.Callable[..., str] = functools.partial(json.dumps, **JSON_COMPACT_KWARGS)
|
1440
1440
|
|
1441
1441
|
|
1442
|
-
########################################
|
1443
|
-
# ../../../../../omlish/lite/pidfile.py
|
1444
|
-
|
1445
|
-
|
1446
|
-
class Pidfile:
|
1447
|
-
def __init__(self, path: str) -> None:
|
1448
|
-
super().__init__()
|
1449
|
-
self._path = path
|
1450
|
-
|
1451
|
-
_f: ta.TextIO
|
1452
|
-
|
1453
|
-
def __repr__(self) -> str:
|
1454
|
-
return f'{self.__class__.__name__}({self._path!r})'
|
1455
|
-
|
1456
|
-
def __enter__(self) -> 'Pidfile':
|
1457
|
-
fd = os.open(self._path, os.O_RDWR | os.O_CREAT, 0o600)
|
1458
|
-
try:
|
1459
|
-
os.set_inheritable(fd, True)
|
1460
|
-
f = os.fdopen(fd, 'r+')
|
1461
|
-
except Exception:
|
1462
|
-
try:
|
1463
|
-
os.close(fd)
|
1464
|
-
except Exception: # noqa
|
1465
|
-
pass
|
1466
|
-
raise
|
1467
|
-
self._f = f
|
1468
|
-
return self
|
1469
|
-
|
1470
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
1471
|
-
if hasattr(self, '_f'):
|
1472
|
-
self._f.close()
|
1473
|
-
del self._f
|
1474
|
-
|
1475
|
-
def try_lock(self) -> bool:
|
1476
|
-
try:
|
1477
|
-
fcntl.flock(self._f, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
1478
|
-
return True
|
1479
|
-
except OSError:
|
1480
|
-
return False
|
1481
|
-
|
1482
|
-
def ensure_locked(self) -> None:
|
1483
|
-
if not self.try_lock():
|
1484
|
-
raise RuntimeError('Could not get lock')
|
1485
|
-
|
1486
|
-
def write(self, pid: ta.Optional[int] = None) -> None:
|
1487
|
-
self.ensure_locked()
|
1488
|
-
if pid is None:
|
1489
|
-
pid = os.getpid()
|
1490
|
-
self._f.write(f'{pid}\n')
|
1491
|
-
self._f.flush()
|
1492
|
-
|
1493
|
-
def clear(self) -> None:
|
1494
|
-
self.ensure_locked()
|
1495
|
-
self._f.seek(0)
|
1496
|
-
self._f.truncate()
|
1497
|
-
|
1498
|
-
def read(self) -> int:
|
1499
|
-
if self.try_lock():
|
1500
|
-
raise RuntimeError('Got lock')
|
1501
|
-
self._f.seek(0)
|
1502
|
-
return int(self._f.read())
|
1503
|
-
|
1504
|
-
def kill(self, sig: int = signal.SIGTERM) -> None:
|
1505
|
-
pid = self.read()
|
1506
|
-
os.kill(pid, sig) # FIXME: Still racy
|
1507
|
-
|
1508
|
-
|
1509
1442
|
########################################
|
1510
1443
|
# ../../../../../omlish/lite/reflect.py
|
1511
1444
|
|
@@ -1628,6 +1561,73 @@ def format_num_bytes(num_bytes: int) -> str:
|
|
1628
1561
|
return f'{num_bytes / 1024 ** (len(FORMAT_NUM_BYTES_SUFFIXES) - 1):.2f}{FORMAT_NUM_BYTES_SUFFIXES[-1]}'
|
1629
1562
|
|
1630
1563
|
|
1564
|
+
########################################
|
1565
|
+
# ../../../../../omlish/os/pidfile.py
|
1566
|
+
|
1567
|
+
|
1568
|
+
class Pidfile:
|
1569
|
+
def __init__(self, path: str) -> None:
|
1570
|
+
super().__init__()
|
1571
|
+
self._path = path
|
1572
|
+
|
1573
|
+
_f: ta.TextIO
|
1574
|
+
|
1575
|
+
def __repr__(self) -> str:
|
1576
|
+
return f'{self.__class__.__name__}({self._path!r})'
|
1577
|
+
|
1578
|
+
def __enter__(self) -> 'Pidfile':
|
1579
|
+
fd = os.open(self._path, os.O_RDWR | os.O_CREAT, 0o600)
|
1580
|
+
try:
|
1581
|
+
os.set_inheritable(fd, True)
|
1582
|
+
f = os.fdopen(fd, 'r+')
|
1583
|
+
except Exception:
|
1584
|
+
try:
|
1585
|
+
os.close(fd)
|
1586
|
+
except Exception: # noqa
|
1587
|
+
pass
|
1588
|
+
raise
|
1589
|
+
self._f = f
|
1590
|
+
return self
|
1591
|
+
|
1592
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
1593
|
+
if hasattr(self, '_f'):
|
1594
|
+
self._f.close()
|
1595
|
+
del self._f
|
1596
|
+
|
1597
|
+
def try_lock(self) -> bool:
|
1598
|
+
try:
|
1599
|
+
fcntl.flock(self._f, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
1600
|
+
return True
|
1601
|
+
except OSError:
|
1602
|
+
return False
|
1603
|
+
|
1604
|
+
def ensure_locked(self) -> None:
|
1605
|
+
if not self.try_lock():
|
1606
|
+
raise RuntimeError('Could not get lock')
|
1607
|
+
|
1608
|
+
def write(self, pid: ta.Optional[int] = None) -> None:
|
1609
|
+
self.ensure_locked()
|
1610
|
+
if pid is None:
|
1611
|
+
pid = os.getpid()
|
1612
|
+
self._f.write(f'{pid}\n')
|
1613
|
+
self._f.flush()
|
1614
|
+
|
1615
|
+
def clear(self) -> None:
|
1616
|
+
self.ensure_locked()
|
1617
|
+
self._f.seek(0)
|
1618
|
+
self._f.truncate()
|
1619
|
+
|
1620
|
+
def read(self) -> int:
|
1621
|
+
if self.try_lock():
|
1622
|
+
raise RuntimeError('Got lock')
|
1623
|
+
self._f.seek(0)
|
1624
|
+
return int(self._f.read())
|
1625
|
+
|
1626
|
+
def kill(self, sig: int = signal.SIGTERM) -> None:
|
1627
|
+
pid = self.read()
|
1628
|
+
os.kill(pid, sig) # FIXME: Still racy
|
1629
|
+
|
1630
|
+
|
1631
1631
|
########################################
|
1632
1632
|
# ../../auth.py
|
1633
1633
|
"""
|
@@ -78,7 +78,7 @@ CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
|
|
78
78
|
# ../../omlish/lite/check.py
|
79
79
|
SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
|
80
80
|
CheckMessage = ta.Union[str, ta.Callable[..., ta.Optional[str]], None] # ta.TypeAlias
|
81
|
-
CheckLateConfigureFn = ta.Callable[['Checks'], None]
|
81
|
+
CheckLateConfigureFn = ta.Callable[['Checks'], None] # ta.TypeAlias
|
82
82
|
CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
|
83
83
|
CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
|
84
84
|
CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
|
@@ -103,7 +103,7 @@ InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
|
|
103
103
|
InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
|
104
104
|
|
105
105
|
# ../../omlish/lite/subprocesses.py
|
106
|
-
SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull']
|
106
|
+
SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlias
|
107
107
|
|
108
108
|
|
109
109
|
########################################
|
@@ -1611,30 +1611,6 @@ class Checks:
|
|
1611
1611
|
check = Checks()
|
1612
1612
|
|
1613
1613
|
|
1614
|
-
########################################
|
1615
|
-
# ../../../omlish/lite/deathsig.py
|
1616
|
-
|
1617
|
-
|
1618
|
-
LINUX_PR_SET_PDEATHSIG = 1 # Second arg is a signal
|
1619
|
-
LINUX_PR_GET_PDEATHSIG = 2 # Second arg is a ptr to return the signal
|
1620
|
-
|
1621
|
-
|
1622
|
-
def set_process_deathsig(sig: int) -> bool:
|
1623
|
-
if sys.platform == 'linux':
|
1624
|
-
libc = ct.CDLL('libc.so.6')
|
1625
|
-
|
1626
|
-
# int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
1627
|
-
libc.prctl.restype = ct.c_int
|
1628
|
-
libc.prctl.argtypes = [ct.c_int, ct.c_ulong, ct.c_ulong, ct.c_ulong, ct.c_ulong]
|
1629
|
-
|
1630
|
-
libc.prctl(LINUX_PR_SET_PDEATHSIG, sig, 0, 0, 0, 0)
|
1631
|
-
|
1632
|
-
return True
|
1633
|
-
|
1634
|
-
else:
|
1635
|
-
return False
|
1636
|
-
|
1637
|
-
|
1638
1614
|
########################################
|
1639
1615
|
# ../../../omlish/lite/json.py
|
1640
1616
|
|
@@ -1880,6 +1856,30 @@ def format_num_bytes(num_bytes: int) -> str:
|
|
1880
1856
|
return f'{num_bytes / 1024 ** (len(FORMAT_NUM_BYTES_SUFFIXES) - 1):.2f}{FORMAT_NUM_BYTES_SUFFIXES[-1]}'
|
1881
1857
|
|
1882
1858
|
|
1859
|
+
########################################
|
1860
|
+
# ../../../omlish/os/deathsig.py
|
1861
|
+
|
1862
|
+
|
1863
|
+
LINUX_PR_SET_PDEATHSIG = 1 # Second arg is a signal
|
1864
|
+
LINUX_PR_GET_PDEATHSIG = 2 # Second arg is a ptr to return the signal
|
1865
|
+
|
1866
|
+
|
1867
|
+
def set_process_deathsig(sig: int) -> bool:
|
1868
|
+
if sys.platform == 'linux':
|
1869
|
+
libc = ct.CDLL('libc.so.6')
|
1870
|
+
|
1871
|
+
# int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
1872
|
+
libc.prctl.restype = ct.c_int
|
1873
|
+
libc.prctl.argtypes = [ct.c_int, ct.c_ulong, ct.c_ulong, ct.c_ulong, ct.c_ulong]
|
1874
|
+
|
1875
|
+
libc.prctl(LINUX_PR_SET_PDEATHSIG, sig, 0, 0, 0, 0)
|
1876
|
+
|
1877
|
+
return True
|
1878
|
+
|
1879
|
+
else:
|
1880
|
+
return False
|
1881
|
+
|
1882
|
+
|
1883
1883
|
########################################
|
1884
1884
|
# ../../../omdev/packaging/specifiers.py
|
1885
1885
|
# Copyright (c) Donald Stufft and individual contributors.
|
@@ -2618,6 +2618,8 @@ def get_remote_payload_src(
|
|
2618
2618
|
TODO:
|
2619
2619
|
- default command
|
2620
2620
|
- auto match all underscores to hyphens
|
2621
|
+
- pre-run, post-run hooks
|
2622
|
+
- exitstack?
|
2621
2623
|
"""
|
2622
2624
|
|
2623
2625
|
|
@@ -2737,11 +2739,12 @@ class ArgparseCli:
|
|
2737
2739
|
|
2738
2740
|
self._args, self._unknown_args = self.get_parser().parse_known_args(self._argv)
|
2739
2741
|
|
2742
|
+
#
|
2743
|
+
|
2740
2744
|
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
2741
2745
|
super().__init_subclass__(**kwargs)
|
2742
2746
|
|
2743
2747
|
ns = cls.__dict__
|
2744
|
-
|
2745
2748
|
objs = {}
|
2746
2749
|
mro = cls.__mro__[::-1]
|
2747
2750
|
for bns in [bcls.__dict__ for bcls in reversed(mro)] + [ns]:
|
@@ -2754,24 +2757,33 @@ class ArgparseCli:
|
|
2754
2757
|
elif k in objs:
|
2755
2758
|
del [k]
|
2756
2759
|
|
2760
|
+
#
|
2761
|
+
|
2757
2762
|
anns = ta.get_type_hints(_ArgparseCliAnnotationBox({
|
2758
2763
|
**{k: v for bcls in reversed(mro) for k, v in getattr(bcls, '__annotations__', {}).items()},
|
2759
2764
|
**ns.get('__annotations__', {}),
|
2760
2765
|
}), globalns=ns.get('__globals__', {}))
|
2761
2766
|
|
2767
|
+
#
|
2768
|
+
|
2762
2769
|
if '_parser' in ns:
|
2763
2770
|
parser = check.isinstance(ns['_parser'], argparse.ArgumentParser)
|
2764
2771
|
else:
|
2765
2772
|
parser = argparse.ArgumentParser()
|
2766
2773
|
setattr(cls, '_parser', parser)
|
2767
2774
|
|
2775
|
+
#
|
2776
|
+
|
2768
2777
|
subparsers = parser.add_subparsers()
|
2778
|
+
|
2769
2779
|
for att, obj in objs.items():
|
2770
2780
|
if isinstance(obj, ArgparseCommand):
|
2771
2781
|
if obj.parent is not None:
|
2772
2782
|
raise NotImplementedError
|
2783
|
+
|
2773
2784
|
for cn in [obj.name, *(obj.aliases or [])]:
|
2774
|
-
|
2785
|
+
subparser = subparsers.add_parser(cn)
|
2786
|
+
|
2775
2787
|
for arg in (obj.args or []):
|
2776
2788
|
if (
|
2777
2789
|
len(arg.args) == 1 and
|
@@ -2779,29 +2791,34 @@ class ArgparseCli:
|
|
2779
2791
|
not (n := check.isinstance(arg.args[0], str)).startswith('-') and
|
2780
2792
|
'metavar' not in arg.kwargs
|
2781
2793
|
):
|
2782
|
-
|
2794
|
+
subparser.add_argument(
|
2783
2795
|
n.replace('-', '_'),
|
2784
2796
|
**arg.kwargs,
|
2785
2797
|
metavar=n,
|
2786
2798
|
)
|
2787
2799
|
else:
|
2788
|
-
|
2789
|
-
|
2800
|
+
subparser.add_argument(*arg.args, **arg.kwargs)
|
2801
|
+
|
2802
|
+
subparser.set_defaults(_cmd=obj)
|
2790
2803
|
|
2791
2804
|
elif isinstance(obj, ArgparseArg):
|
2792
2805
|
if att in anns:
|
2793
|
-
|
2794
|
-
obj.kwargs = {**
|
2806
|
+
ann_kwargs = _get_argparse_arg_ann_kwargs(anns[att])
|
2807
|
+
obj.kwargs = {**ann_kwargs, **obj.kwargs}
|
2808
|
+
|
2795
2809
|
if not obj.dest:
|
2796
2810
|
if 'dest' in obj.kwargs:
|
2797
2811
|
obj.dest = obj.kwargs['dest']
|
2798
2812
|
else:
|
2799
2813
|
obj.dest = obj.kwargs['dest'] = att # type: ignore
|
2814
|
+
|
2800
2815
|
parser.add_argument(*obj.args, **obj.kwargs)
|
2801
2816
|
|
2802
2817
|
else:
|
2803
2818
|
raise TypeError(obj)
|
2804
2819
|
|
2820
|
+
#
|
2821
|
+
|
2805
2822
|
_parser: ta.ClassVar[argparse.ArgumentParser]
|
2806
2823
|
|
2807
2824
|
@classmethod
|
@@ -2820,10 +2837,12 @@ class ArgparseCli:
|
|
2820
2837
|
def unknown_args(self) -> ta.Sequence[str]:
|
2821
2838
|
return self._unknown_args
|
2822
2839
|
|
2823
|
-
|
2824
|
-
|
2840
|
+
#
|
2841
|
+
|
2842
|
+
def _bind_cli_cmd(self, cmd: ArgparseCommand) -> ta.Callable:
|
2843
|
+
return cmd.__get__(self, type(self))
|
2825
2844
|
|
2826
|
-
def
|
2845
|
+
def prepare_cli_run(self) -> ta.Optional[ta.Callable]:
|
2827
2846
|
cmd = getattr(self.args, '_cmd', None)
|
2828
2847
|
|
2829
2848
|
if self._unknown_args and not (cmd is not None and cmd.accepts_unknown):
|
@@ -2835,12 +2854,34 @@ class ArgparseCli:
|
|
2835
2854
|
|
2836
2855
|
if cmd is None:
|
2837
2856
|
self.get_parser().print_help()
|
2857
|
+
return None
|
2858
|
+
|
2859
|
+
return self._bind_cli_cmd(cmd)
|
2860
|
+
|
2861
|
+
#
|
2862
|
+
|
2863
|
+
def cli_run(self) -> ta.Optional[int]:
|
2864
|
+
if (fn := self.prepare_cli_run()) is None:
|
2838
2865
|
return 0
|
2839
2866
|
|
2840
|
-
return
|
2867
|
+
return fn()
|
2841
2868
|
|
2842
|
-
def
|
2843
|
-
sys.exit(rc if isinstance(rc := self(), int) else 0)
|
2869
|
+
def cli_run_and_exit(self) -> ta.NoReturn:
|
2870
|
+
sys.exit(rc if isinstance(rc := self.cli_run(), int) else 0)
|
2871
|
+
|
2872
|
+
def __call__(self, *, exit: bool = False) -> ta.Optional[int]: # noqa
|
2873
|
+
if exit:
|
2874
|
+
return self.cli_run_and_exit()
|
2875
|
+
else:
|
2876
|
+
return self.cli_run()
|
2877
|
+
|
2878
|
+
#
|
2879
|
+
|
2880
|
+
async def async_cli_run(self) -> ta.Optional[int]:
|
2881
|
+
if (fn := self.prepare_cli_run()) is None:
|
2882
|
+
return 0
|
2883
|
+
|
2884
|
+
return await fn()
|
2844
2885
|
|
2845
2886
|
|
2846
2887
|
########################################
|
@@ -6975,7 +7016,7 @@ def main_bootstrap(bs: MainBootstrap) -> Injector:
|
|
6975
7016
|
|
6976
7017
|
class MainCli(ArgparseCli):
|
6977
7018
|
@argparse_command(
|
6978
|
-
argparse_arg('--
|
7019
|
+
argparse_arg('--_payload-file'),
|
6979
7020
|
|
6980
7021
|
argparse_arg('-s', '--shell'),
|
6981
7022
|
argparse_arg('-q', '--shell-quote', action='store_true'),
|
@@ -6993,10 +7034,7 @@ class MainCli(ArgparseCli):
|
|
6993
7034
|
|
6994
7035
|
argparse_arg('command', nargs='+'),
|
6995
7036
|
)
|
6996
|
-
def run(self) -> None:
|
6997
|
-
asyncio.run(self._async_run())
|
6998
|
-
|
6999
|
-
async def _async_run(self) -> None:
|
7037
|
+
async def run(self) -> None:
|
7000
7038
|
bs = MainBootstrap(
|
7001
7039
|
main_config=MainConfig(
|
7002
7040
|
log_level='DEBUG' if self.args.debug else 'INFO',
|
@@ -7005,7 +7043,7 @@ class MainCli(ArgparseCli):
|
|
7005
7043
|
),
|
7006
7044
|
|
7007
7045
|
remote_config=RemoteConfig(
|
7008
|
-
payload_file=self.args.
|
7046
|
+
payload_file=self.args._payload_file, # noqa
|
7009
7047
|
|
7010
7048
|
pycharm_remote_debug=PycharmRemoteDebug(
|
7011
7049
|
port=self.args.pycharm_debug_port,
|
@@ -7068,7 +7106,7 @@ class MainCli(ArgparseCli):
|
|
7068
7106
|
|
7069
7107
|
|
7070
7108
|
def _main() -> None:
|
7071
|
-
MainCli().
|
7109
|
+
sys.exit(asyncio.run(MainCli().async_cli_run()))
|
7072
7110
|
|
7073
7111
|
|
7074
7112
|
if __name__ == '__main__':
|