fix(install): cap requires-python at <3.14 and pin UV_PYTHON to the venv (#38535)

uv selects the project Python from requires-python and from the UV_PYTHON
env var, both of which override an already-created venv on the next
'uv sync'. With no upper bound on requires-python, an inherited
UV_PYTHON=3.14 (or a fresh distro whose newest interpreter uv auto-picks)
silently recreated the installer's 3.11 venv at 3.14, where Rust-backed
transitives (pydantic-core) have no cp314 wheel and fall back to a maturin
source build that fails. This bit a Windows/WSL user with UV_PYTHON set in
their shell and a fresh WSL-arch box where uv auto-picked 3.14.

Two layers:
- pyproject: requires-python '>=3.11' -> '>=3.11,<3.14' (+ uv lock regen).
  uv now refuses a 3.14 interpreter with a clear error instead of attempting
  the maturin build. Backstop independent of the installer.
- install.sh / install.ps1: pin UV_PYTHON to the venv interpreter after
  creating it (in both the venv step and the deps step, since bootstrap runs
  those stages as separate processes). An inherited UV_PYTHON can no longer
  hijack the sync/pip tiers, so the install just works regardless of shell env.

Verified E2E: hostile UV_PYTHON=3.14 + uv venv --python 3.11 + uv sync now
installs into 3.11 with pydantic-core's 3.11 wheel; without the re-pin the
capped requires-python produces a legible incompatibility error rather than a
cryptic build failure.
This commit is contained in:
Teknium 2026-06-03 16:45:47 -07:00 committed by GitHub
parent e8c3ac2f5c
commit 475ecea3d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 584 deletions

View file

@ -1178,12 +1178,33 @@ setup_venv() {
# uv creates the venv and pins the Python version in one step
$UV_CMD venv venv --python "$PYTHON_VERSION"
# Neutralize any inherited UV_PYTHON (e.g. UV_PYTHON=3.14 left in the
# user's shell env). uv honours UV_PYTHON over an existing venv for the
# later `uv sync` / `uv pip install` tiers, so without this it would
# silently delete this 3.11 venv and recreate it at the inherited
# version — building Rust transitives that have no wheel for that
# version from source via maturin, which fails. Pinning UV_PYTHON to the
# interpreter we just created forces every subsequent uv command onto it.
if [ -x "$INSTALL_DIR/venv/bin/python" ]; then
export UV_PYTHON="$INSTALL_DIR/venv/bin/python"
fi
log_success "Virtual environment ready (Python $PYTHON_VERSION)"
}
install_deps() {
log_info "Installing dependencies..."
# Re-pin UV_PYTHON to the venv interpreter. setup_venv already does this,
# but the bootstrap runs install stages (`venv`, `python-deps`) as separate
# processes, so an export from setup_venv does NOT survive into a separate
# python-deps invocation. Re-deriving it here covers that path. Without it,
# an inherited UV_PYTHON=3.14 makes the uv sync/pip tiers below recreate the
# venv at 3.14 and fail the maturin source build (no cp314 wheels yet).
if [ "$DISTRO" != "termux" ] && [ -x "$INSTALL_DIR/venv/bin/python" ]; then
export UV_PYTHON="$INSTALL_DIR/venv/bin/python"
fi
if [ "$DISTRO" = "termux" ]; then
if [ "$USE_VENV" = true ]; then
export VIRTUAL_ENV="$INSTALL_DIR/venv"