ominfra 0.0.0.dev142__py3-none-any.whl → 0.0.0.dev144__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. ominfra/manage/__init__.py +10 -0
  2. ominfra/manage/__main__.py +4 -0
  3. ominfra/manage/bootstrap.py +11 -0
  4. ominfra/manage/bootstrap_.py +18 -0
  5. ominfra/manage/commands/base.py +133 -1
  6. ominfra/manage/commands/execution.py +23 -0
  7. ominfra/manage/commands/inject.py +122 -0
  8. ominfra/manage/commands/marshal.py +26 -0
  9. ominfra/manage/config.py +10 -0
  10. ominfra/manage/deploy/__init__.py +0 -0
  11. ominfra/manage/deploy/command.py +23 -0
  12. ominfra/manage/deploy/inject.py +19 -0
  13. ominfra/manage/inject.py +58 -0
  14. ominfra/manage/main.py +64 -90
  15. ominfra/manage/marshal.py +12 -0
  16. ominfra/manage/remote/__init__.py +0 -0
  17. ominfra/manage/{protocol.py → remote/channel.py} +9 -2
  18. ominfra/manage/remote/config.py +12 -0
  19. ominfra/manage/remote/execution.py +193 -0
  20. ominfra/manage/remote/inject.py +29 -0
  21. ominfra/manage/{payload.py → remote/payload.py} +7 -1
  22. ominfra/manage/{spawning.py → remote/spawning.py} +29 -29
  23. ominfra/pyremote.py +40 -3
  24. ominfra/scripts/journald2aws.py +98 -50
  25. ominfra/scripts/manage.py +2025 -295
  26. ominfra/scripts/supervisor.py +99 -50
  27. ominfra/supervisor/inject.py +2 -1
  28. {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/METADATA +3 -3
  29. {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/RECORD +33 -17
  30. {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/LICENSE +0 -0
  31. {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/WHEEL +0 -0
  32. {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/entry_points.txt +0 -0
  33. {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/top_level.txt +0 -0
@@ -10,4 +10,14 @@ Jobs:
10
10
  - system service manager - systemd / supervisor
11
11
  - users
12
12
  - firewall
13
+
14
+ Deploy:
15
+ - User
16
+ - Dirs
17
+ - GlobalNginx
18
+ - GlobalSupervisor
19
+ - Repo
20
+ - Venv
21
+ - Supervisor
22
+ - Nginx
13
23
  """
@@ -0,0 +1,4 @@
1
+ if __name__ == '__main__':
2
+ from .main import _main # noqa
3
+
4
+ _main()
@@ -0,0 +1,11 @@
1
+ import dataclasses as dc
2
+
3
+ from .config import MainConfig
4
+ from .remote.config import RemoteConfig
5
+
6
+
7
+ @dc.dataclass(frozen=True)
8
+ class MainBootstrap:
9
+ main_config: MainConfig = MainConfig()
10
+
11
+ remote_config: RemoteConfig = RemoteConfig()
@@ -0,0 +1,18 @@
1
+ from omlish.lite.inject import Injector
2
+ from omlish.lite.inject import inj
3
+ from omlish.lite.logs import configure_standard_logging
4
+
5
+ from .bootstrap import MainBootstrap
6
+ from .inject import bind_main
7
+
8
+
9
+ def main_bootstrap(bs: MainBootstrap) -> Injector:
10
+ if (log_level := bs.main_config.log_level) is not None:
11
+ configure_standard_logging(log_level)
12
+
13
+ injector = inj.create_injector(bind_main( # noqa
14
+ main_config=bs.main_config,
15
+ remote_config=bs.remote_config,
16
+ ))
17
+
18
+ return injector
@@ -1,8 +1,13 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  import abc
3
3
  import dataclasses as dc
4
+ import logging
5
+ import traceback
4
6
  import typing as ta
5
7
 
8
+ from omlish.lite.check import check_isinstance
9
+ from omlish.lite.strings import snake_case
10
+
6
11
 
7
12
  CommandT = ta.TypeVar('CommandT', bound='Command')
8
13
  CommandOutputT = ta.TypeVar('CommandOutputT', bound='Command.Output')
@@ -17,11 +22,138 @@ class Command(abc.ABC, ta.Generic[CommandOutputT]):
17
22
  class Output(abc.ABC): # noqa
18
23
  pass
19
24
 
25
+ @ta.final
26
+ def execute(self, executor: 'CommandExecutor') -> CommandOutputT:
27
+ return check_isinstance(executor.execute(self), self.Output) # type: ignore[return-value]
28
+
20
29
 
21
30
  ##
22
31
 
23
32
 
33
+ @dc.dataclass(frozen=True)
34
+ class CommandException:
35
+ name: str
36
+ repr: str
37
+
38
+ traceback: ta.Optional[str] = None
39
+
40
+ exc: ta.Optional[ta.Any] = None # Exception
41
+
42
+ cmd: ta.Optional[Command] = None
43
+
44
+ @classmethod
45
+ def of(
46
+ cls,
47
+ exc: Exception,
48
+ *,
49
+ omit_exc_object: bool = False,
50
+
51
+ cmd: ta.Optional[Command] = None,
52
+ ) -> 'CommandException':
53
+ return CommandException(
54
+ name=type(exc).__qualname__,
55
+ repr=repr(exc),
56
+
57
+ traceback=(
58
+ ''.join(traceback.format_tb(exc.__traceback__))
59
+ if getattr(exc, '__traceback__', None) is not None else None
60
+ ),
61
+
62
+ exc=None if omit_exc_object else exc,
63
+
64
+ cmd=cmd,
65
+ )
66
+
67
+
68
+ class CommandOutputOrException(abc.ABC, ta.Generic[CommandOutputT]):
69
+ @property
70
+ @abc.abstractmethod
71
+ def output(self) -> ta.Optional[CommandOutputT]:
72
+ raise NotImplementedError
73
+
74
+ @property
75
+ @abc.abstractmethod
76
+ def exception(self) -> ta.Optional[CommandException]:
77
+ raise NotImplementedError
78
+
79
+
80
+ @dc.dataclass(frozen=True)
81
+ class CommandOutputOrExceptionData(CommandOutputOrException):
82
+ output: ta.Optional[Command.Output] = None
83
+ exception: ta.Optional[CommandException] = None
84
+
85
+
24
86
  class CommandExecutor(abc.ABC, ta.Generic[CommandT, CommandOutputT]):
25
87
  @abc.abstractmethod
26
- def execute(self, i: CommandT) -> CommandOutputT:
88
+ def execute(self, cmd: CommandT) -> CommandOutputT:
27
89
  raise NotImplementedError
90
+
91
+ def try_execute(
92
+ self,
93
+ cmd: CommandT,
94
+ *,
95
+ log: ta.Optional[logging.Logger] = None,
96
+ omit_exc_object: bool = False,
97
+ ) -> CommandOutputOrException[CommandOutputT]:
98
+ try:
99
+ o = self.execute(cmd)
100
+
101
+ except Exception as e: # noqa
102
+ if log is not None:
103
+ log.exception('Exception executing command: %r', type(cmd))
104
+
105
+ return CommandOutputOrExceptionData(exception=CommandException.of(
106
+ e,
107
+ omit_exc_object=omit_exc_object,
108
+ cmd=cmd,
109
+ ))
110
+
111
+ else:
112
+ return CommandOutputOrExceptionData(output=o)
113
+
114
+
115
+ ##
116
+
117
+
118
+ @dc.dataclass(frozen=True)
119
+ class CommandRegistration:
120
+ command_cls: ta.Type[Command]
121
+
122
+ name: ta.Optional[str] = None
123
+
124
+ @property
125
+ def name_or_default(self) -> str:
126
+ if not (cls_name := self.command_cls.__name__).endswith('Command'):
127
+ raise NameError(cls_name)
128
+ return snake_case(cls_name[:-len('Command')])
129
+
130
+
131
+ CommandRegistrations = ta.NewType('CommandRegistrations', ta.Sequence[CommandRegistration])
132
+
133
+
134
+ ##
135
+
136
+
137
+ @dc.dataclass(frozen=True)
138
+ class CommandExecutorRegistration:
139
+ command_cls: ta.Type[Command]
140
+ executor_cls: ta.Type[CommandExecutor]
141
+
142
+
143
+ CommandExecutorRegistrations = ta.NewType('CommandExecutorRegistrations', ta.Sequence[CommandExecutorRegistration])
144
+
145
+
146
+ ##
147
+
148
+
149
+ CommandNameMap = ta.NewType('CommandNameMap', ta.Mapping[str, ta.Type[Command]])
150
+
151
+
152
+ def build_command_name_map(crs: CommandRegistrations) -> CommandNameMap:
153
+ dct: ta.Dict[str, ta.Type[Command]] = {}
154
+ cr: CommandRegistration
155
+ for cr in crs:
156
+ if (name := cr.name_or_default) in dct:
157
+ raise NameError(name)
158
+ dct[name] = cr.command_cls
159
+ return CommandNameMap(dct)
@@ -0,0 +1,23 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from .base import Command
5
+ from .base import CommandExecutor
6
+
7
+
8
+ CommandExecutorMap = ta.NewType('CommandExecutorMap', ta.Mapping[ta.Type[Command], CommandExecutor])
9
+
10
+
11
+ class CommandExecutionService(CommandExecutor):
12
+ def __init__(
13
+ self,
14
+ *,
15
+ command_executors: CommandExecutorMap,
16
+ ) -> None:
17
+ super().__init__()
18
+
19
+ self._command_executors = command_executors
20
+
21
+ def execute(self, cmd: Command) -> Command.Output:
22
+ ce: CommandExecutor = self._command_executors[type(cmd)]
23
+ return ce.execute(cmd)
@@ -0,0 +1,122 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import functools
4
+ import typing as ta
5
+
6
+ from omlish.lite.inject import Injector
7
+ from omlish.lite.inject import InjectorBindingOrBindings
8
+ from omlish.lite.inject import InjectorBindings
9
+ from omlish.lite.inject import inj
10
+
11
+ from ..config import MainConfig
12
+ from ..marshal import ObjMarshalerInstaller
13
+ from .base import Command
14
+ from .base import CommandExecutor
15
+ from .base import CommandExecutorRegistration
16
+ from .base import CommandExecutorRegistrations
17
+ from .base import CommandNameMap
18
+ from .base import CommandRegistration
19
+ from .base import CommandRegistrations
20
+ from .base import build_command_name_map
21
+ from .execution import CommandExecutionService
22
+ from .execution import CommandExecutorMap
23
+ from .marshal import install_command_marshaling
24
+ from .subprocess import SubprocessCommand
25
+ from .subprocess import SubprocessCommandExecutor
26
+
27
+
28
+ ##
29
+
30
+
31
+ def bind_command(
32
+ command_cls: ta.Type[Command],
33
+ executor_cls: ta.Optional[ta.Type[CommandExecutor]],
34
+ ) -> InjectorBindings:
35
+ lst: ta.List[InjectorBindingOrBindings] = [
36
+ inj.bind(CommandRegistration(command_cls), array=True),
37
+ ]
38
+
39
+ if executor_cls is not None:
40
+ lst.extend([
41
+ inj.bind(executor_cls, singleton=True),
42
+ inj.bind(CommandExecutorRegistration(command_cls, executor_cls), array=True),
43
+ ])
44
+
45
+ return inj.as_bindings(*lst)
46
+
47
+
48
+ ##
49
+
50
+
51
+ @dc.dataclass(frozen=True)
52
+ class _FactoryCommandExecutor(CommandExecutor):
53
+ factory: ta.Callable[[], CommandExecutor]
54
+
55
+ def execute(self, i: Command) -> Command.Output:
56
+ return self.factory().execute(i)
57
+
58
+
59
+ ##
60
+
61
+
62
+ def bind_commands(
63
+ *,
64
+ main_config: MainConfig,
65
+ ) -> InjectorBindings:
66
+ lst: ta.List[InjectorBindingOrBindings] = [
67
+ inj.bind_array(CommandRegistration),
68
+ inj.bind_array_type(CommandRegistration, CommandRegistrations),
69
+
70
+ inj.bind_array(CommandExecutorRegistration),
71
+ inj.bind_array_type(CommandExecutorRegistration, CommandExecutorRegistrations),
72
+
73
+ inj.bind(build_command_name_map, singleton=True),
74
+ ]
75
+
76
+ #
77
+
78
+ def provide_obj_marshaler_installer(cmds: CommandNameMap) -> ObjMarshalerInstaller:
79
+ return ObjMarshalerInstaller(functools.partial(install_command_marshaling, cmds))
80
+
81
+ lst.append(inj.bind(provide_obj_marshaler_installer, array=True))
82
+
83
+ #
84
+
85
+ def provide_command_executor_map(
86
+ injector: Injector,
87
+ crs: CommandExecutorRegistrations,
88
+ ) -> CommandExecutorMap:
89
+ dct: ta.Dict[ta.Type[Command], CommandExecutor] = {}
90
+
91
+ cr: CommandExecutorRegistration
92
+ for cr in crs:
93
+ if cr.command_cls in dct:
94
+ raise KeyError(cr.command_cls)
95
+
96
+ factory = functools.partial(injector.provide, cr.executor_cls)
97
+ if main_config.debug:
98
+ ce = factory()
99
+ else:
100
+ ce = _FactoryCommandExecutor(factory)
101
+
102
+ dct[cr.command_cls] = ce
103
+
104
+ return CommandExecutorMap(dct)
105
+
106
+ lst.extend([
107
+ inj.bind(provide_command_executor_map, singleton=True),
108
+
109
+ inj.bind(CommandExecutionService, singleton=True, eager=main_config.debug),
110
+ inj.bind(CommandExecutor, to_key=CommandExecutionService),
111
+ ])
112
+
113
+ #
114
+
115
+ for command_cls, executor_cls in [
116
+ (SubprocessCommand, SubprocessCommandExecutor),
117
+ ]:
118
+ lst.append(bind_command(command_cls, executor_cls))
119
+
120
+ #
121
+
122
+ return inj.as_bindings(*lst)
@@ -0,0 +1,26 @@
1
+ from omlish.lite.marshal import ObjMarshalerManager
2
+ from omlish.lite.marshal import PolymorphicObjMarshaler
3
+
4
+ from .base import Command
5
+ from .base import CommandNameMap
6
+
7
+
8
+ def install_command_marshaling(
9
+ cmds: CommandNameMap,
10
+ msh: ObjMarshalerManager,
11
+ ) -> None:
12
+ for fn in [
13
+ lambda c: c,
14
+ lambda c: c.Output,
15
+ ]:
16
+ msh.register_opj_marshaler(
17
+ fn(Command),
18
+ PolymorphicObjMarshaler.of([
19
+ PolymorphicObjMarshaler.Impl(
20
+ fn(cmd),
21
+ name,
22
+ msh.get_obj_marshaler(fn(cmd)),
23
+ )
24
+ for name, cmd in cmds.items()
25
+ ]),
26
+ )
@@ -0,0 +1,10 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ @dc.dataclass(frozen=True)
7
+ class MainConfig:
8
+ log_level: ta.Optional[str] = 'INFO'
9
+
10
+ debug: bool = False
File without changes
@@ -0,0 +1,23 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+
4
+ from ..commands.base import Command
5
+ from ..commands.base import CommandExecutor
6
+
7
+
8
+ ##
9
+
10
+
11
+ @dc.dataclass(frozen=True)
12
+ class DeployCommand(Command['DeployCommand.Output']):
13
+ @dc.dataclass(frozen=True)
14
+ class Output(Command.Output):
15
+ pass
16
+
17
+
18
+ ##
19
+
20
+
21
+ class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
22
+ def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
23
+ return DeployCommand.Output()
@@ -0,0 +1,19 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import InjectorBindingOrBindings
5
+ from omlish.lite.inject import InjectorBindings
6
+ from omlish.lite.inject import inj
7
+
8
+ from ..commands.inject import bind_command
9
+ from .command import DeployCommand
10
+ from .command import DeployCommandExecutor
11
+
12
+
13
+ def bind_deploy(
14
+ ) -> InjectorBindings:
15
+ lst: ta.List[InjectorBindingOrBindings] = [
16
+ bind_command(DeployCommand, DeployCommandExecutor),
17
+ ]
18
+
19
+ return inj.as_bindings(*lst)
@@ -0,0 +1,58 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import InjectorBindingOrBindings
5
+ from omlish.lite.inject import InjectorBindings
6
+ from omlish.lite.inject import inj
7
+ from omlish.lite.marshal import ObjMarshalerManager
8
+
9
+ from .commands.inject import bind_commands
10
+ from .config import MainConfig
11
+ from .deploy.inject import bind_deploy
12
+ from .marshal import ObjMarshalerInstaller
13
+ from .marshal import ObjMarshalerInstallers
14
+ from .remote.config import RemoteConfig
15
+ from .remote.inject import bind_remote
16
+
17
+
18
+ ##
19
+
20
+
21
+ def bind_main(
22
+ *,
23
+ main_config: MainConfig,
24
+ remote_config: RemoteConfig,
25
+ ) -> InjectorBindings:
26
+ lst: ta.List[InjectorBindingOrBindings] = [
27
+ inj.bind(main_config),
28
+
29
+ bind_commands(
30
+ main_config=main_config,
31
+ ),
32
+
33
+ bind_remote(
34
+ remote_config=remote_config,
35
+ ),
36
+
37
+ bind_deploy(),
38
+ ]
39
+
40
+ #
41
+
42
+ def build_obj_marshaler_manager(insts: ObjMarshalerInstallers) -> ObjMarshalerManager:
43
+ msh = ObjMarshalerManager()
44
+ inst: ObjMarshalerInstaller
45
+ for inst in insts:
46
+ inst.fn(msh)
47
+ return msh
48
+
49
+ lst.extend([
50
+ inj.bind(build_obj_marshaler_manager, singleton=True),
51
+
52
+ inj.bind_array(ObjMarshalerInstaller),
53
+ inj.bind_array_type(ObjMarshalerInstaller, ObjMarshalerInstallers),
54
+ ])
55
+
56
+ #
57
+
58
+ return inj.as_bindings(*lst)
ominfra/manage/main.py CHANGED
@@ -5,72 +5,24 @@
5
5
  manage.py -s 'docker run -i python:3.12'
6
6
  manage.py -s 'ssh -i /foo/bar.pem foo@bar.baz' -q --python=python3.8
7
7
  """
8
- from omlish.lite.marshal import OBJ_MARSHALER_MANAGER
8
+ import contextlib
9
+ import typing as ta
10
+
11
+ from omlish.lite.logs import log # noqa
9
12
  from omlish.lite.marshal import ObjMarshalerManager
10
- from omlish.lite.marshal import PolymorphicObjMarshaler
13
+ from omlish.lite.marshal import ObjMarshalOptions
14
+ from omlish.lite.pycharm import PycharmRemoteDebug
11
15
 
12
- from ..pyremote import PyremoteBootstrapDriver
13
- from ..pyremote import PyremoteBootstrapOptions
14
- from ..pyremote import pyremote_bootstrap_finalize
15
- from ..pyremote import pyremote_build_bootstrap_cmd
16
+ from .bootstrap import MainBootstrap
17
+ from .bootstrap_ import main_bootstrap
16
18
  from .commands.base import Command
19
+ from .commands.base import CommandExecutor
17
20
  from .commands.subprocess import SubprocessCommand
18
- from .commands.subprocess import SubprocessCommandExecutor
19
- from .payload import get_payload_src
20
- from .protocol import Channel
21
- from .spawning import PySpawner
22
-
23
-
24
- ##
25
-
26
-
27
- _COMMAND_TYPES = {
28
- 'subprocess': SubprocessCommand,
29
- }
30
-
31
-
32
- ##
33
-
34
-
35
- def register_command_marshaling(msh: ObjMarshalerManager) -> None:
36
- for fn in [
37
- lambda c: c,
38
- lambda c: c.Output,
39
- ]:
40
- msh.register_opj_marshaler(
41
- fn(Command),
42
- PolymorphicObjMarshaler.of([
43
- PolymorphicObjMarshaler.Impl(
44
- fn(cty),
45
- k,
46
- msh.get_obj_marshaler(fn(cty)),
47
- )
48
- for k, cty in _COMMAND_TYPES.items()
49
- ]),
50
- )
51
-
52
-
53
- register_command_marshaling(OBJ_MARSHALER_MANAGER)
54
-
55
-
56
- ##
57
-
58
-
59
- def _remote_main() -> None:
60
- rt = pyremote_bootstrap_finalize() # noqa
61
- chan = Channel(rt.input, rt.output)
62
-
63
- while True:
64
- i = chan.recv_obj(Command)
65
- if i is None:
66
- break
67
-
68
- if isinstance(i, SubprocessCommand):
69
- o = SubprocessCommandExecutor().execute(i) # noqa
70
- else:
71
- raise TypeError(i)
72
-
73
- chan.send_obj(o, Command.Output)
21
+ from .config import MainConfig
22
+ from .deploy.command import DeployCommand
23
+ from .remote.config import RemoteConfig
24
+ from .remote.execution import RemoteExecution
25
+ from .remote.spawning import RemoteSpawning
74
26
 
75
27
 
76
28
  ##
@@ -87,50 +39,72 @@ def _main() -> None:
87
39
  parser.add_argument('-q', '--shell-quote', action='store_true')
88
40
  parser.add_argument('--python', default='python3')
89
41
 
42
+ parser.add_argument('--pycharm-debug-port', type=int)
43
+ parser.add_argument('--pycharm-debug-host')
44
+ parser.add_argument('--pycharm-debug-version')
45
+
90
46
  parser.add_argument('--debug', action='store_true')
91
47
 
48
+ parser.add_argument('--local', action='store_true')
49
+
50
+ parser.add_argument('command', nargs='+')
51
+
92
52
  args = parser.parse_args()
93
53
 
94
54
  #
95
55
 
96
- payload_src = get_payload_src(file=args._payload_file) # noqa
56
+ bs = MainBootstrap(
57
+ main_config=MainConfig(
58
+ log_level='DEBUG' if args.debug else 'INFO',
97
59
 
98
- remote_src = '\n\n'.join([
99
- '__name__ = "__remote__"',
100
- payload_src,
101
- '_remote_main()',
102
- ])
60
+ debug=bool(args.debug),
61
+ ),
103
62
 
104
- #
63
+ remote_config=RemoteConfig(
64
+ payload_file=args._payload_file, # noqa
105
65
 
106
- spawner = PySpawner(
107
- pyremote_build_bootstrap_cmd(__package__ or 'manage'),
108
- shell=args.shell,
109
- shell_quote=args.shell_quote,
110
- python=args.python,
66
+ pycharm_remote_debug=PycharmRemoteDebug(
67
+ port=args.pycharm_debug_port,
68
+ host=args.pycharm_debug_host,
69
+ install_version=args.pycharm_debug_version,
70
+ ) if args.pycharm_debug_port is not None else None,
71
+ ),
111
72
  )
112
73
 
113
- with spawner.spawn() as proc:
114
- res = PyremoteBootstrapDriver( # noqa
115
- remote_src,
116
- PyremoteBootstrapOptions(
117
- debug=args.debug,
118
- ),
119
- ).run(proc.stdout, proc.stdin)
74
+ injector = main_bootstrap(
75
+ bs,
76
+ )
120
77
 
121
- chan = Channel(proc.stdout, proc.stdin)
78
+ #
79
+
80
+ cmds: ta.List[Command] = []
81
+ for c in args.command:
82
+ if c == 'deploy':
83
+ cmds.append(DeployCommand())
84
+ else:
85
+ cmds.append(SubprocessCommand([c]))
86
+
87
+ #
88
+
89
+ with contextlib.ExitStack() as es:
90
+ ce: CommandExecutor
122
91
 
123
- #
92
+ if args.local:
93
+ ce = injector[CommandExecutor]
94
+
95
+ else:
96
+ tgt = RemoteSpawning.Target(
97
+ shell=args.shell,
98
+ shell_quote=args.shell_quote,
99
+ python=args.python,
100
+ )
124
101
 
125
- for ci in [
126
- SubprocessCommand(['python3', '-'], input=b'print(1)\n'),
127
- SubprocessCommand(['uname']),
128
- ]:
129
- chan.send_obj(ci, Command)
102
+ ce = es.enter_context(injector[RemoteExecution].connect(tgt, bs)) # noqa
130
103
 
131
- o = chan.recv_obj(Command.Output)
104
+ for cmd in cmds:
105
+ r = ce.try_execute(cmd)
132
106
 
133
- print(o)
107
+ print(injector[ObjMarshalerManager].marshal_obj(r, opts=ObjMarshalOptions(raw_bytes=True)))
134
108
 
135
109
 
136
110
  if __name__ == '__main__':
@@ -0,0 +1,12 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from omlish.lite.marshal import ObjMarshalerManager
5
+
6
+
7
+ @dc.dataclass(frozen=True)
8
+ class ObjMarshalerInstaller:
9
+ fn: ta.Callable[[ObjMarshalerManager], None]
10
+
11
+
12
+ ObjMarshalerInstallers = ta.NewType('ObjMarshalerInstallers', ta.Sequence[ObjMarshalerInstaller])
File without changes