88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Any, Dict, List, Tuple
|
|
|
|
PRESET_FILES: Dict[str, str] = {
|
|
"jsonl_sm": "jsonl_to_jsonl",
|
|
"simple_sm": "jsonl_to_api",
|
|
}
|
|
|
|
|
|
def _run_profiles_dir() -> Path:
|
|
return Path(__file__).resolve().parents[2] / "run_profiles"
|
|
|
|
|
|
def _preset_templates_dir() -> Path:
|
|
return _run_profiles_dir() / "preset"
|
|
|
|
|
|
def _replace_placeholders(value: Any, project_root: Path) -> Any:
|
|
if isinstance(value, str):
|
|
return value.replace("${PROJECT_ROOT}", str(project_root))
|
|
if isinstance(value, dict):
|
|
return {k: _replace_placeholders(v, project_root) for k, v in value.items()}
|
|
if isinstance(value, list):
|
|
return [_replace_placeholders(v, project_root) for v in value]
|
|
return value
|
|
|
|
|
|
def list_preset_names() -> List[str]:
|
|
return sorted(PRESET_FILES.keys())
|
|
|
|
|
|
def get_preset_file_candidates(preset_name: str) -> List[Path]:
|
|
if preset_name not in PRESET_FILES:
|
|
raise ValueError(f"Unknown preset: {preset_name}. Available: {list_preset_names()}")
|
|
|
|
base = PRESET_FILES[preset_name]
|
|
run_profiles_root = _run_profiles_dir()
|
|
preset_templates_root = _preset_templates_dir()
|
|
return [
|
|
run_profiles_root / f"{base}.local.yaml",
|
|
run_profiles_root / f"{base}.local.yml",
|
|
run_profiles_root / f"{base}.local.json",
|
|
preset_templates_root / f"{base}.default.yaml",
|
|
preset_templates_root / f"{base}.default.yml",
|
|
preset_templates_root / f"{base}.default.json",
|
|
]
|
|
|
|
|
|
def resolve_preset_file(preset_name: str) -> Tuple[Path, bool]:
|
|
candidates = get_preset_file_candidates(preset_name)
|
|
for idx, path in enumerate(candidates):
|
|
if path.exists() and path.is_file():
|
|
return path, idx > 0
|
|
raise FileNotFoundError(
|
|
f"No preset file found for {preset_name}. Tried: {[str(p) for p in candidates]}"
|
|
)
|
|
|
|
|
|
def load_overrides_from_file(file_path: Path, project_root: Path) -> Dict[str, Any]:
|
|
suffix = file_path.suffix.lower()
|
|
text = file_path.read_text(encoding="utf-8")
|
|
|
|
if suffix in {".yaml", ".yml"}:
|
|
try:
|
|
import yaml # type: ignore
|
|
except Exception as exc:
|
|
raise RuntimeError(
|
|
"YAML config requires PyYAML. Install with: pip install pyyaml"
|
|
) from exc
|
|
payload = yaml.safe_load(text)
|
|
else:
|
|
payload = json.loads(text)
|
|
|
|
resolved = _replace_placeholders(payload, project_root)
|
|
if not isinstance(resolved, dict):
|
|
raise ValueError(f"Preset file must contain object mapping: {file_path}")
|
|
resolved.pop("extensions", None)
|
|
return resolved
|
|
|
|
|
|
def load_named_preset_overrides(project_root: Path, preset_name: str) -> Tuple[Dict[str, Any], Path, bool]:
|
|
file_path, used_default = resolve_preset_file(preset_name)
|
|
overrides = load_overrides_from_file(file_path, project_root)
|
|
return overrides, file_path, used_default
|