[ADD] cache qemu : messages du binaire en anglais ou en français
Le binaire ne parlait que français alors que le menu suit EL_LANG : un
opérateur anglophone lisait un statut qu'il ne comprenait pas. Chaque message
humain passe par T(), dont la clé EST le texte français, et un catalogue
anglais le traduit ; la langue vient de --lang, puis d'EL_LANG, le français
restant le défaut. Le menu demande le français pour ce qu'il RELIT, ses
motifs ne connaissant que cette langue. Un test refuse un message sans
traduction, une traduction orpheline et un verbe de format qui diverge.
--- EN ---
The binary spoke French only while the menu follows EL_LANG: an English
reader got a status he could not read. Every human message goes through T(),
whose key IS the French text, and an English catalogue translates it; the
language comes from --lang, then EL_LANG, French remaining the default. The
menu asks for French for what it READS BACK, its patterns knowing that
language alone. A test refuses a message without translation, an orphan
translation, and a format verb that drifts.
Assisted-by: Claude Opus 5
2026-09-16 02:59:01 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
"""La langue du binaire du cache, vue du menu.
|
|
|
|
|
|
|
|
|
|
Le binaire traduit ses messages humains selon --lang. Le menu doit donc dire
|
|
|
|
|
laquelle il veut, et la bonne : la langue de todo.py pour ce qu'il AFFICHE,
|
|
|
|
|
le français pour ce qu'il LIT — il ne connaît les libellés que dans cette
|
|
|
|
|
langue. Et ce qu'il lit dans un journal écrit par le service, dont la langue
|
|
|
|
|
est fixée à l'installation, il doit le reconnaître dans les deux.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
import unittest
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from unittest import mock
|
|
|
|
|
|
|
|
|
|
RACINE = Path(__file__).resolve().parent.parent
|
|
|
|
|
sys.path.insert(0, str(RACINE))
|
|
|
|
|
|
|
|
|
|
from script.todo import qemu_cache_menu as menu # noqa: E402
|
|
|
|
|
|
|
|
|
|
CATALOGUE = RACINE / "script" / "qemu_cache" / "catalogue_en.go"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestLOptionDeLangue(unittest.TestCase):
|
|
|
|
|
def test_une_sortie_lue_est_demandee_en_francais(self):
|
|
|
|
|
with mock.patch.object(menu, "get_lang", return_value="en"):
|
|
|
|
|
self.assertEqual(menu.option_langue(lue=True), "--lang fr")
|
|
|
|
|
|
|
|
|
|
def test_une_sortie_affichee_suit_la_langue_de_todo(self):
|
|
|
|
|
for langue in ("fr", "en"):
|
|
|
|
|
with mock.patch.object(menu, "get_lang", return_value=langue):
|
|
|
|
|
self.assertEqual(menu.option_langue(), f"--lang {langue}")
|
|
|
|
|
|
|
|
|
|
def test_le_pre_remplissage_parle_la_langue_de_todo(self):
|
|
|
|
|
"""Lancé par sudo -u : EL_LANG n'y arriverait pas, l'option si."""
|
|
|
|
|
with mock.patch.object(menu, "get_lang", return_value="en"):
|
|
|
|
|
cmd = menu.miroir_prefetch_cmd("/tmp/liste", [])
|
|
|
|
|
self.assertIn("--lang en", cmd)
|
|
|
|
|
|
|
|
|
|
def test_le_retrait_d_exception_garde_nft_en_bout_de_tube(self):
|
|
|
|
|
"""Le message humain va à l'erreur standard ; la sortie standard
|
|
|
|
|
porte les règles que nft lit, et ne se traduit jamais."""
|
|
|
|
|
with mock.patch.object(menu, "get_lang", return_value="en"):
|
|
|
|
|
cmd = menu.bypass_retrait_cmd("52:54:00:00:00:04")
|
|
|
|
|
self.assertIn("--lang en", cmd)
|
|
|
|
|
self.assertTrue(cmd.endswith("| sudo nft -f -"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestCeQueLeMenuLit(unittest.TestCase):
|
|
|
|
|
def test_l_occupation_du_miroir_est_lue_en_francais(self):
|
|
|
|
|
vu = {}
|
|
|
|
|
|
|
|
|
|
def faux_lire(cmd, delai=15):
|
|
|
|
|
vu["cmd"] = cmd
|
|
|
|
|
return "objets : 3\ndépôts git : 12 en miroir, 4.2 Gio\n"
|
|
|
|
|
|
[REF] format : passer l'outillage et les tests sous ruff
Le formateur de ce dépôt est ruff depuis qu'il remplace black, qui ne connaît
aucune cible au-delà de py313 ; ce passage applique sa norme à l'arbre entier,
d'un coup, pour qu'aucun commit de fond n'ait à porter du style. L'écart tient
presque entièrement aux chaînes coupées à la main que ruff recolle quand elles
tiennent sur une ligne, et aux « with » multiples qu'il regroupe : aucune
valeur ne change, et les clés de traduction non plus.
Vérifié : la suite unitaire reste verte après le passage, et le contrôle de
syntaxe ne signale rien.
--- EN ---
This repository's formatter is ruff since it replaced black, which knows no
target beyond py313; this pass applies its standard to the whole tree at once,
so that no substantive commit has to carry style. The difference is almost
entirely the hand-split strings ruff joins back when they fit on one line, and
the multiple "with" it merges: no value changes, nor do the translation keys.
Checked: the unit suite stays green after the pass, and the syntax check
reports nothing.
Assisted-by: Claude Opus 5
2026-09-24 13:30:31 -04:00
|
|
|
with (
|
|
|
|
|
mock.patch.object(
|
|
|
|
|
menu.QemuCacheMenuMixin, "_cache_lire", staticmethod(faux_lire)
|
|
|
|
|
),
|
|
|
|
|
mock.patch.object(menu, "get_lang", return_value="en"),
|
|
|
|
|
):
|
[ADD] cache qemu : messages du binaire en anglais ou en français
Le binaire ne parlait que français alors que le menu suit EL_LANG : un
opérateur anglophone lisait un statut qu'il ne comprenait pas. Chaque message
humain passe par T(), dont la clé EST le texte français, et un catalogue
anglais le traduit ; la langue vient de --lang, puis d'EL_LANG, le français
restant le défaut. Le menu demande le français pour ce qu'il RELIT, ses
motifs ne connaissant que cette langue. Un test refuse un message sans
traduction, une traduction orpheline et un verbe de format qui diverge.
--- EN ---
The binary spoke French only while the menu follows EL_LANG: an English
reader got a status he could not read. Every human message goes through T(),
whose key IS the French text, and an English catalogue translates it; the
language comes from --lang, then EL_LANG, French remaining the default. The
menu asks for French for what it READS BACK, its patterns knowing that
language alone. A test refuses a message without translation, an orphan
translation, and a format verb that drifts.
Assisted-by: Claude Opus 5
2026-09-16 02:59:01 -04:00
|
|
|
rendu = menu.QemuCacheMenuMixin._cache_miroir_occupation()
|
|
|
|
|
self.assertIn("--lang fr", vu["cmd"])
|
|
|
|
|
self.assertEqual(rendu, ("12", "4.2 Gio"))
|
|
|
|
|
|
|
|
|
|
def test_le_journal_est_lu_dans_les_deux_langues(self):
|
|
|
|
|
"""La langue du service est celle de son installation, pas celle de
|
|
|
|
|
qui ouvre le menu : un refus appris doit être reconnu dans les deux."""
|
|
|
|
|
journal = (
|
|
|
|
|
"tunnel opaque retenu pour npm.example (3 échec(s)) : EOF\n"
|
|
|
|
|
"opaque tunnel kept for pypi.example (3 failure(s)): EOF\n"
|
|
|
|
|
)
|
|
|
|
|
commandes = []
|
|
|
|
|
|
|
|
|
|
def faux_lire(cmd, delai=15):
|
|
|
|
|
commandes.append(cmd)
|
|
|
|
|
return journal
|
|
|
|
|
|
|
|
|
|
with mock.patch.object(
|
|
|
|
|
menu.QemuCacheMenuMixin, "_cache_lire", staticmethod(faux_lire)
|
|
|
|
|
):
|
|
|
|
|
hotes = menu.QemuCacheMenuMixin._cache_refus_appris()
|
|
|
|
|
self.assertEqual(hotes, ["npm.example", "pypi.example"])
|
|
|
|
|
for motif in menu.REFUS_APPRIS:
|
|
|
|
|
self.assertIn(motif, commandes[0])
|
|
|
|
|
|
|
|
|
|
def test_le_catalogue_porte_ce_que_le_menu_lit(self):
|
|
|
|
|
"""Une traduction qui s'écarte de ces libellés rendrait le menu
|
|
|
|
|
aveugle sans qu'aucun test du binaire ne le voie."""
|
|
|
|
|
texte = CATALOGUE.read_text(encoding="utf-8")
|
|
|
|
|
self.assertIn('"opaque tunnel kept for %s (', texte)
|
|
|
|
|
for libelle in ("authority : %s", "fingerprint : %s"):
|
|
|
|
|
self.assertIn(f'"{libelle}', texte)
|
|
|
|
|
for prefixe in menu.LIBELLES_TUS:
|
|
|
|
|
self.assertTrue(
|
|
|
|
|
prefixe in texte or prefixe in ("autorité", "empreinte"),
|
|
|
|
|
prefixe,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|