config.py
1 from __future__ import annotations 2 3 import json 4 import logging 5 from dataclasses import dataclass, asdict 6 from pathlib import Path 7 8 log = logging.getLogger(__name__) 9 10 CONFIG_DIR = Path.home() / ".config" / "linamp" 11 CONFIG_PATH = CONFIG_DIR / "config.json" 12 QUEUE_PATH = CONFIG_DIR / "queue.json" 13 14 15 @dataclass 16 class AppConfig: 17 """Application-wide configuration.""" 18 19 music_root: str = "~/Music" 20 21 @property 22 def music_root_path(self) -> Path: 23 """Return music_root as an expanded Path.""" 24 return Path(self.music_root).expanduser() 25 26 27 def load_config() -> AppConfig: 28 """Load config from disk, returning defaults if missing or invalid.""" 29 if CONFIG_PATH.exists(): 30 try: 31 data = json.loads(CONFIG_PATH.read_text()) 32 return AppConfig(**{k: v for k, v in data.items() if k in AppConfig.__dataclass_fields__}) 33 except Exception as exc: 34 log.warning("Failed to load config from %s: %s", CONFIG_PATH, exc) 35 return AppConfig() 36 37 38 def save_config(config: AppConfig) -> None: 39 """Persist config to disk.""" 40 CONFIG_DIR.mkdir(parents=True, exist_ok=True) 41 CONFIG_PATH.write_text(json.dumps(asdict(config), indent=2) + "\n")