-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFlooSettings.py
More file actions
91 lines (74 loc) · 3.11 KB
/
FlooSettings.py
File metadata and controls
91 lines (74 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
from __future__ import annotations
import json, os, sys, tempfile
from pathlib import Path
from typing import Any, Dict, Optional
class FlooSettings:
"""
Generic JSON settings store for FlooCast.
- Arbitrary key/value storage (use any string as the key)
- Persisted to a cross-platform, user-writable location (MSIX-friendly on Windows)
- Includes helpers for saving/loading dict-based device info
"""
def __init__(self, app_name: str = "FlooCast", filename: str = "settings.json"):
self.app_name = app_name
self.filename = filename
self.path: Path = self._default_settings_path(app_name, filename)
self._data: Dict[str, Any] = {}
self.load()
# ---------- Core I/O ----------
def load(self) -> None:
self.path.parent.mkdir(parents=True, exist_ok=True)
if self.path.exists():
try:
self._data = json.loads(self.path.read_text(encoding="utf-8"))
if not isinstance(self._data, dict):
self._data = {}
except Exception:
self._data = {}
def save(self) -> None:
self.path.parent.mkdir(parents=True, exist_ok=True)
fd, tmp_path = tempfile.mkstemp(prefix=".tmp_", dir=str(self.path.parent))
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(self._data, f, indent=2, ensure_ascii=False)
os.replace(tmp_path, self.path)
except Exception:
try:
os.remove(tmp_path)
except Exception:
pass
raise
# ---------- Generic get/set ----------
def get(self, key: str, default: Any = None) -> Any:
return self._data.get(key, default)
def set(self, key: str, value: Any) -> None:
self._data[key] = value
def update(self, mapping: Dict[str, Any]) -> None:
self._data.update(mapping)
def remove(self, key: str) -> None:
self._data.pop(key, None)
# ---------- Named helpers for dict-based items ----------
def set_item(self, name, item):
if isinstance(item, dict):
# shallow copy so the caller can't mutate stored dicts
self._data[name] = dict(item)
else:
# store scalars (bool, int, str, list, etc.) directly
self._data[name] = item
def get_item(self, name, default=None):
value = self._data.get(name, default)
if isinstance(value, dict):
# return a copy so caller can’t mutate our stored copy
return dict(value)
return value
# ---------- Path helper ----------
@staticmethod
def _default_settings_path(app_name: str, filename: str) -> Path:
if sys.platform == "win32":
base = os.getenv("LOCALAPPDATA") or str(Path.home())
return Path(base) / app_name / filename
elif sys.platform == "darwin":
return Path.home() / "Library" / "Application Support" / app_name / filename
else:
cfg = os.getenv("XDG_CONFIG_HOME", str(Path.home() / ".config"))
return Path(cfg) / app_name / filename