From 30fae6c806d750cbd4ffa28b6784a8021b70142c Mon Sep 17 00:00:00 2001 From: MickLesk Date: Mon, 3 Aug 2026 10:35:28 +0200 Subject: [PATCH] refactor: pyenv --- tools/addon/pyenv.sh | 131 +++++++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 37 deletions(-) diff --git a/tools/addon/pyenv.sh b/tools/addon/pyenv.sh index 2ad53f19a..51e32eedf 100644 --- a/tools/addon/pyenv.sh +++ b/tools/addon/pyenv.sh @@ -8,6 +8,16 @@ APP="pyenv" APP_TYPE="addon" +if ! command -v curl &>/dev/null; then + printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2 + if [[ -f /etc/alpine-release ]]; then + apk update >/dev/null 2>&1 + apk add --no-cache curl >/dev/null 2>&1 + else + apt-get update >/dev/null 2>&1 + apt-get install -y curl >/dev/null 2>&1 + fi +fi source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func) source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func) @@ -25,46 +35,93 @@ require_debian_like header_info confirm_not_pve_host get_lxc_ip -msg_info "Installing ${APP}" -$STD apt update -$STD apt install -y \ - make \ - build-essential \ - libjpeg-dev \ - libpcap-dev \ - libssl-dev \ - zlib1g-dev \ - libbz2-dev \ - libreadline-dev \ - libsqlite3-dev \ - autoconf \ - git \ - curl \ - sudo \ - llvm \ - libncursesw5-dev \ - xz-utils \ - tk-dev \ - libxml2-dev \ - libxmlsec1-dev \ - libffi-dev \ - libopenjp2-7 \ - libtiff5 \ - libturbojpeg0-dev \ - liblzma-dev +export PYENV_ROOT="${HOME}/.pyenv" -$STD git clone https://github.com/pyenv/pyenv.git ~/.pyenv +msg_info "Installing dependencies" +$STD apt update + +# Official Python build dependencies for Debian/Ubuntu +# https://github.com/pyenv/pyenv/wiki#suggested-build-environment +PYENV_DEPS=( + build-essential + libssl-dev + zlib1g-dev + libbz2-dev + libreadline-dev + libsqlite3-dev + curl + git + xz-utils + tk-dev + libxml2-dev + libxmlsec1-dev + libffi-dev + liblzma-dev +) + +# Extras for the optional Home Assistant / ESPHome installs below (Pillow et al.) +PYENV_DEPS+=(make llvm libjpeg-dev libpcap-dev libopenjp2-7) + +# These were renamed between releases (libtiff5 is gone on Debian 13 / Ubuntu 24.04), +# so take whichever variant the distro actually ships +for candidates in "libncurses-dev libncursesw5-dev" "libtiff-dev libtiff5-dev" "libturbojpeg0-dev libturbojpeg-dev"; do + for pkg in $candidates; do + if apt-cache show "$pkg" &>/dev/null; then + PYENV_DEPS+=("$pkg") + break + fi + done +done + +install_packages_with_retry "${PYENV_DEPS[@]}" +msg_ok "Installed dependencies" + +# The upstream installer refuses to run when PYENV_ROOT already exists +if [[ -d "$PYENV_ROOT" ]]; then + msg_ok "${APP} is already installed at ${PYENV_ROOT}" +else + msg_info "Installing ${APP}" + # Official installer - also sets up the pyenv-doctor/update/virtualenv plugins + $STD bash <(curl -fsSL https://pyenv.run) + msg_ok "Installed ${APP}" +fi + +# Shell setup per upstream docs. On Debian-based systems ~/.profile prepends the +# per-user bin dirs *after* sourcing ~/.bashrc, so both files need the init call. +msg_info "Configuring shell environment" +for rc in "${HOME}/.bashrc" "${HOME}/.profile"; do + [[ -f "$rc" ]] || touch "$rc" + if ! grep -q 'PYENV_ROOT' "$rc"; then + cat >>"$rc" <<'EOF' + +# pyenv +export PYENV_ROOT="$HOME/.pyenv" +[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH" +eval "$(pyenv init - bash)" +EOF + fi +done +msg_ok "Configured shell environment" + +# Activate pyenv for the remainder of this script +export PATH="${PYENV_ROOT}/bin:$PATH" set +Eeuo pipefail -echo 'export PYENV_ROOT="$HOME/.pyenv"' >>~/.bashrc -echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >>~/.bashrc -echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init --path)"\nfi' >>~/.bashrc -msg_ok "Installed ${APP}" -. ~/.bashrc +eval "$(pyenv init - bash)" set -Eeuo pipefail -msg_info "Installing Python 3.11.1" -$STD pyenv install 3.11.1 -pyenv global 3.11.1 -msg_ok "Installed Python 3.11.1" + +# pyenv resolves a version prefix to the latest release in that line, so pinning +# a patch level (the old 3.11.1) is neither needed nor portable across distros. +# +# 3.14 is the only series all three optional payloads below agree on: +# Home Assistant Core >= 3.14.2 +# ESPHome >= 3.12.0, < 3.15 +# python-matter-server >= 3.12 +# (3.11 has been security-fix-only since 2024 and is EOL in 10/2027.) +PYTHON_SERIES="3.14" +msg_info "Installing Python ${PYTHON_SERIES} (latest patch release)" +$STD pyenv install -s "$PYTHON_SERIES" +pyenv global "$PYTHON_SERIES" +msg_ok "Installed Python $(pyenv version-name)" read -r -p "Would you like to install Home Assistant Beta? " prompt if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then msg_info "Installing Home Assistant Beta"