/ linamp / config.py
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")