Files
light-heart-labs--dreamserver/ods/installers/lib/python-runtime.sh
T
wehub-resource-sync 9e8f1bbeed
Dashboard / frontend (push) Failing after 0s
Dashboard / api (push) Failing after 0s
Lint PowerShell / powershell-lint (ubuntu-latest) (push) Failing after 1s
Python Lint / Lint Python with Ruff (push) Failing after 1s
ShellCheck / Lint shell scripts (push) Failing after 1s
Matrix Smoke / linux-smoke (push) Failing after 1s
Matrix Smoke / distro: cachyos (push) Failing after 15s
Matrix Smoke / distro: linux-mint-21.3 (push) Failing after 15s
Matrix Smoke / distro: debian-12 (push) Failing after 5m21s
Matrix Smoke / distro: fedora-41 (push) Failing after 4m56s
Matrix Smoke / distro: ubuntu-24.04 (push) Failing after 2m13s
Matrix Smoke / distro: rocky-9 (push) Failing after 10m39s
Matrix Smoke / distro: manjaro (push) Failing after 12m11s
Matrix Smoke / distro: opensuse-tw (push) Failing after 11m53s
Matrix Smoke / distro: archlinux (push) Failing after 20m3s
Matrix Smoke / distro: ubuntu-22.04 (push) Failing after 13m49s
Validate .env Schema / tier-1-env-validation (push) Successful in 52s
Validate .env Schema / tier-2-env-validation (push) Successful in 44s
Validate .env Schema / tier-3-env-validation (push) Successful in 52s
Validate .env Schema / tier-4-env-validation (push) Successful in 51s
Validate Extensions Catalog / Check catalog is up-to-date (push) Failing after 9m47s
Secret Scan / Scan for secrets (push) Failing after 21m4s
Validate Docker Compose / Validate Docker Compose files (push) Has been cancelled
Python Type Check / Type check with mypy (push) Has been cancelled
Validate .env Schema / tier-0-env-validation (push) Has been cancelled
Test Linux / integration-smoke (push) Has been cancelled
Lint PowerShell / powershell-lint (windows-latest) (push) Has been cancelled
Matrix Smoke / macos-smoke (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:31:33 +08:00

114 lines
4.1 KiB
Bash
Executable File

#!/bin/bash
# ============================================================================
# ODS Installer — Python runtime guards
# ============================================================================
# Part of: installers/lib/
# Purpose: Ensure installer Python helpers use an interpreter that can import
# the modules they need. This especially protects Linux users with
# Conda/venv Python ahead of /usr/bin/python3 in PATH.
#
# Expects: SCRIPT_DIR, LOG_FILE, PKG_MANAGER, INTERACTIVE, DRY_RUN,
# pkg_install(), pkg_resolve(), ods_sudo(), ai(), ai_ok(), ai_warn(),
# error()
# Provides: ods_python_cmd_path(), ods_python_has_module(),
# ods_ensure_python_module()
# ============================================================================
[[ -f "${SCRIPT_DIR:-$(pwd)}/lib/python-cmd.sh" ]] && . "${SCRIPT_DIR:-$(pwd)}/lib/python-cmd.sh"
ods_python_cmd_path() {
local cmd="${1:-$(ods_detect_python_cmd 2>/dev/null || true)}"
[[ -z "$cmd" ]] && return 1
command -v "$cmd" 2>/dev/null || printf '%s\n' "$cmd"
}
ods_python_has_module() {
local module="$1"
local pycmd="${2:-$(ods_detect_python_cmd)}"
"$pycmd" -c "import ${module}" >/dev/null 2>&1
}
ods_python_is_env_managed() {
local py_path="${1:-$(ods_python_cmd_path 2>/dev/null || true)}"
[[ -n "${CONDA_PREFIX:-}" || -n "${VIRTUAL_ENV:-}" ]] && return 0
[[ "$py_path" == *"/conda/"* || "$py_path" == *"/miniconda"* || "$py_path" == *"/anaconda"* ]] && return 0
[[ "$py_path" == *"/.venv/"* || "$py_path" == *"/venv/"* ]] && return 0
return 1
}
ods_ensure_python_runtime() {
local pycmd
pycmd="$(ods_detect_python_cmd 2>/dev/null || true)"
if [[ -n "$pycmd" ]]; then
printf '%s' "$pycmd"
return 0
fi
if [[ "${DRY_RUN:-false}" == "true" ]]; then
ai_warn "Python is not available (dry-run: would install python3)." >&2
return 1
fi
if declare -f pkg_install >/dev/null 2>&1; then
ai "Installing python3 for installer helpers..." >&2
if declare -f pkg_update >/dev/null 2>&1; then
case "${PKG_MANAGER:-}" in
apt|apk|dnf|xbps|zypper) pkg_update >/dev/null || true ;;
esac
fi
pkg_install python3 >/dev/null 2>>"${LOG_FILE:-/dev/null}" || true
_ods_python_cmd_cached=""
fi
pycmd="$(ods_detect_python_cmd 2>/dev/null || true)"
[[ -n "$pycmd" ]] || return 1
printf '%s' "$pycmd"
}
ods_ensure_python_module() {
local module="$1"
local canonical_pkg="$2"
local pip_pkg="$3"
local display="${4:-$module}"
local pycmd
pycmd="$(ods_ensure_python_runtime)" || error "Python is required but no runnable python3/python was found."
if ods_python_has_module "$module" "$pycmd"; then
ai_ok "$display available for $pycmd"
return 0
fi
if [[ "${DRY_RUN:-false}" == "true" ]]; then
ai_warn "$display is not importable by $pycmd (dry-run: would install ${canonical_pkg})."
return 0
fi
if declare -f pkg_install >/dev/null 2>&1 && declare -f pkg_resolve >/dev/null 2>&1; then
ai "Installing $display for the installer Python runtime..."
# shellcheck disable=SC2046
pkg_install $(pkg_resolve "$canonical_pkg") 2>>"${LOG_FILE:-/dev/null}" || true
fi
if ods_python_has_module "$module" "$pycmd"; then
ai_ok "$display available for $pycmd"
return 0
fi
local py_path
py_path="$(ods_python_cmd_path "$pycmd" 2>/dev/null || printf '%s' "$pycmd")"
if ods_python_is_env_managed "$py_path"; then
ai_bad "$display is not importable by the active Python: $py_path"
ai_bad "A Conda/venv Python appears to be ahead of the system Python."
ai "Run: conda deactivate"
ai "Then re-run the installer, or install the module into that environment:"
ai " $pycmd -m pip install $pip_pkg"
else
ai_bad "$display is not importable by $pycmd."
ai "Install it manually and re-run:"
ai " $pycmd -m pip install $pip_pkg"
fi
error "$display is required by the ODS compose and service registry helpers."
}