Add JSON serialization support for companion preferences

- Introduced a new utility function, _to_json_safe, to ensure companion preferences are JSON-serializable, handling various data types including enums and dataclasses.
- Updated the RepeaterCompanionBridge to use the new serialization method when saving preferences to SQLite.
- Modified SQLiteHandler to ensure companion_hash is consistently converted to a string before database operations.
- Enhanced error handling for preference persistence in the RepeaterCompanionBridge.
This commit is contained in:
agessaman
2026-03-03 16:20:52 -08:00
parent 4f94b343cc
commit 1fbd99d52c
2 changed files with 24 additions and 2 deletions
+22 -1
View File
@@ -10,6 +10,7 @@ from __future__ import annotations
import dataclasses
import logging
from enum import Enum
from typing import Any, Callable, Optional
from pymc_core.companion import CompanionBridge
@@ -17,6 +18,23 @@ from pymc_core.companion import CompanionBridge
logger = logging.getLogger("RepeaterCompanionBridge")
def _to_json_safe(value: Any) -> Any:
"""Convert a value to a JSON-serializable form (avoids TypeError from enums, bytes, etc.)."""
if value is None or isinstance(value, (bool, int, float, str)):
return value
if isinstance(value, Enum):
return value.value
if isinstance(value, bytes):
return value.hex()
if isinstance(value, (list, tuple)):
return [_to_json_safe(v) for v in value]
if isinstance(value, dict):
return {k: _to_json_safe(v) for k, v in value.items()}
if dataclasses.is_dataclass(value) and not isinstance(value, type):
return {f.name: _to_json_safe(getattr(value, f.name)) for f in dataclasses.fields(value)}
return value
class RepeaterCompanionBridge(CompanionBridge):
"""CompanionBridge that persists and loads prefs (full NodePrefs) via SQLite JSON blob."""
@@ -57,7 +75,10 @@ class RepeaterCompanionBridge(CompanionBridge):
return
try:
prefs_dict = dataclasses.asdict(self.prefs)
self._sqlite_handler.companion_save_prefs(self._companion_hash, prefs_dict)
prefs_safe = _to_json_safe(prefs_dict)
self._sqlite_handler.companion_save_prefs(
str(self._companion_hash), prefs_safe
)
except Exception as e:
logger.warning("Failed to persist companion prefs: %s", e)
+2 -1
View File
@@ -1833,6 +1833,7 @@ class SQLiteHandler:
"""Persist prefs for a companion as JSON. Upserts by companion_hash."""
try:
prefs_json = json.dumps(prefs)
key = str(companion_hash) if companion_hash is not None else ""
with sqlite3.connect(self.sqlite_path) as conn:
conn.execute(
"""
@@ -1840,7 +1841,7 @@ class SQLiteHandler:
VALUES (?, ?)
ON CONFLICT(companion_hash) DO UPDATE SET prefs_json = excluded.prefs_json
""",
(companion_hash, prefs_json),
(key, prefs_json),
)
conn.commit()
return True