from __future__ import annotations from dataclasses import dataclass, field from pathlib import Path @dataclass class CommandSpec: command: list[str] cwd: Path description: str = "" env: dict[str, str] = field(default_factory=dict) stdin_text: str | None = None TaskFactory = callable def conda_python(env_name: str, script: Path, *args: object) -> list[str]: return ["conda", "run", "-n", env_name, "python", str(script), *[str(a) for a in args]] def python(script: Path, *args: object) -> list[str]: return ["python", str(script), *[str(a) for a in args]] def bash(script: Path, *args: object) -> list[str]: return ["bash", str(script), *[str(a) for a in args]] def option(params: dict, name: str, default=None): value = params.get(name, default) return value def required(params: dict, name: str): if name not in params or params[name] in (None, ""): raise ValueError(f"missing required parameter: {name}") return params[name] def append_flag(args: list[str], flag: str, value): if value not in (None, ""): args.extend([flag, str(value)])