mirror of
https://github.com/denizsafak/abogen.git
synced 2026-09-20 19:50:59 +02:00
refactor: unify Language enum across all layers
- EngineConfig.language: Language (was lang_code: str = 'a') - Engine owns _KOKORO_LANG_MAP, engine_language(), supported_languages() - Engine provides language_for_voice_id() for voice catalog - Plugins/kokoro/__init__.py calls engine_language() internally - create_pipeline(plugin_id, language=Language) — no kokoro codes - pipeline_factory.py clean of kokoro-specific code - Domain functions raise TypeError if non-enum passed - WebUI api.py: _parse_language() helper at API boundary - Voice catalog returns ISO codes (lang.value) - Constants: LANGUAGE_DESCRIPTIONS keyed by Language enum - All tests updated for Language enum - 1414 tests pass
This commit is contained in:
@@ -14,6 +14,8 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import numpy as np
|
||||
|
||||
from abogen.domain.enums import Language
|
||||
|
||||
from abogen.tts_plugin.engine import Engine, EngineSession
|
||||
from abogen.tts_plugin.errors import EngineError
|
||||
from abogen.tts_plugin.plugin_manager import PluginManager, get_plugin_manager, reset_plugin_manager
|
||||
@@ -328,7 +330,7 @@ class TestRegression:
|
||||
manager._loaded = True
|
||||
|
||||
with patch("abogen.tts_plugin.utils.get_plugin_manager", return_value=manager):
|
||||
backend = create_pipeline("mock_tts", lang_code="a", device="cpu")
|
||||
backend = create_pipeline("mock_tts", language=Language.EN_US, device="cpu")
|
||||
|
||||
# Old interface: pipeline(text, voice=..., speed=..., split_pattern=...)
|
||||
segments = list(backend(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from abogen.domain.enums import Language
|
||||
from abogen.tts_plugin.plugin_manager import PluginManager, get_plugin_manager, reset_plugin_manager
|
||||
from abogen.tts_plugin.utils import Pipeline, create_pipeline
|
||||
from abogen.tts_plugin.engine import Engine, EngineSession
|
||||
@@ -175,7 +176,7 @@ class TestCreatePipelineCompat:
|
||||
mock_engine = FakeEngine()
|
||||
mock_manager.create_engine.return_value = mock_engine
|
||||
|
||||
backend = create_pipeline("kokoro", lang_code="a", device="cpu")
|
||||
backend = create_pipeline("kokoro", language=Language.EN_US, device="cpu")
|
||||
|
||||
assert callable(backend)
|
||||
mock_manager.create_engine.assert_called_once()
|
||||
@@ -185,7 +186,7 @@ class TestCreatePipelineCompat:
|
||||
assert call_args.kwargs["model_path"] is None
|
||||
assert isinstance(call_args.kwargs["config"], EngineConfig)
|
||||
assert call_args.kwargs["config"].device == "cpu"
|
||||
assert call_args.kwargs["config"].lang_code == "a"
|
||||
assert call_args.kwargs["config"].language == Language.EN_US
|
||||
|
||||
def test_create_pipeline_raises_for_unknown_plugin(self):
|
||||
"""create_pipeline raises KeyError for unknown plugins."""
|
||||
|
||||
@@ -8,6 +8,7 @@ These tests verify that value objects satisfy the architectural requirements:
|
||||
|
||||
import pytest
|
||||
|
||||
from abogen.domain.enums import Language
|
||||
from abogen.tts_plugin.types import (
|
||||
AudioFormat,
|
||||
Duration,
|
||||
@@ -192,23 +193,23 @@ class TestEngineConfigContract:
|
||||
config = EngineConfig(device="cuda:0")
|
||||
assert config.device == "cuda:0"
|
||||
|
||||
def test_default_lang_code(self) -> None:
|
||||
def test_default_language(self) -> None:
|
||||
config = EngineConfig()
|
||||
assert config.lang_code == "a"
|
||||
assert config.language == Language.EN_US
|
||||
|
||||
def test_custom_lang_code(self) -> None:
|
||||
config = EngineConfig(lang_code="j")
|
||||
assert config.lang_code == "j"
|
||||
def test_custom_language(self) -> None:
|
||||
config = EngineConfig(language=Language.JA)
|
||||
assert config.language == Language.JA
|
||||
|
||||
def test_immutability(self) -> None:
|
||||
config = EngineConfig()
|
||||
with pytest.raises(AttributeError):
|
||||
config.device = "cuda:0" # type: ignore[misc]
|
||||
|
||||
def test_immutability_lang_code(self) -> None:
|
||||
def test_immutability_language(self) -> None:
|
||||
config = EngineConfig()
|
||||
with pytest.raises(AttributeError):
|
||||
config.lang_code = "j" # type: ignore[misc]
|
||||
config.language = Language.JA # type: ignore[misc]
|
||||
|
||||
def test_unknown_keys_ignored_per_spec(self) -> None:
|
||||
"""Architecture spec: Unknown keys are ignored (no error).
|
||||
@@ -225,11 +226,11 @@ class TestEngineConfigContract:
|
||||
EngineConfig may contain fields that are not relevant to every plugin.
|
||||
Plugins MUST ignore fields they do not need, not raise on them.
|
||||
"""
|
||||
config = EngineConfig(device="cuda:0", lang_code="j")
|
||||
config = EngineConfig(device="cuda:0", language=Language.JA)
|
||||
assert config.device == "cuda:0"
|
||||
assert config.lang_code == "j"
|
||||
assert config.language == Language.JA
|
||||
# A plugin that only needs device simply reads config.device
|
||||
# and ignores config.lang_code — this must not raise.
|
||||
# and ignores config.language — this must not raise.
|
||||
|
||||
def test_engine_config_contains_engine_instance_configuration(self) -> None:
|
||||
"""Architecture Amendment #1: EngineConfig definition.
|
||||
@@ -238,7 +239,7 @@ class TestEngineConfigContract:
|
||||
Engine instance is created and that remain constant throughout
|
||||
the lifetime of that Engine.
|
||||
"""
|
||||
config = EngineConfig(device="cpu", lang_code="a")
|
||||
config = EngineConfig(device="cpu", language=Language.EN_US)
|
||||
# Both fields are init-time, immutable, engine-scoped.
|
||||
assert config.device == "cpu"
|
||||
assert config.lang_code == "a"
|
||||
assert config.language == Language.EN_US
|
||||
|
||||
Reference in New Issue
Block a user