Skip to content

yggdrasil.environ.system_command

system_command

SystemCommand dataclass

SystemCommand(
    args: tuple[str, ...],
    cwd: Path | None,
    env: dict[str, str] | None,
    popen: Popen[str],
    python: Optional["PyEnv"] = None,
)

Wrap a subprocess command and its eventual result.

The command is created around a live subprocess.Popen object and becomes complete after :meth:wait populates :attr:completed.

Features
  • lazy process launching via :meth:run_lazy
  • synchronous helper via :meth:run_sync
  • Python-aware stderr inspection
  • optional one-shot auto-install retry for missing Python modules
  • richer error formatting through :class:SystemCommandError

returncode property

returncode: int | None

Return the exit status once known.

stdout property

stdout: str | None

Captured stdout, available only after completion.

stderr property

stderr: str | None

Captured stderr, available only after completion.

command_str property

command_str: str

Human-readable command string.

run_sync staticmethod

run_sync(
    args: Sequence[str],
    *,
    cwd: Path | None = None,
    env: dict[str, str] | None = None,
    check: bool = True
) -> subprocess.CompletedProcess[str]

Run a command synchronously and optionally raise a formatted error.

run_lazy staticmethod

run_lazy(
    args: Sequence[str],
    *,
    cwd: Path | None = None,
    env: dict[str, str] | None = None,
    python: Optional["PyEnv"] = None
) -> "SystemCommand"

Launch a command and return a lazy wrapper around the live process.

poll

poll() -> int | None

Return the current process return code, or None if still running.

find_module_not_found_error

find_module_not_found_error() -> Optional[ModuleNotFoundError]

Best-effort extraction of a ModuleNotFoundError from stderr.

parse_python_exception

parse_python_exception() -> Optional[tuple[str, str]]

Extract the last Python exception type and message from stderr.

Returns

tuple[str, str] | None (exception_type, message) for the last detected exception line, or None when stderr does not appear to contain a Python exception.

extract_traceback

extract_traceback() -> Optional[str]

Extract the last Python traceback block from stderr.

If the command used python -c <code>, inline <string> frames are annotated with the actual source line from the -c payload.

summary

summary() -> str

Build a short user-friendly summary of the failure.

Examples
  • ModuleNotFoundError: No module named 'pyarrow'
  • ValueError: invalid literal for int() with base 10: 'abc'
  • Process exited with status 127

render_error_details

render_error_details() -> str

Render the most useful detailed error payload.

Preference order: 1. extracted Python traceback 2. raw stderr 3. raw stdout

wait

wait(
    wait: WaitingConfigArg = True,
    raise_error: bool = True,
    auto_install: bool = False,
) -> "SystemCommand"

Wait for process completion, capture outputs, and optionally raise on failure.

Always returns self.

retry

retry(
    wait: WaitingConfigArg = True,
    raise_error: bool = True,
    auto_install: bool = False,
) -> "SystemCommand"

Re-launch the same command, replacing internal process/completed state.

exception

exception(
    wait: WaitingConfigArg = True, auto_install: bool = True
) -> Optional["SystemCommandError"]

Return a :class:SystemCommandError for a failed completed process, or None.

raise_for_status

raise_for_status(
    *,
    wait: WaitingConfigArg = True,
    raise_error: bool = True,
    auto_install: bool = True
) -> "SystemCommand"

Raise :class:SystemCommandError if the command failed.

Returns self when successful or when raise_error=False.

SystemCommandError dataclass

SystemCommandError(command: SystemCommand, message: str | None = None)

Bases: RuntimeError

Raised when a subprocess command fails.

Attributes

command: The failing :class:SystemCommand. message: Optional high-level override message, used for special cases such as timeouts. When omitted, a summary is derived from stderr / traceback.