mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-06-24 03:51:11 +02:00
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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user