[FIX] migration: the module-upgrade step no longer waits forever

Six « press to continue » prompts on the module-code migration were bare
input() calls. Auto-run never reached them, so it stopped there and said
nothing — the question had been asked, after all. They now go through the
timed reader, where Enter and the countdown mean the same thing.

They were English too, on a path the rest of which speaks the system
language.

The guard that forbids a bare input() only looked at a handful of
methods, and internal_module_upgrade was not among them — which is
exactly how these six survived the first sweep. It is now covered, and
the module menu's own prompts are documented as deliberately blocking:
they ask for a module name, a path, a version, and « » after five
seconds would be a wrong answer, not a convenience.

--- FR ---

[FIX] migration : l'étape de migration de code n'attend plus indéfiniment

Six invites « appuyez pour continuer » de la migration de code étaient des
input() nus. L'auto-exécution ne les atteignait pas : elle s'arrêtait là
sans rien dire — la question avait bien été posée. Elles passent
désormais par le lecteur temporisé, où Entrée et le compte à rebours font
la même chose.

Elles étaient aussi en anglais, sur un chemin dont tout le reste parle la
langue du système.

Le garde-fou qui interdit les input() nus ne regardait qu'une poignée de
méthodes, et internal_module_upgrade n'en faisait pas partie — c'est
ainsi que ces six-là avaient survécu. Il la couvre maintenant, et les
invites du menu de modules sont documentées comme bloquantes à dessein :
elles demandent un nom, un chemin, une version.

Assisted-by: Claude Opus 5
This commit is contained in:
Mathieu Benoit 2026-08-18 02:36:44 -04:00
parent 7296a03179
commit 1c7664409e
3 changed files with 73 additions and 9 deletions

View file

@ -5482,6 +5482,22 @@ TRANSLATIONS = {
"fr": "Trop de tours sur cette invite : on passe.",
"en": "Too many turns on this prompt: moving on.",
},
"Please validate git commit on repos, press to": {
"fr": "Veuillez valider les commits sur les dépôts, appuyez pour",
"en": "Please validate git commit on repos, press to",
},
"Check the migrated code, press to continue": {
"fr": "Vérifiez le code migré, appuyez pour continuer",
"en": "Check the migrated code, press to continue",
},
"Please validate the repo is ready to run": {
"fr": "Veuillez valider que le dépôt est prêt pour",
"en": "Please validate the repo is ready to run",
},
"press to continue": {
"fr": "appuyez pour continuer",
"en": "press to continue",
},
"Clean the database before testing the pages?": {
"fr": "Nettoyer la base avant de tester les pages ?",
"en": "Clean the database before testing the pages?",

View file

@ -1062,8 +1062,9 @@ class TodoUpgrade:
cmd = f"./script/code/git_commit_migration_addons_path.py --path {commit_path} --odoo_version {next_version}.0"
self.todo_upgrade_execute(cmd)
print(set_path_migrate_addons)
status = input(
f"💬 Please validate git commit on repos, press to continue : "
status = self.ask(
f"💬 {t('Please validate git commit on repos, press to')}"
f" {t('continue')} : "
).strip()
def internal_module_upgrade(
@ -1111,7 +1112,9 @@ class TodoUpgrade:
print("List of path with migrate code :")
print(lst_path_git_clone_migrate)
print("ℹ To show repo status :\nmake repo_show_status")
input("💬 Check migration code, press to continue : ")
self.ask(
f"💬 {t('Check the migrated code, press to continue')} : "
)
# source_module_path = dct_module_result.get(
# "source_module_path"
@ -1147,8 +1150,9 @@ class TodoUpgrade:
if next_version in [18]:
# TODO need odoo 18, validate python version without switch
status = input(
f"💬 Please validate repo is ready to run upgrade views_migration_18, press to continue : "
status = self.ask(
f"💬 {t('Please validate the repo is ready to run')}"
f" views_migration_18, {t('press to continue')} : "
).strip()
# Apply modification with views_migration_18
has_cmd = False
@ -1171,11 +1175,15 @@ class TodoUpgrade:
print("List of module with migration 18 :")
print(lst_module_to_migrate_all)
print("ℹ To show repo status :\nmake repo_show_status")
input("💬 Check migration 18 code, press to continue : ")
self.ask(
f"💬 {t('Check the migrated code, press to continue')}"
" (18) : "
)
if next_version == 17:
status = input(
f"💬 Please validate repo is ready to run upgrade views_migration_17, press to continue : "
status = self.ask(
f"💬 {t('Please validate the repo is ready to run')}"
f" views_migration_17, {t('press to continue')} : "
).strip()
# Apply modification with views_migration_17
has_cmd = False
@ -1202,7 +1210,10 @@ class TodoUpgrade:
print("List of module with migration 17 :")
print(lst_module_to_migrate_all)
print("ℹ To show repo status :\nmake repo_show_status")
input("💬 Check migration 17 code, press to continue : ")
self.ask(
f"💬 {t('Check the migrated code, press to continue')}"
" (17) : "
)
def execute_odoo_upgrade(self):
# TODO update dev environment for git project

View file

@ -174,6 +174,9 @@ class TestNoPromptOfTheMigrationCanHang(unittest.TestCase):
METHODES = (
"execute_odoo_upgrade",
# Appelée DEPUIS execute_odoo_upgrade : c'est par elle que le
# « validez que le dépôt est prêt » arrivait, et il bloquait.
"internal_module_upgrade",
"prompt_cow_prediction",
"prompt_uninstall_theme",
"prompt_reset_stale_cow_views",
@ -210,6 +213,40 @@ class TestNoPromptOfTheMigrationCanHang(unittest.TestCase):
self.assertEqual(coupables, {}, "invites hors du mode auto")
class TestWhereBlockingIsStillRight(unittest.TestCase):
"""Tout ne doit pas prendre un défaut : certaines questions n'en ont pas.
`execute_module_upgrade` demande un nom de module, un chemin, une
version de départ. Rendre « » au bout de cinq secondes n'y serait pas
une commodité mais une réponse fausse. Ces invites restent bloquantes,
et c'est correct — à une condition, vérifiée ici : qu'aucune migration
automatique ne passe par elles.
"""
def test_the_module_menu_is_not_on_the_automatic_path(self):
import inspect
source = inspect.getsource(TodoUpgrade.execute_odoo_upgrade)
self.assertNotIn("execute_module_upgrade", source)
def test_but_the_step_it_shares_IS(self):
# `internal_module_upgrade` est appelée des DEUX côtés : par le
# menu et par la migration. C'est ce qui la rend obligatoire.
import inspect
source = inspect.getsource(TodoUpgrade.execute_odoo_upgrade)
self.assertIn("internal_module_upgrade", source)
def test_its_prompts_ask_for_values_with_no_default(self):
# Si l'un d'eux devenait un oui/non, il faudrait le faire passer
# par le lecteur temporisé comme les autres.
import inspect
source = inspect.getsource(TodoUpgrade.execute_module_upgrade)
for question in ("Module name", "Path", "From odoo version"):
self.assertIn(question, source)
class TestWhatEnterDoesIsWritten(unittest.TestCase):
"""La question doit dire la vérité à qui appuie sur Entrée."""