Files

182 lines
5.4 KiB
Python

"""Process-wide settings for the FailSafe Translate node."""
import json
import logging
import os
import threading
from .language_models import (
DEFAULT_LOCAL_AUTO_SOURCE_LANGUAGE,
DEFAULT_LOCAL_CPU_LANGUAGES,
LOCAL_MODEL_SPECS,
normalize_local_languages,
)
logger = logging.getLogger("ComfyUI.FailsafeTranslate")
__all__ = ["DEFAULTS", "SECRET_KEYS", "SettingsManager", "all", "update", "reload", "mask"]
DEFAULTS = {
"fallback_enabled": True,
"local_cpu_languages": list(DEFAULT_LOCAL_CPU_LANGUAGES),
"local_auto_source_language": DEFAULT_LOCAL_AUTO_SOURCE_LANGUAGE,
"google_cooldown_minutes": 30,
"google_retries": 0,
"retry_wait_seconds": 3.0,
"final_failure_behavior": "return_input",
"cache_enabled": True,
"cache_max_entries": 256,
}
# Kept for API compatibility with older revisions. There are no secrets now.
SECRET_KEYS = set()
_VALID_FINAL_BEHAVIORS = {"return_input", "return_error", "return_cached", "raise"}
_BOOL_KEYS = {"fallback_enabled", "cache_enabled"}
def _coerce_bool(value, default):
if value is None:
return default
if isinstance(value, bool):
return value
return str(value).strip().lower() in ("true", "1", "yes", "on")
def _coerce(key, value):
"""Coerce an incoming value to the expected type for the given key."""
if key in _BOOL_KEYS:
return _coerce_bool(value, DEFAULTS[key])
if key == "local_cpu_languages":
return normalize_local_languages(value)
if key == "local_auto_source_language":
code = str(value).strip() if value is not None else DEFAULTS[key]
return code if code in LOCAL_MODEL_SPECS else DEFAULTS[key]
if key in ("google_cooldown_minutes", "google_retries", "cache_max_entries"):
try:
iv = int(float(value))
except (TypeError, ValueError):
return DEFAULTS[key]
if key == "google_cooldown_minutes":
return max(1, iv)
if key == "cache_max_entries":
return max(1, iv)
return max(0, iv)
if key == "retry_wait_seconds":
try:
return max(0.0, float(value))
except (TypeError, ValueError):
return DEFAULTS[key]
if key == "final_failure_behavior":
s = str(value).strip() if value is not None else DEFAULTS[key]
return s if s in _VALID_FINAL_BEHAVIORS else DEFAULTS[key]
return DEFAULTS.get(key)
class SettingsManager:
def __init__(self):
self._lock = threading.RLock()
self._path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"failsafe_translate_config.json",
)
self._data = dict(DEFAULTS)
self._data["local_cpu_languages"] = list(DEFAULTS["local_cpu_languages"])
self._load()
def _load(self):
if not os.path.exists(self._path):
return
try:
with open(self._path, "r", encoding="utf-8") as f:
raw = json.load(f)
except Exception as exc: # noqa: BLE001
logger.warning(
"[FailSafeTranslate] could not read settings file %s: %s",
self._path,
exc,
)
return
if not isinstance(raw, dict):
return
with self._lock:
for key, value in raw.items():
if key in DEFAULTS:
self._data[key] = _coerce(key, value)
def _save(self):
try:
with self._lock:
data = dict(self._data)
data["local_cpu_languages"] = list(self._data["local_cpu_languages"])
tmp = self._path + ".tmp"
with open(tmp, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
os.replace(tmp, self._path)
except Exception as exc: # noqa: BLE001
logger.warning(
"[FailSafeTranslate] could not write settings file %s: %s",
self._path,
exc,
)
def all(self):
with self._lock:
out = dict(self._data)
out["local_cpu_languages"] = list(self._data["local_cpu_languages"])
return out
def get(self, key):
with self._lock:
value = self._data.get(key, DEFAULTS.get(key))
return list(value) if key == "local_cpu_languages" and value is not None else value
def update(self, raw):
"""Merge known keys from ``raw`` into memory and persist them."""
changed = {}
if not isinstance(raw, dict):
return changed
with self._lock:
for key, value in raw.items():
if key not in DEFAULTS:
continue
new_value = _coerce(key, value)
if new_value != self._data[key]:
changed[key] = list(new_value) if key == "local_cpu_languages" else new_value
self._data[key] = new_value
if changed:
self._save()
return changed
def reload(self):
with self._lock:
self._data = dict(DEFAULTS)
self._data["local_cpu_languages"] = list(DEFAULTS["local_cpu_languages"])
self._load()
return self.all()
_settings = SettingsManager()
def all():
return _settings.all()
def update(raw):
return _settings.update(raw)
def reload():
return _settings.reload()
def mask(data):
return dict(data) if isinstance(data, dict) else dict(DEFAULTS)