from __future__ import annotations import os from dataclasses import dataclass from pathlib import Path def _resolve_path(value: str | None, default: Path) -> Path: base = Path(value).expanduser() if value else default if not base.is_absolute(): base = default.parent / base return base.resolve() @dataclass(frozen=True) class Settings: project_root: Path source_root: Path db_path: Path log_dir: Path weights_root: Path task_conda_env: str backend_conda_env: str weight_mode: str enable_shell_tasks: bool def get_settings() -> Settings: project_root = Path(os.getenv("SEG_DATA_SERVER_ROOT", Path(__file__).resolve().parents[2])).expanduser() if not project_root.is_absolute(): project_root = (Path(__file__).resolve().parents[2] / project_root).resolve() else: project_root = project_root.resolve() sibling_source = project_root.parent / "Seg" default_source = sibling_source if sibling_source.exists() else project_root.parent source_root = _resolve_path(os.getenv("SEG_SOURCE_ROOT"), default_source) db_path = _resolve_path(os.getenv("SEG_BACKEND_DB"), project_root / "var" / "seg_data_server.sqlite3") log_dir = _resolve_path(os.getenv("SEG_BACKEND_LOG_DIR"), project_root / "var" / "job_logs") weights_root = (project_root / "weights").resolve() return Settings( project_root=project_root, source_root=source_root, db_path=db_path, log_dir=log_dir, weights_root=weights_root, task_conda_env=os.getenv("SEG_TASK_CONDA_ENV", "seg_smp"), backend_conda_env=os.getenv("SEG_BACKEND_CONDA_ENV", "seg_server"), weight_mode=os.getenv("SEG_WEIGHT_MODE", "copy"), enable_shell_tasks=os.getenv("SEG_ENABLE_SHELL_TASKS", "1") == "1", ) settings = get_settings()