Source code for jobflow_remote.remote.host.base

from __future__ import annotations

import abc
import traceback
from typing import TYPE_CHECKING

from monty.json import MSONable

if TYPE_CHECKING:
    from pathlib import Path


[docs] class BaseHost(MSONable): """Base Host class."""
[docs] @abc.abstractmethod def execute( self, command: str | list[str], workdir: str | Path | None = None, timeout: int | None = None, ) -> tuple[str, str, int]: """Execute the given command on the host. Parameters ---------- command: str or list of str Command to execute, as a str or list of str workdir: str or None path where the command will be executed. """ raise NotImplementedError
[docs] @abc.abstractmethod def mkdir( self, directory: str | Path, recursive: bool = True, exist_ok: bool = True ) -> bool: """Create directory on the host.""" raise NotImplementedError
[docs] @abc.abstractmethod def write_text_file(self, filepath, content): """Write content to a file on the host.""" raise NotImplementedError
[docs] @abc.abstractmethod def connect(self): raise NotImplementedError
[docs] @abc.abstractmethod def close(self) -> bool: raise NotImplementedError
@property @abc.abstractmethod def is_connected(self) -> bool: raise NotImplementedError
[docs] @abc.abstractmethod def put(self, src, dst): raise NotImplementedError
[docs] @abc.abstractmethod def get(self, src, dst): raise NotImplementedError
[docs] @abc.abstractmethod def copy(self, src, dst): raise NotImplementedError
[docs] def test(self) -> str | None: msg = None try: cmd = "echo 'test'" stdout, stderr, returncode = self.execute(cmd) if returncode != 0 or stdout.strip() != "test": msg = f"Command was executed but some error occurred.\nstdoud: {stdout}\nstderr: {stderr}" except Exception: exc = traceback.format_exc() msg = f"Error while executing command:\n {exc}" return msg
[docs] @abc.abstractmethod def listdir(self, path: str | Path) -> list[str]: raise NotImplementedError
[docs] @abc.abstractmethod def remove(self, path: str | Path): raise NotImplementedError
[docs] @abc.abstractmethod def rmtree(self, path: str | Path, raise_on_error: bool = False) -> bool: """Recursively delete a directory tree on a host. This method must be implemented by subclasses of `BaseHost`. It is intended to remove an entire directory tree, including all files and subdirectories, on the host represented by the subclass. Parameters ---------- path : str or Path The path to the directory tree to be removed. raise_on_error : bool If set to `False` (default), errors will be ignored, and the method will attempt to continue removing remaining files and directories. Otherwise, any errors encountered during the removal process will raise an exception. Returns ------- bool True if the directory tree was successfully removed, False otherwise. """ raise NotImplementedError
@property def interactive_login(self) -> bool: """ True if the host requires interactive actions upon login. False by default. Subclasses should override the method to customize the value. """ return False
[docs] class HostError(Exception): pass