Files
silo-calc/pythonpath/silo_calc/settings.py
Zoe Forbes 13b56fd1b0 initial: LibreOffice Calc Silo extension (extracted from silo monorepo)
LibreOffice Calc extension for Silo PLM integration. Uses shared
silo-client package (submodule) for API communication.

Changes from monorepo version:
- SiloClient class removed from client.py, replaced with CalcSiloSettings
  adapter + factory function wrapping silo_client.SiloClient
- silo_calc_component.py adds silo-client to sys.path
- Makefile build-oxt copies silo_client into .oxt for self-contained packaging
- All other modules unchanged
2026-02-06 11:24:13 -06:00

95 lines
2.5 KiB
Python

"""Persistent settings for the Silo Calc extension.
Settings are stored in ``~/.config/silo/calc-settings.json``.
The file is a flat JSON dict with known keys.
"""
import json
import os
from pathlib import Path
from typing import Any, Dict
_SETTINGS_DIR = (
Path(os.environ.get("XDG_CONFIG_HOME", "~/.config")).expanduser() / "silo"
)
_SETTINGS_FILE = _SETTINGS_DIR / "calc-settings.json"
# Default values for every known key.
_DEFAULTS: Dict[str, Any] = {
"api_url": "",
"api_token": "",
"ssl_verify": True,
"ssl_cert_path": "",
"auth_username": "",
"auth_role": "",
"auth_source": "",
"projects_dir": "", # fallback: SILO_PROJECTS_DIR env or ~/projects
"default_schema": "kindred-rd",
"openrouter_api_key": "", # fallback: OPENROUTER_API_KEY env var
"openrouter_model": "", # fallback: ai_client.DEFAULT_MODEL
"openrouter_instructions": "", # fallback: ai_client.DEFAULT_INSTRUCTIONS
}
def load() -> Dict[str, Any]:
"""Load settings, returning defaults for any missing keys."""
cfg = dict(_DEFAULTS)
if _SETTINGS_FILE.is_file():
try:
with open(_SETTINGS_FILE, "r") as f:
stored = json.load(f)
cfg.update(stored)
except (json.JSONDecodeError, OSError):
pass
return cfg
def save(cfg: Dict[str, Any]) -> None:
"""Persist the full settings dict to disk."""
_SETTINGS_DIR.mkdir(parents=True, exist_ok=True)
with open(_SETTINGS_FILE, "w") as f:
json.dump(cfg, f, indent=2)
def get(key: str, default: Any = None) -> Any:
"""Convenience: load a single key."""
cfg = load()
return cfg.get(key, default)
def put(key: str, value: Any) -> None:
"""Convenience: update a single key and persist."""
cfg = load()
cfg[key] = value
save(cfg)
def save_auth(username: str, role: str = "", source: str = "", token: str = "") -> None:
"""Store authentication info."""
cfg = load()
cfg["auth_username"] = username
cfg["auth_role"] = role
cfg["auth_source"] = source
if token:
cfg["api_token"] = token
save(cfg)
def clear_auth() -> None:
"""Remove stored auth credentials."""
cfg = load()
cfg["api_token"] = ""
cfg["auth_username"] = ""
cfg["auth_role"] = ""
cfg["auth_source"] = ""
save(cfg)
def get_projects_dir() -> Path:
"""Return the resolved projects base directory."""
cfg = load()
d = cfg.get("projects_dir", "")
if not d:
d = os.environ.get("SILO_PROJECTS_DIR", "~/projects")
return Path(d).expanduser()