Source code for job_execution.job

"""Backend-neutral job and execution data structures."""

from dataclasses import dataclass, field
from pathlib import Path
from typing import Any


[docs] @dataclass(frozen=True) class CommandOptions: """Streams, environment and checks of a command job.""" stdin: Any = None stdout: Path | None = None stderr: Path | None = None env: dict[str, str] | None = None runtime_environment: tuple[str, ...] | str | None = None configuration: dict[str, Any] | None = None application_log: Path | None = None check: bool = True capture_output: bool = False
[docs] @dataclass(frozen=True) class JobSpec: """Describe one independent unit of work.""" job_id: str index: int function: Any = None item: Any = None command: tuple[str, ...] | str | Path | None = None options: CommandOptions | None = None initializer: Any = None initargs: tuple[Any, ...] = () context_spec: dict[str, Any] | None = None metadata: dict[str, Any] = field(default_factory=dict) resources: dict[str, Any] = field(default_factory=dict) mount_paths: tuple[Path, ...] = () output_paths: tuple[Path, ...] = () def __post_init__(self): """Validate the mutually exclusive job execution forms.""" has_function = self.function is not None has_command = self.command is not None if has_function == has_command: raise ValueError("A JobSpec must define exactly one of function or command.") if has_command and not self.command: raise ValueError("A command JobSpec must contain at least one argument.") if self.options is None: object.__setattr__(self, "options", CommandOptions())
[docs] @dataclass class ExecutionOptions: """Options shared by execution backends.""" backend: str = "local" max_workers: int | None = None work_dir: Path | None = None backend_config: dict[str, Any] = field(default_factory=dict) initializer: Any = None initargs: tuple[Any, ...] = ()
[docs] @dataclass class JobResult: """Result and diagnostic information for one job.""" job_id: str index: int value: Any = None status: str = "completed" return_code: int = 0 stdout: Path | None = None stderr: Path | None = None error: str | None = None runtime: float = 0.0 output: str | None = None error_output: str | None = None
[docs] @dataclass class SubmissionHandle: """Persistable description of a submitted execution.""" backend: str work_dir: Path job_ids: tuple[str, ...] scheduler_id: int | None = None process_ids: dict[str, int] = field(default_factory=dict) metadata: dict[str, Any] = field(default_factory=dict)
[docs] def as_dict(self): """Return a JSON-serializable manifest representation.""" return { "backend": self.backend, "work_dir": str(self.work_dir), "job_ids": list(self.job_ids), "scheduler_id": self.scheduler_id, "process_ids": self.process_ids, "metadata": self.metadata, }
[docs] @classmethod def from_dict(cls, payload): """Restore a submission handle from a manifest mapping.""" return cls( backend=payload["backend"], work_dir=Path(payload["work_dir"]), job_ids=tuple(payload.get("job_ids", ())), scheduler_id=payload.get("scheduler_id"), process_ids={key: int(value) for key, value in payload.get("process_ids", {}).items()}, metadata=dict(payload.get("metadata", {})), )