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