mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-09 12:17:13 +00:00
server() preferred the deployed service and fell back to a throwaway container when it did not answer. That container ran the upstream image directly, with LT_UPDATE_MODELS on and neither the package-cache CA nor the argos-net.com hijack, so it refetched gigabytes from upstream on every run while the deployed service already carries those models in its image, installed through the cache at build time. The fallback is gone. It was reached by accident rather than by failure. deploy() ended in await_service(), which polled for 300 seconds; the first start of the service installs its models and takes far longer, so the wait expired, deploy() reported nothing running, and the caller spawned the throwaway beside the service it had just deployed successfully. await_service and SERVICE_TIMEOUT_SECONDS are removed, leaving the single readiness wait the client already performs with the budget those models need. Step 0 of the deploy also stopped forcing a recreate. It rebuilt a healthy lane on every invocation and took whatever model install was in flight with it; compose recreates on a changed configuration by itself. The wait no longer looks like a hang: it reports how many of the wanted languages the server offers, which ones are still missing, how long it has waited against its budget, and what the lane has pulled. i18n-tune waits the same way and gets the same report. service_url() and lane_container() replace the two places that each rebuilt one of those strings, and deploy() reads the environment once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import contextlib
|
|
import importlib
|
|
import unittest
|
|
import unittest.mock as mock
|
|
from pathlib import Path
|
|
from tempfile import TemporaryDirectory
|
|
|
|
from utils.i18n.catalog import catalog_path, new_catalog, write_catalog
|
|
from utils.i18n.languages import LANGUAGES_FILE
|
|
from utils.i18n.libretranslate import Outcome
|
|
|
|
cli = importlib.import_module("cli.build.i18n.__main__")
|
|
|
|
LANGUAGES = """\
|
|
en: {name: English, native: English, direction: ltr, libretranslate: true}
|
|
de: {name: German, native: Deutsch, direction: ltr, libretranslate: true}
|
|
fr: {name: French, native: Français, direction: ltr, libretranslate: true}
|
|
"""
|
|
|
|
|
|
def _catalog(root: Path, code: str, translation: str) -> None:
|
|
catalog = new_catalog("core", code)
|
|
catalog.add("Hello", translation, context="menu:x:title")
|
|
path = catalog_path(root, code, "core")
|
|
path.parent.mkdir(parents=True)
|
|
write_catalog(path, catalog)
|
|
|
|
|
|
class TestTranslate(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self._tmp = TemporaryDirectory()
|
|
self.addCleanup(self._tmp.cleanup)
|
|
self.root = Path(self._tmp.name)
|
|
(self.root / LANGUAGES_FILE).parent.mkdir()
|
|
(self.root / LANGUAGES_FILE).write_text(LANGUAGES, encoding="utf-8")
|
|
_catalog(self.root, "de", "Hallo")
|
|
|
|
def _run(self) -> tuple[int, mock.Mock, mock.Mock]:
|
|
started = mock.Mock(return_value=contextlib.nullcontext("http://lt"))
|
|
client = mock.Mock()
|
|
client.return_value.translate.side_effect = lambda texts, code: Outcome(
|
|
["Bonjour"] * len(texts), 0, 0, ""
|
|
)
|
|
with (
|
|
mock.patch.object(cli, "PROJECT_ROOT", self.root),
|
|
mock.patch.object(cli, "server", started),
|
|
mock.patch.object(cli, "LibreTranslate", client),
|
|
):
|
|
return cli.translate(["core"], []), started, client
|
|
|
|
def test_only_languages_with_pending_entries_are_awaited(self) -> None:
|
|
_catalog(self.root, "fr", "")
|
|
|
|
status, _started, client = self._run()
|
|
|
|
self.assertEqual(status, 0)
|
|
self.assertEqual(client.return_value.wait.call_args.args[0], ["fr"])
|
|
|
|
def test_nothing_pending_starts_no_container(self) -> None:
|
|
_catalog(self.root, "fr", "Bonjour")
|
|
|
|
status, started, _client = self._run()
|
|
|
|
self.assertEqual(status, 0)
|
|
started.assert_not_called()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|