[ADD] install: mise as Python provider, pyenv as fallback
mise lays down a precompiled CPython where pyenv builds one: seconds against one to three minutes, with no -dev package at all. The choice lives in EL_PYTHON_PROVIDER -- auto, mise or pyenv -- and in a single file, lib_python_provider.sh. The rest of the repository only knows venv paths and needs to know none of this. In auto mode an ALREADY installed interpreter wins, whichever provider put it there. mise is never installed on its own, "curl | sh" commits too much for a script to decide -- make install_mise carries that decision. MISE_PYTHON_COMPILE=false forbids it from quietly compiling: without that guard it would fall back to pyenv's own engine, giving us the slowness without the tooling. That is also what stopped gcc from collapsing while building CPython on a low-memory s390x guest, for nothing. One real bug falls along the way: a failed venv did not stop the install, which then went on and failed further down, far from the cause. --- FR --- mise pose un CPython précompilé là où pyenv en compile un : des secondes contre une à trois minutes, et aucun paquet -dev. Le choix vit dans EL_PYTHON_PROVIDER — auto, mise ou pyenv — et dans un seul fichier, lib_python_provider.sh. Le reste du dépôt ne connaît que des chemins de venv et n'a rien à savoir de tout cela. En mode auto, un interpréteur DÉJÀ posé l'emporte, quel qu'en soit le fournisseur. mise n'est jamais installé de lui-même, « curl | sh » engage trop pour qu'un script en décide — make install_mise porte cette décision. MISE_PYTHON_COMPILE=false lui interdit de compiler en silence : sans ce garde, il retomberait sur le moteur de pyenv, et nous aurions sa lenteur sans son outillage. C'est aussi ce qui a évité que gcc s'écroule en bâtissant CPython sur une VM s390x à faible mémoire, inutilement. Un vrai défaut tombe au passage : un venv raté n'arrêtait pas l'installation, qui continuait et échouait plus loin, loin de la cause. Assisted-by: Claude Opus 5
This commit is contained in:
parent
a579cc9cf3
commit
70d9ad456c
12 changed files with 303 additions and 55 deletions
|
|
@ -8,8 +8,19 @@
|
||||||
|
|
||||||
Plateformes supportées : Ubuntu 24.04 / 25.10 / 26.04, Linux Mint 22.3,
|
Plateformes supportées : Ubuntu 24.04 / 25.10 / 26.04, Linux Mint 22.3,
|
||||||
Debian 12, AlmaLinux 9+, Rocky Linux 9+, openSUSE Tumbleweed, Arch Linux,
|
Debian 12, AlmaLinux 9+, Rocky Linux 9+, openSUSE Tumbleweed, Arch Linux,
|
||||||
macOS (pyenv),
|
macOS (mise ou pyenv),
|
||||||
Windows (WSL/Docker).
|
Windows (WSL/Docker).
|
||||||
|
|
||||||
Ubuntu 20.04 et 22.04 sont abandonnées : pikepdf exige qpdf >= 12.2, compilé
|
Ubuntu 20.04 et 22.04 sont abandonnées : pikepdf exige qpdf >= 12.2, compilé
|
||||||
en C++20, quand focal livre GCC 9.
|
en C++20, quand focal livre GCC 9.
|
||||||
|
|
||||||
|
## Interpréteur Python
|
||||||
|
|
||||||
|
`EL_PYTHON_PROVIDER` (dans `env_var.sh`) vaut `auto`, `mise` ou `pyenv`.
|
||||||
|
`auto` reprend un interpréteur DÉJÀ posé, quel que soit le fournisseur ; sinon
|
||||||
|
il préfère mise, qui pose un CPython précompilé, et retombe sur pyenv, qui le
|
||||||
|
compile.
|
||||||
|
|
||||||
|
Un seul fichier décide : `script/install/lib_python_provider.sh`. mise n'est
|
||||||
|
jamais installé automatiquement — `make install_mise` porte cette décision.
|
||||||
|
Pas de binaire mise pour s390x à ce jour : cette architecture reste sur pyenv.
|
||||||
|
|
|
||||||
22
Makefile
22
Makefile
|
|
@ -97,6 +97,28 @@ version:
|
||||||
pyenv_update:
|
pyenv_update:
|
||||||
~/.pyenv/bin/pyenv update
|
~/.pyenv/bin/pyenv update
|
||||||
|
|
||||||
|
# mise pose un CPython PRECOMPILE la ou pyenv le compile : quelques secondes
|
||||||
|
# contre une a trois minutes, et aucun paquet -dev requis. Volontairement
|
||||||
|
# EXPLICITE : « curl | sh » engage, et ce n'est pas a un script d'installation
|
||||||
|
# de le decider a la place de l'utilisateur. Une fois mise present,
|
||||||
|
# EL_PYTHON_PROVIDER=auto s'en sert tout seul.
|
||||||
|
#
|
||||||
|
# Pas de binaire s390x publie a ce jour : sur cette architecture, la cible
|
||||||
|
# le dit et n'installe rien.
|
||||||
|
.PHONY: install_mise
|
||||||
|
install_mise:
|
||||||
|
@if command -v mise >/dev/null 2>&1; then \
|
||||||
|
echo "mise deja present : $$(mise --version)"; \
|
||||||
|
elif command -v pacman >/dev/null 2>&1; then \
|
||||||
|
sudo pacman -S --needed --noconfirm mise; \
|
||||||
|
elif [ "$$(uname -m)" = "s390x" ]; then \
|
||||||
|
echo "mise ne publie pas de binaire s390x : on reste sur pyenv."; \
|
||||||
|
else \
|
||||||
|
echo "Installation de mise depuis https://mise.run"; \
|
||||||
|
curl -fsSL https://mise.run | sh; \
|
||||||
|
echo "Ajoutez ~/.local/bin a votre PATH, puis relancez l installation."; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: db_create_db_test
|
.PHONY: db_create_db_test
|
||||||
db_create_db_test:
|
db_create_db_test:
|
||||||
./script/make.sh db_drop_db_test
|
./script/make.sh db_drop_db_test
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ Changez de version avec `make switch_odoo_18`, `make switch_odoo_16`, etc.
|
||||||
# Supported platforms
|
# Supported platforms
|
||||||
|
|
||||||
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
||||||
- **macOS** : via pyenv
|
- **macOS** : via mise ou pyenv
|
||||||
- **Windows** : via WSL or Docker
|
- **Windows** : via WSL or Docker
|
||||||
- **Mainframe** : 390x architecture
|
- **Mainframe** : 390x architecture
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ Changez de version avec `make switch_odoo_18`, `make switch_odoo_16`, etc.
|
||||||
# Plateformes supportées
|
# Plateformes supportées
|
||||||
|
|
||||||
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
||||||
- **macOS** : via pyenv
|
- **macOS** : via mise ou pyenv
|
||||||
- **Windows** : via WSL ou Docker
|
- **Windows** : via WSL ou Docker
|
||||||
- **Mainframe** : architecture 390x
|
- **Mainframe** : architecture 390x
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ Changez de version avec `make switch_odoo_18`, `make switch_odoo_16`, etc.
|
||||||
# Plateformes supportées
|
# Plateformes supportées
|
||||||
|
|
||||||
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
||||||
- **macOS** : via pyenv
|
- **macOS** : via mise ou pyenv
|
||||||
- **Windows** : via WSL ou Docker
|
- **Windows** : via WSL ou Docker
|
||||||
- **Mainframe** : architecture 390x
|
- **Mainframe** : architecture 390x
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ Switch between versions with `make switch_odoo_18`, `make switch_odoo_16`, etc.
|
||||||
# Supported platforms
|
# Supported platforms
|
||||||
|
|
||||||
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
- **Linux** : Ubuntu 24.04, 25.10, 26.04; Debian 12; AlmaLinux 9+; Rocky Linux 9+; Arch Linux
|
||||||
- **macOS** : via pyenv
|
- **macOS** : via mise ou pyenv
|
||||||
- **Windows** : via WSL or Docker
|
- **Windows** : via WSL or Docker
|
||||||
- **Mainframe** : 390x architecture
|
- **Mainframe** : 390x architecture
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@ EL_POETRY_VERSION=$(cat ".poetry-version" | xargs)
|
||||||
EL_PYTHON_ODOO_VERSION=$(cat ".python-odoo-version" | xargs)
|
EL_PYTHON_ODOO_VERSION=$(cat ".python-odoo-version" | xargs)
|
||||||
EL_PYTHON_ERPLIBRE_VERSION=$(cat "./conf/python-erplibre-version" | xargs)
|
EL_PYTHON_ERPLIBRE_VERSION=$(cat "./conf/python-erplibre-version" | xargs)
|
||||||
EL_ERPLIBRE_VERSION=$(cat ".erplibre-version" | xargs)
|
EL_ERPLIBRE_VERSION=$(cat ".erplibre-version" | xargs)
|
||||||
|
# Fournisseur d'interpreteur Python : auto | mise | pyenv.
|
||||||
|
# « auto » prend ce qui est DEJA pose, sinon mise s'il est present (Python
|
||||||
|
# precompile, quelques secondes), sinon pyenv (compilation). Voir
|
||||||
|
# script/install/lib_python_provider.sh.
|
||||||
|
EL_PYTHON_PROVIDER="${EL_PYTHON_PROVIDER:-auto}"
|
||||||
# The default port where this Odoo instance will run under (provided you use the command -c in the terminal)
|
# The default port where this Odoo instance will run under (provided you use the command -c in the terminal)
|
||||||
# Set to true if you want to install it, false if you don't need it or have it already installed.
|
# Set to true if you want to install it, false if you don't need it or have it already installed.
|
||||||
EL_INSTALL_WKHTMLTOPDF="True"
|
EL_INSTALL_WKHTMLTOPDF="True"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Le code de retour du script de distribution DOIT remonter : il est aujourd'hui
|
||||||
|
# la derniere commande executee, donc propage par accident. « set -e » le rend
|
||||||
|
# explicite, et update_env_version.py:818 s'en sert pour arreter l'installation
|
||||||
|
# au lieu d'enchainer sur un systeme sans compilateur.
|
||||||
|
set -e
|
||||||
|
|
||||||
# « $OSTYPE » ne decrit PAS le systeme : bash le fige au triplet avec lequel il
|
# « $OSTYPE » ne decrit PAS le systeme : bash le fige au triplet avec lequel il
|
||||||
# a ete compile. openSUSE batit bash en « x86_64-suse-linux » et le renseigne
|
# a ete compile. openSUSE batit bash en « x86_64-suse-linux » et le renseigne
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,21 @@ if [[ "${EL_PHASE}" != "poetry" ]]; then
|
||||||
if [[ ! -n "${DOCKER_BUILD}" ]]; then
|
if [[ ! -n "${DOCKER_BUILD}" ]]; then
|
||||||
# Install ERPLibre venv
|
# Install ERPLibre venv
|
||||||
echo -e "Install ${VENV_ERPLIBRE_PATH} with ${EL_PYTHON_ERPLIBRE_VERSION}"
|
echo -e "Install ${VENV_ERPLIBRE_PATH} with ${EL_PYTHON_ERPLIBRE_VERSION}"
|
||||||
./script/install/install_venv.sh "ERPLibre" "${VENV_ERPLIBRE_PATH}" "${EL_PYTHON_ERPLIBRE_VERSION}"
|
# Le code de retour n'était PAS regardé : quand l'interpréteur ne
|
||||||
|
# pouvait pas être obtenu, le script continuait, et tout ce qui suit
|
||||||
|
# échouait à son tour sur un venv inexistant. Le log devenait une
|
||||||
|
# cascade de « No such file or directory » répartie sur trois fichiers,
|
||||||
|
# où la cause réelle — pas de compilateur C — se perdait tout en haut.
|
||||||
|
if ! ./script/install/install_venv.sh "ERPLibre" "${VENV_ERPLIBRE_PATH}" "${EL_PYTHON_ERPLIBRE_VERSION}"; then
|
||||||
|
echo "Echec de creation de ${VENV_ERPLIBRE_PATH}, arret."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
# Install Odoo venv
|
# Install Odoo venv
|
||||||
echo -e "Install ${VENV_ODOO_PATH} with ${EL_PYTHON_ODOO_VERSION}"
|
echo -e "Install ${VENV_ODOO_PATH} with ${EL_PYTHON_ODOO_VERSION}"
|
||||||
./script/install/install_venv.sh "Odoo" "${VENV_ODOO_PATH}" "${EL_PYTHON_ODOO_VERSION}"
|
if ! ./script/install/install_venv.sh "Odoo" "${VENV_ODOO_PATH}" "${EL_PYTHON_ODOO_VERSION}"; then
|
||||||
|
echo "Echec de creation de ${VENV_ODOO_PATH}, arret."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
mkdir .venv
|
mkdir .venv
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,18 @@ if [[ ${retVal} -ne 0 ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Dépendances de build pour pyenv (compilation de CPython) — CRITIQUE.
|
# Dépendances de build pour pyenv (compilation de CPython) — CRITIQUE.
|
||||||
|
# Python de la DISTRIBUTION d'abord : Tumbleweed livre python312 en 3.12.13,
|
||||||
|
# qui satisfait « >=3.12.10,<3.13 ». lib_python_provider.sh le prefere alors a
|
||||||
|
# toute compilation — decisif sur s390x, ou gcc 15.2 s'arrete sur une erreur
|
||||||
|
# interne en batissant Parser/parser.c de CPython 3.12.10.
|
||||||
|
# Le nom suit la version demandee : python312 pour 3.12.x.
|
||||||
|
PY_WANT="$(cat .python-odoo-version 2>/dev/null | xargs)"
|
||||||
|
PY_PKG="python$(echo "${PY_WANT}" | awk -F. '{print $1 $2}')"
|
||||||
|
if [ -n "${PY_WANT}" ]; then
|
||||||
|
echo -e "\n---- Python ${PY_WANT} depuis la distribution (${PY_PKG}) ----"
|
||||||
|
zyp_soft "${PY_PKG}" "${PY_PKG}-devel" "${PY_PKG}-pip"
|
||||||
|
fi
|
||||||
|
|
||||||
echo -e "\n---- Dependances pyenv (compilation Python) ----"
|
echo -e "\n---- Dependances pyenv (compilation Python) ----"
|
||||||
zyp_in \
|
zyp_in \
|
||||||
make gcc zlib-devel libbz2-devel readline-devel sqlite3-devel \
|
make gcc zlib-devel libbz2-devel readline-devel sqlite3-devel \
|
||||||
|
|
|
||||||
|
|
@ -17,52 +17,25 @@ echo "Context: $CONTEXT"
|
||||||
echo "Venv Path: $VENV_PATH"
|
echo "Venv Path: $VENV_PATH"
|
||||||
echo "Python Version: $PYTHON_VERSION"
|
echo "Python Version: $PYTHON_VERSION"
|
||||||
|
|
||||||
PYENV_PATH=~/.pyenv
|
# Le CHOIX du fournisseur (mise ou pyenv) vit dans la bibliothèque : ce script
|
||||||
PYENV_VERSION_PATH=${PYENV_PATH}/versions/${PYTHON_VERSION}
|
# ne connaît qu'un chemin d'interpréteur. C'est ce qui permet d'en ajouter un
|
||||||
PYTHON_EXEC=${PYENV_VERSION_PATH}/bin/python
|
# troisième sans toucher ici.
|
||||||
echo "Python path version home"
|
# shellcheck source=script/install/lib_python_provider.sh
|
||||||
echo ${PYENV_VERSION_PATH}
|
. ./script/install/lib_python_provider.sh
|
||||||
#echo "Python path version local"
|
|
||||||
#echo ${LOCAL_PYTHON_EXEC}
|
|
||||||
|
|
||||||
if [[ ! -d "${PYENV_PATH}" ]]; then
|
PYTHON_EXEC="$(el_python_exec "${PYTHON_VERSION}")"
|
||||||
echo -e "\n---- Installing pyenv in ${PYENV_PATH} ----"
|
if [[ -z "${PYTHON_EXEC}" ]] || [[ ! -x "${PYTHON_EXEC}" ]]; then
|
||||||
# export PYENV_GIT_TAG=v2.3.35
|
echo "Aucun interpreteur Python ${PYTHON_VERSION} n'a pu etre obtenu."
|
||||||
# To change version
|
echo " Fournisseur demande : ${EL_PYTHON_PROVIDER:-auto}"
|
||||||
# rm ~/.pyenv to uninstall it
|
echo " Voir 'make install_mise', ou installez pyenv."
|
||||||
curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
echo "Interpreteur retenu : ${PYTHON_EXEC}"
|
||||||
echo -e "\n---- Export pyenv in ${PYENV_PATH} ----"
|
|
||||||
export PATH="${PYENV_PATH}/bin:$PATH"
|
|
||||||
eval "$(pyenv init -)"
|
|
||||||
eval "$(pyenv virtualenv-init -)"
|
|
||||||
|
|
||||||
if [[ ! -d "${PYENV_VERSION_PATH}" ]]; then
|
|
||||||
echo -e "\n---- Installing python ${PYTHON_VERSION} with pyenv in ${PYENV_VERSION_PATH} ----"
|
|
||||||
# Update all python version list
|
|
||||||
cd "${PYENV_PATH}" && git pull && cd -
|
|
||||||
yes n|pyenv install ${PYTHON_VERSION}
|
|
||||||
if [[ $retVal -ne 0 ]]; then
|
|
||||||
echo -e "${Red}Error${Color_Off} when installing pyenv"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# This will write .python-version
|
|
||||||
# pyenv local ${PYTHON_VERSION}
|
|
||||||
|
|
||||||
if [[ ! -d ${VENV_PATH} ]]; then
|
if [[ ! -d ${VENV_PATH} ]]; then
|
||||||
echo -e "\n---- Create Virtual environment Python ----"
|
echo -e "\n---- Create Virtual environment Python ----"
|
||||||
if [[ -e ${PYTHON_EXEC} ]]; then
|
if ! "${PYTHON_EXEC}" -m venv "${VENV_PATH}"; then
|
||||||
${PYTHON_EXEC} -m venv "${VENV_PATH}"
|
echo "Virtual environment, error when creating ${VENV_PATH}"
|
||||||
retVal=$?
|
exit 1
|
||||||
if [[ $retVal -ne 0 ]]; then
|
fi
|
||||||
echo "Virtual environment, error when creating ${VENV_PATH}"
|
fi
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Missing pyenv, please refer installation guide. Check variable '${PYTHON_EXEC}'."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
|
||||||
196
script/install/lib_python_provider.sh
Executable file
196
script/install/lib_python_provider.sh
Executable file
|
|
@ -0,0 +1,196 @@
|
||||||
|
#!/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 : « une version de Python » -> « un interpréteur ».
|
||||||
|
#
|
||||||
|
# C'est le seul endroit du dépôt qui décide COMMENT un interpréteur est
|
||||||
|
# obtenu. Tout le reste ne consomme que des chemins de venv, jamais pyenv ni
|
||||||
|
# mise. Ajouter un fournisseur se fait donc ici, et nulle part ailleurs.
|
||||||
|
#
|
||||||
|
# Deux fournisseurs :
|
||||||
|
# pyenv historique. Compile CPython depuis les sources : 1 à 3 min sur une
|
||||||
|
# machine récente, bien plus sous émulation, et il lui faut une
|
||||||
|
# douzaine de -dev (openssl, zlib, readline, sqlite, bzip2, xz, tk…).
|
||||||
|
# mise pose un CPython PRÉCOMPILÉ (astral python-build-standalone) :
|
||||||
|
# quelques secondes, aucun compilateur requis.
|
||||||
|
#
|
||||||
|
# EL_PYTHON_PROVIDER choisit : auto (défaut), mise, ou pyenv.
|
||||||
|
#
|
||||||
|
# En mode « auto », un interpréteur DÉJÀ présent gagne, quel que soit le
|
||||||
|
# fournisseur qui l'a posé. Une installation pyenv qui marche n'est donc
|
||||||
|
# jamais doublée par un second CPython de 150 Mo.
|
||||||
|
|
||||||
|
# Ne jamais laisser mise compiler en silence : sans build précompilée pour la
|
||||||
|
# plateforme, il retomberait sur python-build — le moteur de pyenv — et on
|
||||||
|
# aurait la lenteur de pyenv sans son outillage. « false » = télécharger ou
|
||||||
|
# échouer ; l'échec nous fait basculer proprement sur le repli.
|
||||||
|
export MISE_PYTHON_COMPILE=false
|
||||||
|
|
||||||
|
el_pyenv_root() {
|
||||||
|
echo "${PYENV_ROOT:-${HOME}/.pyenv}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Chemin de l'interpréteur pyenv d'une version, qu'il existe ou non.
|
||||||
|
el_pyenv_exec_path() {
|
||||||
|
echo "$(el_pyenv_root)/versions/$1/bin/python"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpréteur déjà posé par mise, sans le moindre accès réseau.
|
||||||
|
el_mise_exec_path() {
|
||||||
|
command -v mise > /dev/null 2>&1 || return 1
|
||||||
|
local out
|
||||||
|
out="$(mise where "python@$1" 2> /dev/null)" || return 1
|
||||||
|
[ -n "${out}" ] && [ -x "${out}/bin/python" ] || return 1
|
||||||
|
echo "${out}/bin/python"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Vrai si l'exécutable rend EXACTEMENT la version demandée. Un interpréteur
|
||||||
|
# présent mais d'une autre version casserait Poetry, dont le pyproject exige
|
||||||
|
# le patch au près (>=3.12.10,<3.13).
|
||||||
|
el_python_is_version() {
|
||||||
|
local exe="$1" want="$2" got
|
||||||
|
[ -x "${exe}" ] || return 1
|
||||||
|
got="$("${exe}" -c 'import platform;print(platform.python_version())' 2> /dev/null)"
|
||||||
|
[ "${got}" = "${want}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Vrai si l'exécutable CONVIENT : même majeure.mineure, et patch au moins
|
||||||
|
# égal au demandé. C'est exactement ce qu'exige le pyproject — « >=3.12.10,
|
||||||
|
# <3.13 » — et non l'égalité stricte que testait el_python_is_version.
|
||||||
|
#
|
||||||
|
# La distinction n'est pas théorique. Tumbleweed s390x livre python312 en
|
||||||
|
# 3.12.13 : parfaitement utilisable, mais rejeté par l'égalité, ce qui forçait
|
||||||
|
# pyenv à COMPILER CPython — et gcc 15.2 s'y arrête sur une erreur interne
|
||||||
|
# dans Parser/parser.c, un fichier généré de quarante mille lignes.
|
||||||
|
el_python_is_compatible() {
|
||||||
|
local exe="$1" want="$2" got
|
||||||
|
[ -x "${exe}" ] || return 1
|
||||||
|
got="$("${exe}" -c 'import platform;print(platform.python_version())' \
|
||||||
|
2> /dev/null)"
|
||||||
|
[ -n "${got}" ] || return 1
|
||||||
|
# Même majeure.mineure : 3.13 ne convient pas à un pyproject borné à <3.13.
|
||||||
|
[ "${got%.*}" = "${want%.*}" ] || return 1
|
||||||
|
# Patch au moins égal, comparé en version et non en chaîne (3.12.9 < 3.12.10).
|
||||||
|
[ "$(printf '%s\n%s\n' "${want}" "${got}" | sort -V | head -1)" = "${want}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpréteur de la DISTRIBUTION qui conviendrait, s'il y en a un.
|
||||||
|
#
|
||||||
|
# Cherché avant toute compilation : sur une architecture émulée, bâtir CPython
|
||||||
|
# prend des dizaines de minutes quand il aboutit. Le nom suit la convention de
|
||||||
|
# toutes les distributions, « python3.12 ».
|
||||||
|
el_distro_python_exec() {
|
||||||
|
local want="$1" exe
|
||||||
|
# Des chemins SYSTEME, jamais « command -v » : dans un venv activé celui-ci
|
||||||
|
# rend le python DU VENV, et l'on bâtirait un venv depuis un venv. Le PATH
|
||||||
|
# d'une session interactive n'a rien à faire dans cette décision.
|
||||||
|
for exe in "/usr/bin/python${want%.*}" "/usr/local/bin/python${want%.*}"; do
|
||||||
|
if el_python_is_compatible "${exe}" "${want}"; then
|
||||||
|
echo "${exe}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Installe la version via mise. Renvoie le chemin, ou échoue.
|
||||||
|
el_mise_install() {
|
||||||
|
local version="$1" exe
|
||||||
|
command -v mise > /dev/null 2>&1 || return 1
|
||||||
|
echo "---- Python ${version} via mise (precompile) ----" >&2
|
||||||
|
mise install "python@${version}" >&2 || return 1
|
||||||
|
exe="$(el_mise_exec_path "${version}")" || return 1
|
||||||
|
el_python_is_version "${exe}" "${version}" || return 1
|
||||||
|
echo "${exe}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Installe la version via pyenv, en posant pyenv lui-même au besoin.
|
||||||
|
el_pyenv_install() {
|
||||||
|
local version="$1" root exe
|
||||||
|
root="$(el_pyenv_root)"
|
||||||
|
exe="$(el_pyenv_exec_path "${version}")"
|
||||||
|
if [[ ! -d "${root}" ]]; then
|
||||||
|
echo "---- Installation de pyenv dans ${root} ----" >&2
|
||||||
|
curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer \
|
||||||
|
| bash >&2 || return 1
|
||||||
|
fi
|
||||||
|
export PATH="${root}/bin:$PATH"
|
||||||
|
eval "$(pyenv init - 2> /dev/null)" || true
|
||||||
|
eval "$(pyenv virtualenv-init - 2> /dev/null)" || true
|
||||||
|
if [[ ! -d "${root}/versions/${version}" ]]; then
|
||||||
|
# pyenv COMPILE CPython : sans compilateur C, il télécharge l'archive,
|
||||||
|
# lance configure et s'arrête sur « no acceptable C compiler found », après
|
||||||
|
# avoir gaspillé le téléchargement. On le dit AVANT, et on nomme le paquet.
|
||||||
|
if ! command -v cc > /dev/null 2>&1 \
|
||||||
|
&& ! command -v gcc > /dev/null 2>&1; then
|
||||||
|
echo "Aucun compilateur C : pyenv ne peut pas compiler Python." >&2
|
||||||
|
echo " Installez le necessaire de compilation (build-essential," >&2
|
||||||
|
echo " gcc/gcc-c++, ou le motif devel_basis) puis relancez." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "---- Python ${version} via pyenv (compilation) ----" >&2
|
||||||
|
# La liste des versions connues vient du dépôt git de pyenv : sans ce
|
||||||
|
# « pull », une version récente est « not a known version ».
|
||||||
|
(cd "${root}" && git pull) >&2 || true
|
||||||
|
# Le contrôle d'erreur d'origine testait un $retVal jamais affecté ici :
|
||||||
|
# un échec de compilation passait inaperçu jusqu'au test d'existence.
|
||||||
|
if ! yes n | pyenv install "${version}" >&2; then
|
||||||
|
echo "pyenv install ${version} a echoue." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
el_python_is_version "${exe}" "${version}" || return 1
|
||||||
|
echo "${exe}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# API publique : imprime le chemin absolu d'un interpréteur de cette version,
|
||||||
|
# ou rien (et rend non nul) si aucun fournisseur n'y parvient.
|
||||||
|
el_python_exec() {
|
||||||
|
local version="$1" provider="${EL_PYTHON_PROVIDER:-auto}" exe
|
||||||
|
|
||||||
|
# 1) Déjà présent ? On ne réinstalle rien et on ne touche pas au réseau.
|
||||||
|
# C'est ce qui rend le changement sans effet pour une installation
|
||||||
|
# pyenv existante.
|
||||||
|
if [ "${provider}" != "mise" ]; then
|
||||||
|
exe="$(el_pyenv_exec_path "${version}")"
|
||||||
|
if el_python_is_version "${exe}" "${version}"; then
|
||||||
|
echo "${exe}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "${provider}" != "pyenv" ]; then
|
||||||
|
if exe="$(el_mise_exec_path "${version}")" \
|
||||||
|
&& el_python_is_version "${exe}" "${version}"; then
|
||||||
|
echo "${exe}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2) Un interpréteur de la DISTRIBUTION qui convient ? Rien à installer,
|
||||||
|
# rien à compiler. Vérifié avant mise et pyenv : c'est le seul chemin
|
||||||
|
# qui ne coûte rien, et sur s390x le seul qui aboutisse partout — mise
|
||||||
|
# n'y publie aucun binaire, et pyenv doit compiler.
|
||||||
|
# Uniquement en mode « auto » : demander mise ou pyenv explicitement doit
|
||||||
|
# être respecté, sinon le réglage ne veut plus rien dire.
|
||||||
|
if [ "${provider}" = "auto" ] \
|
||||||
|
&& exe="$(el_distro_python_exec "${version}")"; then
|
||||||
|
echo "Python $("${exe}" -V 2>&1 | awk '{print $2}') de la distribution :" \
|
||||||
|
"aucune compilation." >&2
|
||||||
|
echo "${exe}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3) Rien de posé : il faut provisionner. mise d'abord quand il est là,
|
||||||
|
# parce qu'il télécharge au lieu de compiler.
|
||||||
|
if [ "${provider}" != "pyenv" ]; then
|
||||||
|
if exe="$(el_mise_install "${version}")"; then
|
||||||
|
echo "${exe}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
[ "${provider}" = "mise" ] && return 1
|
||||||
|
command -v mise > /dev/null 2>&1 \
|
||||||
|
&& echo "mise n'a pas pu fournir Python ${version} : repli sur pyenv." >&2
|
||||||
|
fi
|
||||||
|
el_pyenv_install "${version}"
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,23 @@ DIR_VENV_ERPLIBRE=".venv.erplibre"
|
||||||
if [[ ! -d "$DIR_VENV_ERPLIBRE" ]]; then
|
if [[ ! -d "$DIR_VENV_ERPLIBRE" ]]; then
|
||||||
DIR_VENV_ERPLIBRE_EXIST=0
|
DIR_VENV_ERPLIBRE_EXIST=0
|
||||||
echo "$DIR_VENV_ERPLIBRE does not exist."
|
echo "$DIR_VENV_ERPLIBRE does not exist."
|
||||||
if [[ ! -d "~/.pyenv/versions/$(< ./conf/python-erplibre-version)/bin/python" ]]; then
|
# Le test d'origine etait inoperant : le tilde entre guillemets n'est pas
|
||||||
"~/.pyenv/versions/$(< ./conf/python-erplibre-version)/bin/python" -m venv $DIR_VENV_ERPLIBRE
|
# etendu, et « -d » testait un FICHIER comme un repertoire. La condition
|
||||||
|
# etait donc toujours vraie, la commande echouait en « No such file or
|
||||||
|
# directory », et le repli « python -m venv » ne servait jamais.
|
||||||
|
# shellcheck source=script/install/lib_python_provider.sh
|
||||||
|
. ./script/install/lib_python_provider.sh
|
||||||
|
EL_PY_WANT="$(< ./conf/python-erplibre-version)"
|
||||||
|
# Ici on ne PROVISIONNE pas : ce script s'execute au demarrage de TODO, il
|
||||||
|
# doit rester rapide et hors reseau. On prend ce qui est deja pose, sinon
|
||||||
|
# le python du systeme.
|
||||||
|
EL_PY_EXEC="$(el_pyenv_exec_path "${EL_PY_WANT}")"
|
||||||
|
el_python_is_version "${EL_PY_EXEC}" "${EL_PY_WANT}" \
|
||||||
|
|| EL_PY_EXEC="$(el_mise_exec_path "${EL_PY_WANT}" 2> /dev/null)"
|
||||||
|
if [[ -n "${EL_PY_EXEC}" ]] && [[ -x "${EL_PY_EXEC}" ]]; then
|
||||||
|
"${EL_PY_EXEC}" -m venv $DIR_VENV_ERPLIBRE
|
||||||
else
|
else
|
||||||
python -m venv $DIR_VENV_ERPLIBRE
|
python3 -m venv $DIR_VENV_ERPLIBRE
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue