This commit is contained in:
timeshifter
2022-12-06 15:10:36 +01:00
parent 695c4fc924
commit 28963c3e64
11 changed files with 58 additions and 41 deletions
+69
View File
@@ -0,0 +1,69 @@
from __future__ import annotations
from pathlib import Path
from subprocess import Popen, call, check_output, PIPE
from zfs_backup.misc import assert_type
class CommandInterface:
_BINARY: Path
@classmethod
def _run_command(cls, *args: str) -> None:
CommandRunner.run([str(cls._BINARY), *args])
@classmethod
def _get_output(cls, *args: str) -> str:
return CommandRunner.get_output([str(cls._BINARY), *args])
@classmethod
def _open_stream(cls, *args: str) -> Popen:
return CommandRunner.send_stream([str(cls._BINARY), *args])
@classmethod
def _receive_stream(cls, *args: str, stream: Popen) -> None:
CommandRunner.receive_from_stream([str(cls._BINARY), *args], stream=stream)
class CommandRunner:
@staticmethod
def _sanity_check(cmdline: list[str]) -> None:
assert_type(cmdline, list, "Command line must be a list")
for item in cmdline:
assert_type(item, str, "Only strings allowed in command line")
@staticmethod
def _to_list(command: str | list[str]) -> list[str]:
"""If the command is a str, return it as list. Otherwise, return the command."""
if isinstance(command, str):
return [command]
return command
@classmethod
def run(cls, cmdline: str | list[str]) -> None:
"""Run the command, wait for it to return."""
cmdline = cls._to_list(cmdline)
cls._sanity_check(cmdline)
call(cmdline)
@classmethod
def get_output(cls, cmdline: str | list[str]) -> str:
"""Run the command, return the output of the command."""
cmdline = cls._to_list(cmdline)
cls._sanity_check(cmdline)
return check_output(cmdline).strip().decode()
@classmethod
def receive_from_stream(cls, cmdline: str | list[str], stream: Popen) -> None:
"""Run the command, receive data from a pipe to stdin."""
cmdline = cls._to_list(cmdline)
cls._sanity_check(cmdline)
check_output(cmdline, stdin=stream.stdout)
@classmethod
def send_stream(cls, cmdline: str | list[str]) -> Popen:
"""Run the command, redirect stdout to a pipe."""
cmdline = cls._to_list(cmdline)
cls._sanity_check(cmdline)
return Popen(cmdline, stdout=PIPE)