From a743c4462a978fbda111c236d63e385da95ffcd6 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Mon, 3 Aug 2026 08:03:58 +0000 Subject: [PATCH] =?UTF-8?q?[FIX]=20requirement:=20borner=20Textual,=20et?= =?UTF-8?q?=20d=C3=A9clarer=20lxml=20plut=C3=B4t=20que=20l'h=C3=A9riter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Textual était déclaré sans version. Les quatre écrans TUI du dépôt sont écrits pour la 8, et la bibliothèque casse son API entre majeures : un « pip install -U » les casse tous sans prévenir. Borner le fichier de requirements ne suffisait pas. install_command() faisait « pip install textual », sans borne : « make install » aurait pris la 8, et l'installation proposée à l'écran la majeure suivante. Deux chemins pour la même dépendance, qui ne disent pas la même chose. La borne vit donc dans une seule constante, TEXTUAL_SPEC, que install_command() utilise, et que le fichier de requirements recopie avec un commentaire qui pointe dessus. La borne ne s'applique qu'à l'installation : ensure() vérifie « est-ce importable », pas « à quelle version ». Un Textual 9 déjà présent passe, et c'est volontaire — refuser de démarrer sur une version qui marche peut-être serait pire que le problème. lxml devient une dépendance déclarée. Il n'arrivait que par pykeepass, openupgradelib et odoo-module-migrator ; le jour où l'un d'eux s'en passe, il disparaît d'un venv sans que rien ne le réclame. Sans borne : cyclonedx-python-lib demande déjà « lxml >=4,<7 », en ajouter une seconde n'apporterait qu'un conflit possible. Vérifié : install_command() porte la borne, l'insertion de « --user » hors venv reste au bon rang, et le Textual installé (8.2.8) la satisfait. Co-Authored-By: Claude Opus 5 (1M context) --- requirement/erplibre_require-ments.txt | 8 +++++++- script/todo/textual_setup.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/requirement/erplibre_require-ments.txt b/requirement/erplibre_require-ments.txt index a05b81b..9016738 100644 --- a/requirement/erplibre_require-ments.txt +++ b/requirement/erplibre_require-ments.txt @@ -24,7 +24,13 @@ openai humanize requests urwid -textual +# Borne recopiée de script/todo/textual_setup.py (TEXTUAL_SPEC) : les écrans TUI +# sont écrits pour Textual 8, qui casse son API entre majeures. Modifier les deux. +textual>=8,<9 +# Dépendance directe : les outils d'analyse comparent des arbres XML avec lxml. +# Il n'arrivait que par pykeepass / openupgradelib / odoo-module-migrator, donc +# un jour où l'un d'eux s'en passe, il disparaît sans que rien ne le réclame. +lxml python-dotenv python-dateutil unidecode diff --git a/script/todo/textual_setup.py b/script/todo/textual_setup.py index 070c0c0..eae64b1 100644 --- a/script/todo/textual_setup.py +++ b/script/todo/textual_setup.py @@ -29,6 +29,15 @@ except Exception: # pragma: no cover - repli si i18n indisponible return key +# Borne de version, à UN seul endroit. Les écrans TUI du dépôt sont écrits pour +# Textual 8 ; la bibliothèque casse son API entre majeures. « pip install +# textual » sans borne installerait la majeure suivante et casserait les écrans +# sans prévenir, alors même que requirement/erplibre_require-ments.txt la borne. +# Les deux chemins d'installation doivent dire la même chose : ce littéral est +# recopié dans le fichier de requirements, avec un commentaire qui pointe ici. +TEXTUAL_SPEC = "textual>=8,<9" + + def available() -> bool: """Textual est-il importable maintenant ?""" return importlib.util.find_spec("textual") is not None @@ -47,7 +56,7 @@ def install_command(): verrait jamais. Hors venv, « --user » contourne le refus des distributions dont l'environnement est « externally managed » (PEP 668). """ - cmd = [sys.executable, "-m", "pip", "install", "textual"] + cmd = [sys.executable, "-m", "pip", "install", TEXTUAL_SPEC] if not in_venv(): cmd.insert(4, "--user") return cmd