129 lines
4.3 KiB
Python
129 lines
4.3 KiB
Python
"""Configuration management for mytoolkit.
|
|
|
|
Unified config file: ~/.mytoolkit/config.json (keys.* namespace)
|
|
Legacy: ~/.mytoolkit/env.json (migrated on first load)
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
_MYTOOLKIT_HOME = Path(os.environ.get("MYTOOLKIT_HOME", Path.home() / ".mytoolkit"))
|
|
CONFIG_PATH = _MYTOOLKIT_HOME / "config.json"
|
|
_LEGACY_MODULE_PATH = Path(__file__).parent / "config.json"
|
|
_LEGACY_ENV_PATH = _MYTOOLKIT_HOME / "env.json"
|
|
|
|
|
|
class Config:
|
|
"""Simple config manager for mytoolkit.
|
|
|
|
Stores in ~/.mytoolkit/config.json under the "keys" key::
|
|
|
|
{"keys": {"apikey_ark": "...", "volc_appid": "...", "path_study": "...", ...}}
|
|
"""
|
|
|
|
def __init__(self):
|
|
self._config_path = CONFIG_PATH
|
|
self._migrate_legacy()
|
|
self._data = self._load()
|
|
|
|
# ------------------------------------------------------------------
|
|
# Migration
|
|
# ------------------------------------------------------------------
|
|
|
|
def _migrate_legacy(self) -> None:
|
|
"""One-shot: merge legacy env.json into config.json (keys.* format)."""
|
|
self._config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Load any existing config.json
|
|
existing: dict = {}
|
|
if self._config_path.exists():
|
|
try:
|
|
existing = json.loads(self._config_path.read_text())
|
|
except (json.JSONDecodeError, OSError):
|
|
existing = {}
|
|
|
|
keys = existing.get("keys", {})
|
|
|
|
# 1) Legacy ~/.mytoolkit/env.json (vars.* → keys.*)
|
|
migrated_env = False
|
|
if _LEGACY_ENV_PATH.exists():
|
|
try:
|
|
legacy = json.loads(_LEGACY_ENV_PATH.read_text())
|
|
legacy_vars = legacy.get("vars", {})
|
|
if legacy_vars:
|
|
keys.update(legacy_vars)
|
|
migrated_env = True
|
|
except (json.JSONDecodeError, OSError):
|
|
pass
|
|
|
|
if migrated_env:
|
|
existing["keys"] = dict(sorted(keys.items()))
|
|
self._config_path.write_text(
|
|
json.dumps(existing, indent=2, ensure_ascii=False) + "\n"
|
|
)
|
|
# Rename env.json out of the way so we don't re-migrate
|
|
backup = _LEGACY_ENV_PATH.with_name("env.json.migrated")
|
|
if not backup.exists():
|
|
_LEGACY_ENV_PATH.rename(backup)
|
|
|
|
# 2) Very old bundled config.json next to this module (early mytoolkit)
|
|
if not self._config_path.exists() and _LEGACY_MODULE_PATH.exists():
|
|
try:
|
|
_LEGACY_MODULE_PATH.rename(self._config_path)
|
|
except OSError:
|
|
pass
|
|
|
|
# ------------------------------------------------------------------
|
|
# Load / Save
|
|
# ------------------------------------------------------------------
|
|
|
|
def _load(self) -> dict:
|
|
if self._config_path.exists():
|
|
try:
|
|
return json.loads(self._config_path.read_text())
|
|
except (json.JSONDecodeError, OSError):
|
|
pass
|
|
return {"keys": {}}
|
|
|
|
def save(self):
|
|
self._config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
self._config_path.write_text(
|
|
json.dumps(self._data, indent=2, ensure_ascii=False) + "\n"
|
|
)
|
|
|
|
# ------------------------------------------------------------------
|
|
# Accessors
|
|
# ------------------------------------------------------------------
|
|
|
|
def get(self, name: str) -> str | None:
|
|
"""Get a key by name."""
|
|
return self._data.get("keys", {}).get(name)
|
|
|
|
def get_all(self) -> dict[str, str]:
|
|
"""Return all keys as a flat dict."""
|
|
return self._data.get("keys", {}).copy()
|
|
|
|
def set(self, name: str, value: str):
|
|
"""Set a key and persist."""
|
|
if "keys" not in self._data:
|
|
self._data["keys"] = {}
|
|
self._data["keys"][name] = value
|
|
self.save()
|
|
|
|
def remove(self, name: str) -> bool:
|
|
"""Remove a key. Returns True if existed."""
|
|
if name in self._data.get("keys", {}):
|
|
del self._data["keys"][name]
|
|
self.save()
|
|
return True
|
|
return False
|
|
|
|
def export(self) -> dict[str, str]:
|
|
"""Return all keys with MYCLI_ prefix for shell eval."""
|
|
return {f"MYCLI_{k.upper()}": v for k, v in self.get_all().items()}
|
|
|
|
|
|
# Global singleton
|
|
config = Config()
|