Source code for mmirage.cli_utils.runtime

"""Runtime/path helpers for the MMIRAGE CLI."""

from __future__ import annotations

import logging
import os
from pathlib import Path
from typing import Optional, Sequence

from mmirage.config.config import MMirageConfig


logger = logging.getLogger(__name__)


[docs] def expand_path(path: str, project_root: Optional[str] = None) -> str: """Expand environment variables, user home and relative paths.""" expanded = Path(os.path.expandvars(os.path.expanduser(path))) if not expanded.is_absolute() and project_root: expanded = Path(project_root) / expanded return str(expanded.resolve())
[docs] def get_project_root(cfg: MMirageConfig) -> str: """Return the configured project root, or the current working directory.""" project_root = cfg.execution_params.project_root if project_root: return expand_path(project_root) return os.getcwd()
[docs] def create_directories(paths: Sequence[str]) -> None: """Create directories if they do not already exist.""" for path in paths: Path(path).mkdir(parents=True, exist_ok=True)
[docs] def validate_edf_env_path(cfg: MMirageConfig) -> None: """Validate the optional EDF environment file path.""" edf_env = cfg.execution_params.edf_env if not edf_env: return resolved = expand_path(edf_env, get_project_root(cfg)) if not Path(resolved).is_file(): raise FileNotFoundError(f"EDF environment file not found: {resolved}")
[docs] def add_file_logging(log_file: str, level: str) -> None: """Add a file handler so logs are also written to disk.""" resolved_log_file = Path(expand_path(log_file)) try: resolved_log_file.parent.mkdir(parents=True, exist_ok=True) except OSError as exc: logger.warning("Unable to create log directory for %s: %s", resolved_log_file, exc) return root_logger = logging.getLogger() for handler in root_logger.handlers: if isinstance(handler, logging.FileHandler) and Path(handler.baseFilename).resolve() == resolved_log_file: return try: file_handler = logging.FileHandler(resolved_log_file, mode="a", encoding="utf-8") except OSError as exc: logger.warning("Unable to open log file %s: %s", resolved_log_file, exc) return file_handler.setLevel(getattr(logging, level.upper(), logging.INFO)) file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s")) root_logger.addHandler(file_handler)
[docs] def setup_runtime(cfg: MMirageConfig, log_level: str) -> None: """Initialize runtime-level logging.""" report_dir = Path(expand_path(cfg.execution_params.report_dir, get_project_root(cfg))) log_file = report_dir / f"{cfg.execution_params.job_name}.out" add_file_logging(str(log_file), log_level) logger.info("Writing logs to %s", log_file)