Commit graph

2 commits

Author SHA1 Message Date
a743c4462a [FIX] requirement: borner Textual, et déclarer lxml plutôt que l'hériter
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) <noreply@anthropic.com>
2026-08-03 08:03:58 +00:00
5d6a262489 [IMP] todo: offer to install textual instead of just naming it
« Installez textual pour le TUI (pip) » left the user to work out which pip,
which interpreter, which package — and it was printed from eight different
places. Every TUI screen now asks:

  ⚠  Textual est nécessaire pour cet écran.
  L'installer maintenant ? (O/n, défaut : oui)

The command targets sys.executable, the interpreter that will have to import
it — installing a distribution package would land somewhere the venv never
looks. Outside a venv it adds --user, which is also what gets past the refusal
of distributions whose environment is externally managed (PEP 668).

Two details that decide whether this works at all:

  · importlib.invalidate_caches() after installing. A failed import is
    remembered, so without it textual stays « missing » for the rest of the
    session despite having just been installed.
  · a pip that exits non-zero never reports success. The check is « is it
    importable NOW », not « did pip return 0 », and the failure suggests the
    distribution package by name.

It lives in its own module rather than as a TODO method: todo_upgrade needs it
too and is imported BY todo, so putting it there would close a cycle.

One call site is deliberately NOT converted. The statistics screen only reads
files; it never touches Textual, and its old message claimed otherwise. An
import failure there is a real module problem and now says so.

Verified: already-present asks nothing and runs nothing; refusal installs
nothing; pip failing returns False and points at python3-textual; pip
succeeding returns True; prompt=False reports without asking. Then each of the
four TUI entries — telemetry, deploy form, deploy progress, migration resume —
offers and falls back cleanly on refusal, while the statistics screen stays
silent.

Also caught by those tests: « import importlib » alone does not expose
importlib.util, so availability could not be checked at all.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 02:42:52 -04:00