uv replaces pip where it can: the tools venv and the Poetry bootstrap. The choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A uv failure falls back to pip: it is stricter on metadata and rejects packages pip accepts. Three guards. The target always goes through "--python" rather than being inferred from the active venv: poetry.toml declares a "./.venv" uv would also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And "uv pip sync" is never used: it would delete pip itself and everything Poetry laid down. One bug falls along the way: the idempotence guard aimed at .venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a successful replay reported failure all the same. --- FR --- uv remplace pip là où il le peut : le venv d'outils et l'amorçage de Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les métadonnées et refuse des paquets que pip accepte. Trois gardes. La cible passe toujours par « --python » plutôt que d'être déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip lui-même et tout ce que Poetry a posé. Un défaut tombe au passage : le garde d'idempotence visait .venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo, si bien qu'un rejeu réussi rapportait quand même un échec. Assisted-by: Claude Opus 5
70 lines
2.9 KiB
Bash
Executable file
70 lines
2.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
#
|
|
# Bibliothèque SOURÇABLE : installer des paquets Python dans un venv donné.
|
|
#
|
|
# Seul endroit du dépôt qui décide COMMENT les paquets sont posés. Deux
|
|
# fournisseurs, même contrat de sortie :
|
|
# pip historique, toujours présent dans un venv.
|
|
# uv nettement plus rapide sur la résolution, le téléchargement et la
|
|
# pose ; il met aussi en cache les roues qu'il CONSTRUIT, ce qui
|
|
# compte là où rien n'a de roue publiée.
|
|
#
|
|
# EL_PIP_PROVIDER choisit : auto (défaut), uv, ou pip.
|
|
#
|
|
# CE QUE ÇA NE FAIT PAS — et il faut le savoir avant d'en attendre trop :
|
|
# « poetry install --no-root » n'est PAS concerné. uv ne lit pas poetry.lock
|
|
# (astral-sh/uv#1804, fermé « not planned ») et Poetry 2.1.3 n'a plus la
|
|
# commande « export ». Or c'est cette étape qui domine : 354 paquets contre
|
|
# 153 pour le venv d'outils. Le gain porte donc sur le venv d'outils et
|
|
# l'amorçage de Poetry, pas sur le gros morceau.
|
|
#
|
|
# Et sur s390x il est quasi nul : une trentaine de paquets binaires n'ont
|
|
# aucune roue (numpy, pandas, pillow, lxml, pymupdf…) et se COMPILENT. uv
|
|
# n'enlève pas une seconde de gcc ; il parallélise seulement entre paquets.
|
|
|
|
# uv ne supporte pas officiellement Python 3.7, encore utilisé par Odoo 12
|
|
# et 13. En dessous de ce seuil on reste sur pip, sans discuter.
|
|
EL_UV_MIN_PY_MINOR=8
|
|
|
|
el_uv_usable() {
|
|
# $1 = interpréteur du venv visé.
|
|
local py="$1" minor
|
|
command -v uv > /dev/null 2>&1 || return 1
|
|
[ -x "${py}" ] || return 1
|
|
minor="$("${py}" -c 'import sys;print(sys.version_info[1])' 2> /dev/null)"
|
|
[ -n "${minor}" ] || return 1
|
|
[ "${minor}" -ge "${EL_UV_MIN_PY_MINOR}" ] 2> /dev/null || return 1
|
|
}
|
|
|
|
# API publique : installe dans le venv `$1`, avec les arguments qui suivent.
|
|
#
|
|
# La CIBLE est toujours explicite, jamais déduite de l'environnement. uv
|
|
# cherche sinon un « .venv » dans le répertoire courant ou un parent, et
|
|
# poetry.toml en déclare justement un — le dépôt porte déjà la trace de cette
|
|
# confusion, des dépendances du pyproject Odoo s'étant retrouvées dans
|
|
# .venv.erplibre. « --python » ferme la question.
|
|
#
|
|
# « uv pip sync » n'est jamais utilisé : il SUPPRIME ce qui n'est pas dans le
|
|
# fichier d'entrée, donc pip lui-même et tout ce que Poetry a posé.
|
|
el_pip_install() {
|
|
local venv="$1"
|
|
shift
|
|
local py="${venv}/bin/python"
|
|
local provider="${EL_PIP_PROVIDER:-auto}"
|
|
|
|
if [ "${provider}" != "pip" ] && el_uv_usable "${py}"; then
|
|
echo " installation par uv ($(uv --version 2>&1 | head -1))"
|
|
if uv pip install --python "${py}" "$@"; then
|
|
return 0
|
|
fi
|
|
if [ "${provider}" = "uv" ]; then
|
|
return 1
|
|
fi
|
|
# uv est plus strict que pip sur les métadonnées : il refuse des paquets
|
|
# que pip accepte. Le repli n'est donc pas théorique.
|
|
echo " uv a echoue : reprise avec pip." >&2
|
|
fi
|
|
"${py}" -m pip install "$@"
|
|
}
|