aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_hub.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/tests/test_hub.py')
-rw-r--r--app/tests/test_hub.py273
1 files changed, 217 insertions, 56 deletions
diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py
index f40b72d..725f4f6 100644
--- a/app/tests/test_hub.py
+++ b/app/tests/test_hub.py
@@ -75,29 +75,33 @@ class HubHelperTests(unittest.TestCase):
def test_status_mark(self):
from backends import BackendStatus
- running = BackendStatus("k", "l", installed=True, configured=True,
- running=True, managed=True)
+ local = BackendStatus("k", "l", installed=True, configured=True,
+ running=True, managed=True)
remote = BackendStatus("k", "l", installed=True, configured=True,
- running=True)
+ running=True, remote=True)
+ both = BackendStatus("k", "l", installed=True, configured=True,
+ running=True, managed=True, remote=True)
models = BackendStatus("k", "l", installed=True, configured=True,
running=True, managed=True,
running_models=["Base", "CustomVoice"])
remote_models = BackendStatus("k", "l", installed=True,
configured=True, running=True,
- running_models=["Base"])
+ remote=True, running_models=["Base"])
installed = BackendStatus("k", "l", installed=True,
configured=False)
none = BackendStatus("k", "l", installed=False, configured=False)
# running beats installed (a server is up even if not configured);
# only a backend that is neither installed nor running is dimmed.
- self.assertEqual(hub._status_mark(running),
- ("running", "ok", "body"))
- # A server without a live recorded pid was started externally.
+ self.assertEqual(hub._status_mark(local),
+ ("running [local]", "ok", "body"))
+ # A server this tool did not start, found at the remote URL.
self.assertEqual(hub._status_mark(remote),
("running [remote]", "ok", "body"))
+ self.assertEqual(hub._status_mark(both),
+ ("running [local, remote]", "ok", "body"))
# Multi-model backends name the models that answered.
self.assertEqual(hub._status_mark(models),
- ("running (Base, CustomVoice)", "ok", "body"))
+ ("running [local] (Base, CustomVoice)", "ok", "body"))
self.assertEqual(hub._status_mark(remote_models),
("running [remote] (Base)", "ok", "body"))
self.assertEqual(hub._status_mark(installed),
@@ -183,12 +187,13 @@ class HubMenuTests(unittest.TestCase):
dead = self._none_status("audiocpp", "audio.cpp")
external = self._none_status("qwen", "qwen-tts")
external.running = True
+ external.remote = True
with patch.object(hub.tui, "menu", fake_menu), \
patch.object(hub, "detect_all",
return_value=[dead, external]):
hub._hub_menu(screen)
# Unusable backend: dim name. Running-but-not-installed stays
- # bright and is tagged remote (no pid file → not started by us).
+ # bright and is tagged remote (found at its remote URL).
self.assertEqual(
captured["rows"],
[("audio.cpp", "unavailable", "err", "dim"),
@@ -308,7 +313,7 @@ class SubmenuStatusTableTests(unittest.TestCase):
BackendStatus("audiocpp", "audio.cpp", installed=True,
configured=True),
BackendStatus("qwen", "qwen-tts", installed=False,
- configured=False, running=True),
+ configured=False, running=True, remote=True),
]
with patch.object(hub, "REGISTRY", infos), \
patch.object(hub.tui, "menu",
@@ -468,35 +473,45 @@ class ConvertFlowTests(unittest.TestCase):
# ------------------------------------------------------------------
def _patch_remote(self, models, voices=None):
- """No local checkout; fetch helpers return MODELS/VOICES."""
- checkout = patch.object(hub.audiocpp_backend, "find_local_checkout",
- return_value=None)
+ """Fetch helpers return MODELS/VOICES for a remote audio.cpp server."""
fetched_models = patch.object(hub.audiocpp_backend,
"fetch_server_models",
lambda url: models)
fetched_voices = patch.object(hub.audiocpp_backend,
"fetch_server_voices",
lambda url, model_id: voices)
- for patcher in (checkout, fetched_models, fetched_voices):
+ for patcher in (fetched_models, fetched_voices):
patcher.start()
self.addCleanup(patcher.stop)
+ def _remote(self, key, label, spec_name=None, url=None,
+ remote_urls=None, remote_models=None):
+ """A running remote backend status (not installed on this machine)."""
+ if remote_urls is None:
+ remote_urls = {spec_name or key:
+ url or f"http://{key}.local:8080"}
+ return BackendStatus(key, label, installed=False, configured=False,
+ running=True, remote=True,
+ remote_urls=remote_urls,
+ remote_models=list(remote_models or []))
+
def test_audiocpp_remote_builds_one_form(self):
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", model_id="higgs",
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="",
speed="1.5")
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertEqual(cmd[0], "convert")
self.assertEqual(cmd[1], hub.BACKEND_AUDIOCPP)
kwargs = cmd[2]
self.assertEqual(kwargs["model_id"], "higgs")
self.assertEqual(kwargs["voice"], "narrator")
self.assertIsNone(kwargs["instructions"])
+ self.assertEqual(kwargs["api_url"], "http://audiocpp.local:8080")
self.assertEqual(kwargs["output_format"], "m4b")
self.assertEqual(kwargs["speed"], 1.5)
self.assertFalse(kwargs["single_file"])
@@ -511,8 +526,9 @@ class ConvertFlowTests(unittest.TestCase):
"single_file", "debug"])
self.assertEqual(form_kwargs["buttons"], ("Generate!", "Cancel"))
self.assertTrue(form_kwargs["start_on_buttons"])
- # The backend field offers the ready backend.
- self.assertEqual(fields[0]["choices"], [("audio.cpp", "audiocpp")])
+ # The backend field offers the remote entry under a [remote] label.
+ self.assertEqual(fields[0]["choices"],
+ [("audio.cpp [remote]", "audiocpp-remote")])
# The model menu was fed from the live query (label, id).
self.assertEqual(self._field("model_id")["choices"],
[("higgs (higgs_audio_tts, tts)", "higgs")])
@@ -522,11 +538,11 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "qwen", "family": "qwen3_tts", "task": "tts"}],
voices=["narrator"])
with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp", model_id="qwen",
+ self._answer_form(backend="audiocpp-remote", model_id="qwen",
audiocpp_voice="(built-in speaker)",
instructions="")
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ None, [self._remote("audiocpp", "audio.cpp")])
# The sentinel maps to "no voice" (built-in speaker).
self.assertIsNone(cmd[2]["voice"])
fields = self.tui.forms_seen[0][1]
@@ -542,11 +558,11 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote([{"id": "legacy", "family": "", "task": ""}],
voices=[])
with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp", model_id="legacy",
+ self._answer_form(backend="audiocpp-remote", model_id="legacy",
audiocpp_voice="(built-in speaker)",
instructions="")
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNotNone(cmd)
self.assertIsNone(cmd[2]["voice"])
@@ -554,11 +570,11 @@ class ConvertFlowTests(unittest.TestCase):
self._patch_remote(
[{"id": "design", "family": "qwen3_tts", "task": "vdes"}])
with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp", model_id="design",
+ self._answer_form(backend="audiocpp-remote", model_id="design",
audiocpp_voice=None,
instructions="A warm British narrator")
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ 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]
@@ -574,25 +590,25 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=["narrator"])
with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp", model_id="higgs",
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="narrator", instructions="")
hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ [self._remote("audiocpp", "audio.cpp")])
voice_field = self._field("audiocpp_voice")
self.assertIsNotNone(voice_field["validate"](""))
self.assertIsNone(voice_field["validate"]("narrator"))
def test_audiocpp_remote_unreachable_models_flash_and_abort(self):
self._patch_remote(None) # endpoint did not answer valid JSON
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNone(cmd)
self.assertIn("Could not list models", self.tui.flashes[0])
def test_audiocpp_remote_empty_models_flash_and_abort(self):
self._patch_remote([])
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNone(cmd)
self.assertIn("hosts no model entries", self.tui.flashes[0])
@@ -603,10 +619,10 @@ class ConvertFlowTests(unittest.TestCase):
[{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
voices=[])
with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="audiocpp", model_id="higgs",
+ self._answer_form(backend="audiocpp-remote", model_id="higgs",
audiocpp_voice="", instructions="")
- cmd = hub._convert_menu(None,
- [self._ready("audiocpp", "audio.cpp")])
+ cmd = hub._convert_menu(
+ None, [self._remote("audiocpp", "audio.cpp")])
self.assertIsNotNone(cmd)
self.assertIsNone(cmd[2]["voice"])
fields = self.tui.forms_seen[0][1]
@@ -646,6 +662,50 @@ class ConvertFlowTests(unittest.TestCase):
self.assertEqual(cmd[2]["model_id"], "qwen")
self.assertEqual(cmd[2]["voice"], "Narrator")
+ def test_managed_and_remote_both_offered(self):
+ # A ready managed audio.cpp (server.json) AND a running remote
+ # audio.cpp: both entries appear. The managed entry reads server.json
+ # (no api_url), the remote entry live-queries (api_url set).
+ self._patch_remote(
+ [{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
+ voices=["narrator"])
+ with tempfile.TemporaryDirectory() as td:
+ root = Path(td)
+ (root / "server.json").write_text(json.dumps({
+ "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", ""):
+ self._answer_form(backend="audiocpp", model_id="qwen",
+ audiocpp_voice="(built-in speaker)",
+ instructions="")
+ cmd = hub._convert_menu(None, [
+ self._ready("audiocpp", "audio.cpp"),
+ self._remote("audiocpp", "audio.cpp")])
+ self.assertEqual(cmd[0], "convert")
+ self.assertEqual(cmd[1], hub.BACKEND_AUDIOCPP)
+ # Managed entry: no api_url override (uses the configured local URL).
+ self.assertNotIn("api_url", cmd[2])
+ self.assertEqual(cmd[2]["model_id"], "qwen")
+ fields = self.tui.forms_seen[0][1]
+ self.assertEqual(fields[0]["choices"],
+ [("audio.cpp", "audiocpp"),
+ ("audio.cpp [remote]", "audiocpp-remote")])
+
+ def test_audiocpp_remote_mapper_adds_api_url(self):
+ 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 = hub._convert_menu(
+ 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")
+
# ------------------------------------------------------------------
# common fields: output format, speed, single-file, debug
# ------------------------------------------------------------------
@@ -740,6 +800,36 @@ class ConvertFlowTests(unittest.TestCase):
self.assertEqual(voice_field["choices"],
[("default", "default"), ("obama", "obama")])
+ def test_faster_remote_uses_text_voice_and_api_url(self):
+ st = self._remote("faster", "faster-qwen3-tts",
+ url="http://10.0.0.5:8000")
+ self._answer_form(backend="faster-remote", faster_voice="obama")
+ cmd = hub._convert_menu(None, [st])
+ self.assertEqual(cmd[0], "convert")
+ self.assertEqual(cmd[1], "faster")
+ self.assertEqual(cmd[2]["voice"], "obama")
+ self.assertEqual(cmd[2]["api_url"], "http://10.0.0.5:8000")
+ self.assertEqual(self._field("faster_voice")["kind"], "text")
+
+ def test_qwen_remote_limited_modes_and_api_url(self):
+ # A remote qwen with only the Base (clone) demo answering: the form
+ # offers only clone mode and targets the clone remote URL.
+ st = self._remote(
+ "qwen", "qwen-tts",
+ remote_urls={"qwen-clone": "http://10.0.0.5:7861"},
+ remote_models=["Base"])
+ with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \
+ patch.object(hub.config, "SPEAKER", "Vivian"):
+ self._answer_form(backend="qwen-remote", mode="clone",
+ speaker="Vivian", clone="/tmp/ref.wav")
+ cmd = hub._convert_menu(None, [st])
+ self.assertEqual(cmd[1], hub.BACKEND_QWEN)
+ self.assertEqual(cmd[2]["clone"], "/tmp/ref.wav")
+ self.assertEqual(cmd[2]["api_url"], "http://10.0.0.5:7861")
+ fields = self.tui.forms_seen[0][1]
+ self.assertEqual(self._field("mode")["choices"],
+ [("Clone from a .wav file", "clone")])
+
# ------------------------------------------------------------------
# multiple backends: the Backend picker gates which options show
# ------------------------------------------------------------------
@@ -747,15 +837,20 @@ class ConvertFlowTests(unittest.TestCase):
def test_multiple_backends_gate_options_on_backend_value(self):
# Two ready backends: the form leads with a Backend picker and the
# per-backend fields are hidden/shown by its value.
- self._patch_remote(
- [{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}],
- voices=["narrator"])
- with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
- self._answer_form(backend="qwen", mode="custom", speaker="Vivian",
- clone="")
- cmd = hub._convert_menu(None, [
- self._ready("audiocpp", "audio.cpp"),
- self._ready("qwen", "qwen-tts")])
+ with tempfile.TemporaryDirectory() as td:
+ root = Path(td)
+ (root / "server.json").write_text(json.dumps({
+ "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", ""):
+ self._answer_form(backend="qwen", mode="custom",
+ speaker="Vivian", clone="")
+ cmd = hub._convert_menu(None, [
+ self._ready("audiocpp", "audio.cpp"),
+ self._ready("qwen", "qwen-tts")])
self.assertEqual(cmd[0], "convert")
self.assertEqual(cmd[1], hub.BACKEND_QWEN)
fields = self.tui.forms_seen[0][1]
@@ -882,6 +977,33 @@ class RunConversionTests(unittest.TestCase):
hub._run_conversion("qwen", {})
mk_conv.assert_called_once()
+ def test_remote_conversion_skips_setup_checks(self):
+ # A remote conversion targets an external server: no autostart, no
+ # "not fully set up" warning, no launch hint — just convert.
+ with patch.object(hub, "detect_all", return_value=[]) as mk_detect, \
+ patch.object(hub.audiobook, "convert", return_value=0) as mk_conv:
+ hub._run_conversion("audiocpp", {"api_url": "http://10.0.0.5:8080"})
+ mk_conv.assert_called_once_with(
+ backend="audiocpp", api_url="http://10.0.0.5:8080")
+ # The remote path never re-detects or touches managed-instance state.
+ mk_detect.assert_not_called()
+
+ def test_managed_conversion_warns_when_port_occupied_by_other_server(self):
+ spec = ServerSpec("audiocpp", "http://127.0.0.1:8080", ["x"])
+ status = BackendStatus("audiocpp", "audio.cpp", installed=True,
+ configured=True, running=False,
+ servers=[spec])
+ with patch.object(hub, "detect_all", return_value=[status]), \
+ patch.object(hub, "_select_spec", return_value=spec), \
+ patch("backends.common.server_running", return_value=True), \
+ patch.object(hub.servers, "alive", return_value=False), \
+ patch.object(hub.audiobook, "convert", return_value=0) as mk_conv, \
+ patch("builtins.print") as mk_print:
+ hub._run_conversion("audiocpp", {})
+ mk_conv.assert_called_once()
+ printed = " ".join(str(call.args[0]) for call in mk_print.call_args_list)
+ self.assertIn("did not start", printed)
+
class AddAutostartTests(unittest.TestCase):
"""_add_autostart: always starts the server when it isn't running."""
@@ -906,6 +1028,13 @@ class AddAutostartTests(unittest.TestCase):
hub._add_autostart(cmd, [self._status()])
self.assertNotIn("autostart", cmd[2])
+ def test_no_autostart_for_remote_conversion(self):
+ # A remote conversion (api_url set) never autostarts: the server is
+ # external to this tool, so there is nothing to start/stop here.
+ cmd = ("convert", "audiocpp", {"api_url": "http://10.0.0.5:8080"})
+ hub._add_autostart(cmd, [])
+ self.assertNotIn("autostart", cmd[2])
+
class SettingsTests(unittest.TestCase):
"""Settings menu: field collection, validation, config.py writing."""
@@ -955,17 +1084,24 @@ class SettingsTests(unittest.TestCase):
original = {name: getattr(hub.config, name) for name in
("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE",
"CHUNK_SIZE", "QWEN_API_URL", "CLONE_API_URL",
- "FASTER_API_URL", "AUDIOCPP_API_URL")}
+ "FASTER_API_URL", "AUDIOCPP_API_URL",
+ "QWEN_REMOTE_URL", "CLONE_REMOTE_URL",
+ "FASTER_REMOTE_URL", "AUDIOCPP_REMOTE_URL")}
self.addCleanup(lambda: [setattr(hub.config, name, value)
for name, value in original.items()])
values = {"audio_format": "ogg", "audio_bitrate": " 192k ",
"language": "en", "chunk_size": "300",
"qwen_custom_port": "7862", "qwen_clone_port": "7863",
- "faster_port": "8001", "audiocpp_port": "8081"}
+ "faster_port": "8001", "audiocpp_port": "8081",
+ "audiocpp_remote_url": "10.0.0.5:8080",
+ "faster_remote_url": "http://10.0.0.6:8000",
+ "qwen_custom_remote_url": "",
+ "qwen_clone_remote_url": ""}
with patch.object(hub, "_write_config", fake_write), \
patch.object(hub, "_sync_audiocpp_server_port"):
hub._apply_settings(values)
- # Values are trimmed and language normalized to a display name.
+ # Values are trimmed and language normalized to a display name;
+ # remote URLs are normalized to full http(s) URLs (empty = off).
self.assertEqual(written, {"AUDIO_FORMAT": "ogg",
"AUDIO_BITRATE": "192k",
"LANGUAGE": "English",
@@ -974,7 +1110,13 @@ class SettingsTests(unittest.TestCase):
"CLONE_API_URL": "http://127.0.0.1:7863",
"FASTER_API_URL": "http://127.0.0.1:8001",
"AUDIOCPP_API_URL":
- "http://127.0.0.1:8081"})
+ "http://127.0.0.1:8081",
+ "QWEN_REMOTE_URL": "",
+ "CLONE_REMOTE_URL": "",
+ "FASTER_REMOTE_URL":
+ "http://10.0.0.6:8000",
+ "AUDIOCPP_REMOTE_URL":
+ "http://10.0.0.5:8080"})
# In-memory config is reloaded so this session sees the change.
self.assertEqual(hub.config.AUDIO_FORMAT, "ogg")
self.assertEqual(hub.config.AUDIO_BITRATE, "192k")
@@ -982,12 +1124,16 @@ class SettingsTests(unittest.TestCase):
self.assertEqual(hub.config.CHUNK_SIZE, 300)
self.assertEqual(hub.config.QWEN_API_URL, "http://127.0.0.1:7862")
self.assertEqual(hub.config.FASTER_API_URL, "http://127.0.0.1:8001")
+ self.assertEqual(hub.config.AUDIOCPP_REMOTE_URL,
+ "http://10.0.0.5:8080")
def test_apply_settings_rejects_bad_values(self):
original = {name: getattr(hub.config, name) for name in
("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE",
"CHUNK_SIZE", "QWEN_API_URL", "CLONE_API_URL",
- "FASTER_API_URL", "AUDIOCPP_API_URL")}
+ "FASTER_API_URL", "AUDIOCPP_API_URL",
+ "QWEN_REMOTE_URL", "CLONE_REMOTE_URL",
+ "FASTER_REMOTE_URL", "AUDIOCPP_REMOTE_URL")}
self.addCleanup(lambda: [setattr(hub.config, name, value)
for name, value in original.items()])
base = {"audio_format": "m4b", "audio_bitrate": "128k",
@@ -1001,6 +1147,9 @@ class SettingsTests(unittest.TestCase):
hub._apply_settings({**base, "chunk_size": "0"})
with self.assertRaises(ValueError):
hub._apply_settings({**base, "audiocpp_port": "70000"})
+ with self.assertRaises(ValueError):
+ hub._apply_settings({**base,
+ "audiocpp_remote_url": "not a url"})
mk_write.assert_not_called()
def test_field_validators(self):
@@ -1044,18 +1193,24 @@ class SettingsTests(unittest.TestCase):
self.assertEqual([f["key"] for f in captured["fields"]],
["audio_format", "audio_bitrate", "language",
"chunk_size", "audiocpp_port", "faster_port",
- "qwen_custom_port", "qwen_clone_port"])
+ "qwen_custom_port", "qwen_clone_port",
+ "audiocpp_remote_url", "faster_remote_url",
+ "qwen_custom_remote_url", "qwen_clone_remote_url"])
kinds = {f["key"]: f["kind"] for f in captured["fields"]}
self.assertEqual(kinds["audio_format"], "choice")
self.assertEqual(kinds["audio_bitrate"], "text")
self.assertEqual(kinds["audiocpp_port"], "text")
+ self.assertEqual(kinds["audiocpp_remote_url"], "text")
labels = {f["key"]: f["label"] for f in captured["fields"]}
self.assertEqual(labels["qwen_clone_port"], "qwen-tts Base port")
+ self.assertEqual(labels["audiocpp_remote_url"],
+ "audio.cpp remote URL")
self.assertNotIn("(clone)", " ".join(labels.values()))
- # The ports section note hangs off the first port field so it
- # renders between the output settings and the ports.
+ # The ports section note hangs off the first port field, the remote
+ # section note off the first remote URL field.
notes = {f["key"]: f.get("note") for f in captured["fields"]}
self.assertTrue(notes["audiocpp_port"])
+ self.assertTrue(notes["audiocpp_remote_url"])
self.assertIsNone(notes["audio_format"])
self.assertIsNone(notes["qwen_custom_port"])
self.assertEqual(applied, [{"audio_format": "ogg",
@@ -1094,7 +1249,9 @@ class SettingsTests(unittest.TestCase):
original = {name: getattr(hub.config, name) for name in
("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE",
"CHUNK_SIZE", "QWEN_API_URL", "CLONE_API_URL",
- "FASTER_API_URL", "AUDIOCPP_API_URL")}
+ "FASTER_API_URL", "AUDIOCPP_API_URL",
+ "QWEN_REMOTE_URL", "CLONE_REMOTE_URL",
+ "FASTER_REMOTE_URL", "AUDIOCPP_REMOTE_URL")}
self.addCleanup(lambda: [setattr(hub.config, name, value)
for name, value in original.items()])
@@ -1110,7 +1267,11 @@ class SettingsTests(unittest.TestCase):
'QWEN_API_URL = "http://127.0.0.1:7860"\n'
'CLONE_API_URL = "http://127.0.0.1:7861"\n'
'FASTER_API_URL = "http://127.0.0.1:8000"\n'
- 'AUDIOCPP_API_URL = "http://127.0.0.1:8080"\n',
+ 'AUDIOCPP_API_URL = "http://127.0.0.1:8080"\n'
+ 'QWEN_REMOTE_URL = "http://127.0.0.1:7860"\n'
+ 'CLONE_REMOTE_URL = "http://127.0.0.1:7861"\n'
+ 'FASTER_REMOTE_URL = "http://127.0.0.1:8000"\n'
+ 'AUDIOCPP_REMOTE_URL = "http://127.0.0.1:8080"\n',
encoding="utf-8")
with patch.object(hub.config, "__file__", str(path)):
# Down to Chunk size, Enter -> editor, Ctrl-U + '300',