aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_hub.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-28 14:57:48 -0400
committerhistoria <historiavg@proton.me>2026-08-28 14:57:48 -0400
commitdb38085d07ce75f8961eecdc1919e98748254c53 (patch)
treebeaea2ba84de05bfc2fa90e9b92a24568d3b4cb9 /app/tests/test_hub.py
parentafb2c2d5b297c5aa28bcced0e3f90e207d799c2a (diff)
downloadtts-audiobook-generator-db38085d07ce75f8961eecdc1919e98748254c53.tar.gz
refactor: overhaul config.py, remove cli default options
Diffstat (limited to 'app/tests/test_hub.py')
-rw-r--r--app/tests/test_hub.py323
1 files changed, 127 insertions, 196 deletions
diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py
index ee1425d..86dd9e3 100644
--- a/app/tests/test_hub.py
+++ b/app/tests/test_hub.py
@@ -916,8 +916,7 @@ class ConvertFlowTests(unittest.TestCase):
patch.object(hub.config, "AUDIO_FORMAT", "m4b"), \
patch.object(hub.config, "LANGUAGE", "English"), \
patch.object(hub.config, "SPEED", 1.25), \
- patch.object(hub.config, "DEBUG", False), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ patch.object(hub.config, "DEBUG", False):
self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="")
cmd = self._convert(
@@ -964,11 +963,10 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "short", "family": "higgs_audio_tts", "task": "tts"},
{"id": "a-much-longer-model-id", "family": "qwen3_tts",
"task": "tts"}])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="short",
- audiocpp_voice="", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="short",
+ audiocpp_voice="", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNotNone(cmd)
choices = self._field("model_id")["choices"]
# "a-much-longer-model-id" is 22 columns wide; both types open at
@@ -990,13 +988,12 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "Qwen3-TTS-12Hz-1.7B-CustomVoice-GGUF",
"family": "qwen3_tts", "task": "tts"}])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(
- backend="audiocpp-remote",
- model_id="Qwen3-TTS-12Hz-1.7B-CustomVoice-GGUF",
- audiocpp_voice="Ryan", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(
+ backend="audiocpp-remote",
+ model_id="Qwen3-TTS-12Hz-1.7B-CustomVoice-GGUF",
+ audiocpp_voice="Ryan", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
# The picked speaker is passed as --voice; no separate speaker kwarg.
self.assertEqual(cmd[2]["voice"], "Ryan")
self.assertNotIn("speaker", cmd[2])
@@ -1016,13 +1013,12 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "Qwen3-TTS-12Hz-1.7B-Base-GGUF",
"family": "qwen3_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(
- backend="audiocpp-remote",
- model_id="Qwen3-TTS-12Hz-1.7B-Base-GGUF",
- audiocpp_voice="narrator", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(
+ backend="audiocpp-remote",
+ model_id="Qwen3-TTS-12Hz-1.7B-Base-GGUF",
+ audiocpp_voice="narrator", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertEqual(cmd[2]["voice"], "narrator")
self.assertNotIn("speaker", cmd[2])
self.assertIsNone(cmd[2]["instructions"])
@@ -1044,12 +1040,11 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "Qwen3-TTS-12Hz-1.7B-Base-GGUF",
"family": "qwen3_tts", "task": "tts"}],
voices=[])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(
- backend="audiocpp-remote",
- model_id="Qwen3-TTS-12Hz-1.7B-Base-GGUF",
- audiocpp_voice="", instructions="")
- self._convert(None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(
+ backend="audiocpp-remote",
+ model_id="Qwen3-TTS-12Hz-1.7B-Base-GGUF",
+ audiocpp_voice="", instructions="")
+ self._convert(None, [self._remote("audiocpp", "audio.cpp")])
fields = self.tui.forms_seen[0][1]
voice_field = self._field("audiocpp_voice")
self.assertTrue(voice_field["visible"](fields))
@@ -1069,9 +1064,7 @@ class ConvertFlowTests(unittest.TestCase):
"models": [{"id": "qwen", "family": "qwen3_tts",
"task": "tts"}],
}), encoding="utf-8")
- with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=root), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ with patch.object(hub.audiocpp_backend, "find_local_checkout", return_value=root):
self._answer_form(backend="audiocpp", model_id="qwen",
audiocpp_voice="", instructions="")
self._convert(None,
@@ -1091,11 +1084,10 @@ class ConvertFlowTests(unittest.TestCase):
# built-in speaker.
self._patch_remote([{"id": "legacy", "family": "", "task": ""}],
voices=[])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="legacy",
- audiocpp_voice="", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="legacy",
+ audiocpp_voice="", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNotNone(cmd)
self.assertIsNone(cmd[2]["voice"])
self.assertNotIn("speaker", cmd[2])
@@ -1106,12 +1098,11 @@ class ConvertFlowTests(unittest.TestCase):
def test_audiocpp_vdes_hides_voice_and_requires_instructions(self):
self._patch_remote(
[{"id": "design", "family": "qwen3_tts", "task": "vdes"}])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="design",
- audiocpp_voice=None,
- instructions="A warm British narrator")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="design",
+ audiocpp_voice=None,
+ instructions="A warm British narrator")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNone(cmd[2]["voice"])
self.assertEqual(cmd[2]["instructions"], "A warm British narrator")
fields = self.tui.forms_seen[0][1]
@@ -1129,12 +1120,11 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="narrator",
- instructions="stale description")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="narrator",
+ instructions="stale description")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertEqual(cmd[2]["instructions"], "stale description")
def test_audiocpp_required_voice_validates(self):
@@ -1142,11 +1132,10 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="narrator", instructions="")
- self._convert(None,
- [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="narrator", instructions="")
+ self._convert(None,
+ [self._remote("audiocpp", "audio.cpp")])
voice_field = self._field("audiocpp_voice")
self.assertIsNotNone(voice_field["validate"](""))
self.assertIsNone(voice_field["validate"]("narrator"))
@@ -1157,14 +1146,12 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "Qwen3-TTS-CustomVoice-GGUF", "family": "qwen3_tts",
"task": "tts"}])
- with patch.object(hub.config, "SPEAKER", "Vivian"), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(
- backend="audiocpp-remote",
- model_id="Qwen3-TTS-CustomVoice-GGUF",
- audiocpp_voice="Vivian", instructions="")
- self._convert(None,
- [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(
+ backend="audiocpp-remote",
+ model_id="Qwen3-TTS-CustomVoice-GGUF",
+ audiocpp_voice="Vivian", instructions="")
+ self._convert(None,
+ [self._remote("audiocpp", "audio.cpp")])
fields = self.tui.forms_seen[0][1]
label = self._field("audiocpp_voice")["label"]
self.assertEqual(label(fields), "Built-in voice")
@@ -1175,12 +1162,11 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "Qwen3-TTS-Base-GGUF", "family": "qwen3_tts",
"task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote",
- model_id="Qwen3-TTS-Base-GGUF",
- audiocpp_voice="narrator", instructions="")
- self._convert(None,
- [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote",
+ model_id="Qwen3-TTS-Base-GGUF",
+ audiocpp_voice="narrator", instructions="")
+ self._convert(None,
+ [self._remote("audiocpp", "audio.cpp")])
fields = self.tui.forms_seen[0][1]
label = self._field("audiocpp_voice")["label"]
self.assertEqual(label(fields), "Voice to clone")
@@ -1192,11 +1178,10 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="", instructions="")
- self._convert(None,
- [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="", instructions="")
+ self._convert(None,
+ [self._remote("audiocpp", "audio.cpp")])
fields = self.tui.forms_seen[0][1]
voice = self._field("audiocpp_voice")
instr = self._field("instructions")
@@ -1211,11 +1196,10 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=[])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
fields = self.tui.forms_seen[0][1]
voice = self._field("audiocpp_voice")
instr = self._field("instructions")
@@ -1230,13 +1214,12 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(
- backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="narrator", instructions="",
- request_options="emotion=neutral, speed=1.1")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(
+ backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="narrator", instructions="",
+ request_options="emotion=neutral, speed=1.1")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertEqual(cmd[2]["request_options"],
{"emotion": "neutral", "speed": "1.1"})
@@ -1244,12 +1227,11 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="narrator", instructions="",
- request_options="oops")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="narrator", instructions="",
+ request_options="oops")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
options_field = self._field("request_options")
self.assertIsNone(options_field["validate"]("emotion=neutral"))
self.assertIsNotNone(options_field["validate"]("oops"))
@@ -1284,9 +1266,7 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=self._specs_checkout(
- ("higgs_audio_tts",))), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ return_value=self._specs_checkout(("higgs_audio_tts",))):
self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="")
cmd = self._convert(
@@ -1302,9 +1282,7 @@ class ConvertFlowTests(unittest.TestCase):
# A checkout exists but only qwen3_tts declares request options:
# higgs is provably unsupported -> hidden.
with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=self._specs_checkout(
- ("qwen3_tts",))), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ return_value=self._specs_checkout(("qwen3_tts",))):
self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="")
self._convert(None,
@@ -1317,9 +1295,7 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=None), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ with patch.object(hub.audiocpp_backend, "find_local_checkout", return_value=None):
self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="")
self._convert(None,
@@ -1335,12 +1311,11 @@ class ConvertFlowTests(unittest.TestCase):
{"id": "design", "family": "qwen3_tts", "task": "vdes"},
{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"},
], voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="design",
- audiocpp_voice=None,
- instructions="A warm British narrator")
- self._convert(None,
- [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="design",
+ audiocpp_voice=None,
+ instructions="A warm British narrator")
+ self._convert(None,
+ [self._remote("audiocpp", "audio.cpp")])
instr = self._field("instructions")
self.assertEqual(instr["help"], [
"TTS style instructions. Supported by some clone models. Example:",
@@ -1352,9 +1327,7 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=self._specs_checkout(
- ("qwen3_tts", "higgs_audio_tts"))), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ return_value=self._specs_checkout(("qwen3_tts", "higgs_audio_tts"))):
self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="")
self._convert(None,
@@ -1371,7 +1344,6 @@ class ConvertFlowTests(unittest.TestCase):
# The Settings Language setting travels on the run kwargs as-is;
# the converter normalizes it (short codes included).
with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
patch.object(hub.config, "LANGUAGE", "en"):
self._answer_form(backend="qwen", mode="custom",
speaker="Vivian", clone="")
@@ -1399,11 +1371,10 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=[])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNotNone(cmd)
self.assertIsNone(cmd[2]["voice"])
fields = self.tui.forms_seen[0][1]
@@ -1429,11 +1400,8 @@ class ConvertFlowTests(unittest.TestCase):
"voice_dir": str(root),
}), encoding="utf-8")
(root / "Narrator.wav").write_bytes(b"x")
- with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=root), \
- patch.object(hub.audiocpp_backend, "fetch_server_models",
- must_not_query), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ with patch.object(hub.audiocpp_backend, "find_local_checkout", return_value=root), \
+ patch.object(hub.audiocpp_backend, "fetch_server_models", must_not_query):
self._answer_form(backend="audiocpp", model_id="qwen",
audiocpp_voice="Narrator", instructions="")
cmd = self._convert(None,
@@ -1456,9 +1424,7 @@ class ConvertFlowTests(unittest.TestCase):
"models": [{"id": "qwen", "family": "qwen3_tts",
"task": "tts"}],
}), encoding="utf-8")
- with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=root), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ with patch.object(hub.audiocpp_backend, "find_local_checkout", return_value=root):
self._answer_form(backend="audiocpp", model_id="qwen",
audiocpp_voice="", instructions="")
cmd = self._convert(None, [
@@ -1496,9 +1462,7 @@ class ConvertFlowTests(unittest.TestCase):
"models": [{"id": "qwen", "family": "qwen3_tts",
"task": "tts"}],
}), encoding="utf-8")
- with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=root), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ with patch.object(hub.audiocpp_backend, "find_local_checkout", return_value=root):
# Managed selected: its picks must survive next to the
# remote entry's same-shaped fields.
self.tui.form_script.append({
@@ -1529,12 +1493,11 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp-remote", model_id="higgs",
- audiocpp_voice="narrator", instructions="")
- cmd = self._convert(
- None, [self._remote("audiocpp", "audio.cpp",
- url="http://10.0.0.5:8080")])
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
+ audiocpp_voice="narrator", instructions="")
+ cmd = self._convert(
+ None, [self._remote("audiocpp", "audio.cpp",
+ url="http://10.0.0.5:8080")])
self.assertEqual(cmd[2]["api_url"], "http://10.0.0.5:8080")
# ------------------------------------------------------------------
@@ -1556,29 +1519,17 @@ class ConvertFlowTests(unittest.TestCase):
# ------------------------------------------------------------------
def test_qwen_builds_speaker_and_clone_form(self):
- with patch.object(hub.qwen_backend, "QWEN_SPEAKERS",
- ["Vivian", "Serena"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
- patch.object(hub.qwen_backend.config, "QWEN_MODEL",
- "CustomVoice"):
+ with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian", "Serena"]):
self._answer_form(backend="qwen", mode="custom", speaker="Serena",
clone="")
- # The fake mirrors the real update_config_value contract:
- # persisting a value also lands it on the imported module.
- def fake_update(key, value, config_path=None):
- setattr(hub.config, key, value)
- return True
-
- with patch.object(hub.common, "update_config_value",
- fake_update):
- cmd = self._convert(None,
- [self._ready("qwen", "qwen-tts")])
- speaker_in_memory = hub.config.SPEAKER
+ cmd = self._convert(None,
+ [self._ready("qwen", "qwen-tts")])
self.assertEqual(cmd[0], "convert")
self.assertEqual(cmd[1], hub.BACKEND_QWEN)
self.assertIsNone(cmd[2]["clone"])
self.assertIsNone(cmd[2].get("instructions"))
- self.assertEqual(speaker_in_memory, "Serena")
+ # The picked speaker travels with the run; nothing is persisted.
+ self.assertEqual(cmd[2]["voice"], "Serena")
fields = self.tui.forms_seen[0][1]
self.assertEqual([f["key"] for f in fields],
["backend", "mode", "speaker", "clone_dir",
@@ -1617,11 +1568,8 @@ class ConvertFlowTests(unittest.TestCase):
self.assertFalse(clone_field["visible"](fields))
self.assertTrue(design_field["visible"](fields))
- def test_qwen_design_mode_passes_instructions_and_persists_model(self):
- with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
- patch.object(hub.qwen_backend.config, "QWEN_MODEL",
- "CustomVoice"):
+ def test_qwen_design_mode_passes_instructions(self):
+ with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]):
self._answer_form(backend="qwen", mode="design",
qwen_instructions="A warm narrator")
with patch.object(hub.common, "update_config_value") as mk_update:
@@ -1629,51 +1577,37 @@ class ConvertFlowTests(unittest.TestCase):
[self._ready("qwen", "qwen-tts")])
self.assertEqual(cmd[2]["clone"], None)
self.assertEqual(cmd[2]["instructions"], "A warm narrator")
- # The model switch is persisted (CustomVoice -> VoiceDesign).
- mk_update.assert_called_once_with("QWEN_MODEL", "VoiceDesign")
+ # Per-run choices are not persisted to the config file.
+ mk_update.assert_not_called()
- def test_qwen_clone_mode_passes_path_and_persists_model(self):
- with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
- patch.object(hub.qwen_backend.config, "QWEN_MODEL",
- "CustomVoice"):
+ def test_qwen_clone_mode_passes_path(self):
+ with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]):
self._answer_form(backend="qwen", mode="clone", speaker="Vivian",
clone="/tmp/ref.wav")
with patch.object(hub.common, "update_config_value") as mk_update:
cmd = self._convert(None,
- [self._ready("qwen", "qwen-tts")])
+ [self._ready("qwen", "qwen-tts")])
self.assertEqual(cmd[2]["clone"], "/tmp/ref.wav")
- # Clone mode does not touch the global speaker.
- keys = [c.args[0] for c in mk_update.call_args_list]
- self.assertNotIn("SPEAKER", keys)
- # ...but remembers the switch to the Base model.
- self.assertEqual(keys, ["QWEN_MODEL"])
- self.assertEqual(mk_update.call_args.args[1], "Base")
-
- def test_qwen_same_model_run_persists_nothing_new(self):
- with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
- patch.object(hub.qwen_backend.config, "QWEN_MODEL",
- "CustomVoice"):
+ mk_update.assert_not_called()
+
+ def test_qwen_custom_mode_passes_the_speaker(self):
+ with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]):
self._answer_form(backend="qwen", mode="custom", speaker="Vivian")
with patch.object(hub.common, "update_config_value") as mk_update:
cmd = self._convert(None,
[self._ready("qwen", "qwen-tts")])
self.assertIsNotNone(cmd)
+ self.assertEqual(cmd[2]["voice"], "Vivian")
mk_update.assert_not_called()
- def test_qwen_form_opens_on_the_configured_model(self):
- # The persisted QWEN_MODEL seeds the Model picker's default, so the
- # form opens on what the last run chose (not always the first row).
+ def test_qwen_form_defaults_to_the_first_model(self):
+ # No persisted default: the Model picker opens on CustomVoice.
with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
- patch.object(hub.qwen_backend.config, "QWEN_MODEL",
- "VoiceDesign"), \
patch.object(hub.common, "update_config_value"):
self._answer_form(backend="qwen", mode="design",
qwen_instructions="A warm narrator")
self._convert(None, [self._ready("qwen", "qwen-tts")])
- self.assertEqual(self._field("mode")["value"], "design")
+ self.assertEqual(self._field("mode")["value"], "custom")
def test_qwen_clone_dir_defaults_to_the_project_voices(self):
# The Clone .wav directory is the shared directory widget, seeded
@@ -1689,9 +1623,7 @@ class ConvertFlowTests(unittest.TestCase):
("narrator.wav", str(root / "narrator.wav")),
]
with patch.object(hub.common, "VOICES_DIR", root), \
- patch.object(hub.qwen_backend, "QWEN_SPEAKERS",
- ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
+ patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
patch.object(hub.common, "update_config_value"):
self._answer_form(backend="qwen", mode="custom",
speaker="Vivian")
@@ -1720,9 +1652,7 @@ class ConvertFlowTests(unittest.TestCase):
(other / "beta.wav").write_bytes(b"")
(other / "alpha.wav").write_bytes(b"")
with patch.object(hub.common, "VOICES_DIR", root), \
- patch.object(hub.qwen_backend, "QWEN_SPEAKERS",
- ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
+ patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
patch.object(hub.common, "update_config_value"):
self._answer_form(backend="qwen", mode="clone", clone="")
self._convert(None, [self._ready("qwen", "qwen-tts")])
@@ -1746,9 +1676,7 @@ class ConvertFlowTests(unittest.TestCase):
with tempfile.TemporaryDirectory() as td:
empty = Path(td)
with patch.object(hub.common, "VOICES_DIR", empty), \
- patch.object(hub.qwen_backend, "QWEN_SPEAKERS",
- ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"), \
+ patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
patch.object(hub.common, "update_config_value"):
self._answer_form(backend="qwen", mode="clone", clone="")
cmd = self._convert(None,
@@ -1846,8 +1774,7 @@ class ConvertFlowTests(unittest.TestCase):
"qwen", "qwen-tts",
remote_urls={"qwen": "http://10.0.0.5:7861"},
remote_models=["Base"])
- with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
- patch.object(hub.config, "SPEAKER", "Vivian"):
+ with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]):
self._answer_form(backend="qwen-remote", mode="clone",
speaker="Vivian", clone="/tmp/ref.wav")
cmd = self._convert(None, [st])
@@ -1870,9 +1797,7 @@ class ConvertFlowTests(unittest.TestCase):
"models": [{"id": "higgs", "family": "higgs_audio_tts",
"task": "tts"}],
}), encoding="utf-8")
- with patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=root), \
- patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ with patch.object(hub.audiocpp_backend, "find_local_checkout", return_value=root):
self._answer_form(backend="qwen", mode="custom",
speaker="Vivian", clone="")
cmd = self._convert(None, [
@@ -1974,7 +1899,11 @@ class PrepareRunConfigTests(unittest.TestCase):
with patch.object(hub, "detect_all", return_value=[]), \
patch.object(hub, "_find_spec", return_value=spec):
cfg = hub._prepare_run_config("qwen", kwargs)
- self.assertIs(cfg.autostart_spec, spec)
+ # The qwen spec is rebuilt for the model this run selected, so an
+ # autostart boots exactly what the conversion needs.
+ self.assertEqual(cfg.autostart_spec.name, "qwen")
+ self.assertEqual(cfg.autostart_spec.identity, "qwen-custom")
+ self.assertEqual(cfg.autostart_spec.url, spec.url)
self.assertFalse(cfg.restart_first)
self.assertEqual(cfg.server_name, "qwen")
self.assertNotIn("autostart", kwargs)
@@ -1985,13 +1914,15 @@ class PrepareRunConfigTests(unittest.TestCase):
spec = self._spec()
status = BackendStatus("qwen", "qwen-tts", installed=True,
configured=True, servers=[spec])
- kwargs = {"restart_server": "qwen"}
+ kwargs = {"restart_server": "qwen", "clone": "/tmp/ref.wav"}
with patch.object(hub, "detect_all", return_value=[status]), \
patch("backends.common.server_running",
return_value=True), \
patch.object(hub.servers, "alive", return_value=True):
cfg = hub._prepare_run_config("qwen", kwargs)
- self.assertIs(cfg.autostart_spec, spec)
+ self.assertEqual(cfg.autostart_spec.name, spec.name)
+ # The restart spec hosts the Base model (the run clones a voice).
+ self.assertEqual(cfg.autostart_spec.identity, "qwen-clone")
self.assertTrue(cfg.restart_first)
self.assertNotIn("restart_server", kwargs)
self.assertEqual(cfg.server_url, spec.url)