2022-08-24 15:01:07 +00:00
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class InteractiveInput:
|
2022-10-05 09:14:51 +00:00
|
|
|
"""Interactive input for a shell command.
|
2022-08-24 15:01:07 +00:00
|
|
|
|
2022-10-05 09:14:51 +00:00
|
|
|
Attributes:
|
2022-10-05 16:41:47 +00:00
|
|
|
prompt_pattern: Regular expression that defines expected prompt from the command.
|
|
|
|
input: User input that should be supplied to the command in response to the prompt.
|
2022-08-24 15:01:07 +00:00
|
|
|
"""
|
2022-08-24 11:41:11 +00:00
|
|
|
|
2022-08-24 15:01:07 +00:00
|
|
|
prompt_pattern: str
|
|
|
|
input: str
|
|
|
|
|
|
|
|
|
2022-10-05 16:41:47 +00:00
|
|
|
class CommandInspector(ABC):
|
|
|
|
"""Interface of inspector that processes command text before execution."""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def inspect(self, command: str) -> str:
|
|
|
|
"""Transforms command text and returns modified command.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
command: Command to transform with this inspector.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Transformed command text.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
2022-08-24 15:01:07 +00:00
|
|
|
@dataclass
|
|
|
|
class CommandOptions:
|
2022-10-05 09:14:51 +00:00
|
|
|
"""Options that control command execution.
|
2022-08-24 15:01:07 +00:00
|
|
|
|
2022-10-05 09:14:51 +00:00
|
|
|
Attributes:
|
2022-10-05 16:41:47 +00:00
|
|
|
interactive_inputs: User inputs that should be interactively supplied to
|
2022-10-05 09:14:51 +00:00
|
|
|
the command during execution.
|
2022-10-05 16:41:47 +00:00
|
|
|
close_stdin: Controls whether stdin stream should be closed after feeding interactive
|
|
|
|
inputs or after requesting non-interactive command. If shell implementation does not
|
|
|
|
support this functionality, it should ignore this flag without raising an error.
|
|
|
|
timeout: Timeout for command execution (in seconds).
|
|
|
|
check: Controls whether to check return code of the command. Set to False to
|
2022-10-05 09:14:51 +00:00
|
|
|
ignore non-zero return codes.
|
2022-08-24 15:01:07 +00:00
|
|
|
"""
|
2022-08-24 11:41:11 +00:00
|
|
|
|
2022-08-24 15:01:07 +00:00
|
|
|
interactive_inputs: Optional[list[InteractiveInput]] = None
|
2022-10-05 16:41:47 +00:00
|
|
|
close_stdin: bool = False
|
2022-08-24 15:01:07 +00:00
|
|
|
timeout: int = 30
|
|
|
|
check: bool = True
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class CommandResult:
|
2022-10-05 09:14:51 +00:00
|
|
|
"""Represents a result of a command executed via shell.
|
|
|
|
|
|
|
|
Attributes:
|
2022-10-05 16:41:47 +00:00
|
|
|
stdout: Complete content of stdout stream.
|
|
|
|
stderr: Complete content of stderr stream.
|
|
|
|
return_code: Return code (or exit code) of the command's process.
|
2022-08-24 15:01:07 +00:00
|
|
|
"""
|
2022-08-24 11:41:11 +00:00
|
|
|
|
2022-08-24 15:01:07 +00:00
|
|
|
stdout: str
|
|
|
|
stderr: str
|
|
|
|
return_code: int
|
|
|
|
|
|
|
|
|
|
|
|
class Shell(ABC):
|
2022-10-05 09:14:51 +00:00
|
|
|
"""Interface of a command shell on some system (local or remote)."""
|
2022-08-24 15:01:07 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def exec(self, command: str, options: Optional[CommandOptions] = None) -> CommandResult:
|
2022-10-05 09:14:51 +00:00
|
|
|
"""Executes specified command on this shell.
|
|
|
|
|
|
|
|
To execute interactive command, user inputs should be specified in *options*.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
command: Command to execute on the shell.
|
|
|
|
options: Options that control command execution.
|
2022-08-24 15:01:07 +00:00
|
|
|
|
2022-10-05 09:14:51 +00:00
|
|
|
Returns:
|
|
|
|
Command's result.
|
2022-08-24 15:01:07 +00:00
|
|
|
"""
|