Files
abogen/tests/test_voice_cache.py
T
Artem Akymenko 985e16f1f8 feat: migrate remaining consumers to new Plugin Architecture
- Add compatibility functions to tts_plugin/compat.py:
  - get_metadata(): returns TTSBackendMetadata with voices
  - is_registered_backend(): checks if plugin is loaded
  - resolve_backend_for_voice(): resolves backend for voice spec
  - get_default_voice(): gets default voice for backend

- Update tts_plugin/__init__.py to export new functions

- Migrate all consumers from old tts_backend_registry:
  - WebUI: conversion_runner, debug_tts_runner, routes/api, routes/utils/*
  - PyQt UI: gui, predownload_gui, voice_formula_gui
  - Voice utilities: voice_cache, voice_formulas, voice_profiles
  - Other: subtitle_utils, utils, predownload_gui (root)

- Update tests to use new plugin architecture

Old architecture remains intact as fallback.
2026-07-12 16:20:06 +03:00

70 lines
1.9 KiB
Python

from types import SimpleNamespace
from typing import cast
import pytest
from abogen.tts_plugin.compat import get_metadata
from abogen.voice_cache import (
LocalEntryNotFoundError,
_CACHED_VOICES,
ensure_voice_assets,
)
from abogen.webui.conversion_runner import _collect_required_voice_ids
from abogen.webui.service import Job
@pytest.fixture(autouse=True)
def clear_voice_cache():
_CACHED_VOICES.clear()
yield
_CACHED_VOICES.clear()
def test_ensure_voice_assets_downloads_missing(monkeypatch):
recorded = []
cached = set()
def fake_download(**kwargs):
filename = kwargs["filename"]
if kwargs.get("local_files_only"):
if filename in cached:
return f"/tmp/{filename}"
raise LocalEntryNotFoundError(f"{filename} missing")
recorded.append(filename)
cached.add(filename)
return f"/tmp/{filename}"
monkeypatch.setattr("abogen.voice_cache.hf_hub_download", fake_download)
downloaded, errors = ensure_voice_assets(["af_nova", "am_liam"])
assert downloaded == {"af_nova", "am_liam"}
assert errors == {}
assert set(recorded) == {"voices/af_nova.pt", "voices/am_liam.pt"}
recorded.clear()
downloaded_again, errors_again = ensure_voice_assets(["af_nova"])
assert downloaded_again == set()
assert errors_again == {}
assert recorded == []
def test_collect_required_voice_ids_includes_all():
job = SimpleNamespace(
voice="af_nova",
chapters=[{"voice_formula": "af_nova*0.7+am_liam*0.3"}],
chunks=[{"voice": "am_michael"}],
speakers={
"hero": {"voice_formula": "af_nova*0.6+am_liam*0.4"},
"narrator": {"voice": "af_nova"},
},
)
voices = _collect_required_voice_ids(cast(Job, job))
assert {"af_nova", "am_liam", "am_michael"}.issubset(voices)
assert voices.issuperset(get_metadata("kokoro").voices)