You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.1 KiB
Python

import abc
from functools import cached_property
from pathlib import PurePath
from typing import Callable, Optional
from .base import CommandArgs, ShellCommandStr
from .completed import CompletedExec
# List of POSIX shells which shall be used
DETECTED_SHELLS = [
"/usr/bin/bash",
"/bin/bash",
"/usr/bin/sh",
"/bin/sh",
]
class ExecutorTarget(metaclass=abc.ABCMeta):
@abc.abstractmethod
def exec_cmd(
self,
*,
command: CommandArgs,
check: bool,
capture_stdout: bool,
work_dir: Optional[PurePath],
) -> CompletedExec:
...
@staticmethod
def process_tester(
exec: Callable[[CommandArgs], CompletedExec]
) -> Callable[[CommandArgs], bool]:
return lambda command: exec(command).returncode == 0
@staticmethod
def _search_shell_with(tester: Callable[[CommandArgs], bool]) -> str:
for shell in DETECTED_SHELLS:
command = CommandArgs([shell, "-c", "true"])
if tester(command):
return command[0]
# TODO specialize
raise Exception(
f"Could not find an acceptable shell on this host, searched for {DETECTED_SHELLS}"
)
@cached_property
def found_shell(self) -> str:
return self._search_shell_with(
self.process_tester(
lambda command: self.exec_cmd(
command=command,
check=False,
capture_stdout=False,
work_dir=None,
)
)
)
def convert_shell_command(self, shell_cmd: ShellCommandStr) -> CommandArgs:
return CommandArgs([self.found_shell, "-c", str(shell_cmd)])
def exec_shell(
self,
*,
shell_cmd: ShellCommandStr,
check: bool,
capture_stdout: bool,
work_dir: Optional[PurePath],
) -> CompletedExec:
return self.exec_cmd(
command=self.convert_shell_command(shell_cmd=shell_cmd),
check=check,
capture_stdout=capture_stdout,
work_dir=work_dir,
)