Coverage for arclith / adapters / output / yaml / secret_adapter.py: 100%
23 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-25 15:02 +0100
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-25 15:02 +0100
1from __future__ import annotations
3from pathlib import Path
5import yaml
7from arclith.domain.ports.secret_resolver import SecretResolver
10class YamlSecretAdapter(SecretResolver):
11 """Reads secrets from a gitignored YAML file (local dev fallback).
13 The file mirrors the config.yaml structure — only secret fields need to appear.
15 Example secrets.yaml:
16 adapters:
17 mongodb:
18 uri: mongodb://localhost:5971
19 lm:
20 planner:
21 api_key: sk-ant-xxxx
22 """
24 def __init__(self, path: str | Path) -> None:
25 self._path = Path(path)
26 self._data: dict | None = None
28 def _load(self) -> dict:
29 if self._data is None:
30 if self._path.exists():
31 with self._path.open() as f:
32 self._data = yaml.safe_load(f) or {}
33 else:
34 self._data = {}
35 return self._data
37 def get(self, field_path: str, secret_key: str) -> str | None:
38 data = self._load()
39 current: object = data
40 for key in field_path.split("."):
41 if not isinstance(current, dict) or key not in current:
42 return None
43 current = current[key]
44 return str(current) if current is not None else None