From 7b857b34f1d3ce98c2cbf9c9b523a1e66ab05151 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 5 Oct 2026 06:35:37 -0500 Subject: [PATCH 1/6] PYTHON-6051 Bump drivers-evergreen-tools to v1.2.0 --- .github/workflows/test-mod-wsgi.yml | 2 +- .github/workflows/test-python.yml | 14 +++++++------- drivers-evergreen-tools | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-mod-wsgi.yml b/.github/workflows/test-mod-wsgi.yml index 2ae2310ab6..c10db479cb 100644 --- a/.github/workflows/test-mod-wsgi.yml +++ b/.github/workflows/test-mod-wsgi.yml @@ -159,7 +159,7 @@ jobs: uv pip install -r requirements/mod_wsgi.txt uv run --no-sync python tools/fail_if_no_c.py - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@49da51cebc0060b4d699d57bdef30ee7e071de44 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 with: version: ${{ steps.versions.outputs.mongodb-version }} topology: "replica_set" diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index f5b1069e30..8a33ec381c 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -85,7 +85,7 @@ jobs: # The beta Python here relies on the action's prerelease default. python-version: ${{ matrix.python-version }} - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 with: version: "${{ matrix.mongodb-version }}" - name: Run tests @@ -107,7 +107,7 @@ jobs: with: python-version: "3.10" - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 with: version: "8.0" - name: Setup tests @@ -135,7 +135,7 @@ jobs: - name: Install dependencies run: just install - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 with: version: "8.0" - name: Run tests @@ -194,12 +194,12 @@ jobs: - name: Install dependencies run: just install - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 - name: Run tests run: | just integration-tests - id: setup-mongodb-ssl - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 with: ssl: true - name: Run tests @@ -254,7 +254,7 @@ jobs: # Test sdist on lowest supported Python python-version: "3.9" - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 - name: Run connect test from sdist shell: bash run: | @@ -278,7 +278,7 @@ jobs: with: python-version: "3.9" - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 # v1.1.0 + uses: mongodb-labs/drivers-evergreen-tools@354a81692bfd2b654a38277b681d248507d17800 # v1.2.0 with: version: "8.0" - name: Run tests diff --git a/drivers-evergreen-tools b/drivers-evergreen-tools index ec0b1497b3..354a81692b 160000 --- a/drivers-evergreen-tools +++ b/drivers-evergreen-tools @@ -1 +1 @@ -Subproject commit ec0b1497b3d351acbfc4fd7579bf3de4de0a1046 +Subproject commit 354a81692bfd2b654a38277b681d248507d17800 From c6976251200fe659c76d02eaf5fb43e0159746a2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 5 Oct 2026 06:37:12 -0500 Subject: [PATCH 2/6] PYTHON-6051 Make setup-uv-python.sh robust to missing interpreters and broken venvs --- .evergreen/scripts/setup-uv-python.sh | 39 ++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/.evergreen/scripts/setup-uv-python.sh b/.evergreen/scripts/setup-uv-python.sh index 09397803f5..b4454edd4e 100755 --- a/.evergreen/scripts/setup-uv-python.sh +++ b/.evergreen/scripts/setup-uv-python.sh @@ -16,6 +16,20 @@ set -euo pipefail HERE=$(dirname ${BASH_SOURCE:-$0}) HERE="$( cd -- "$HERE" > /dev/null 2>&1 && pwd )" +ROOT=$(dirname "$(dirname $HERE)") + +# A .venv whose interpreter was removed (e.g. a deleted uv-managed Python) +# makes every `uv python find` fail, even for interpreters that exist, and +# blocks `uv sync` too. The venv is a build artifact, so remove it and let +# `uv sync` recreate it. +for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scripts/python.exe"; do + if [ -L "$_py" ] && [ ! -e "$_py" ]; then + echo "Removing broken .venv (its interpreter is gone); uv sync will recreate it." + rm -rf "$ROOT/.venv" + break + fi +done +unset _py # Source the env files to pick up common variables. if [ -f $HERE/env.sh ]; then @@ -59,15 +73,34 @@ function _toolchain_dir() { } # Make sure uv can provide the requested Python, downloading it if needed. +# If the request cannot be found or installed (e.g. python-downloads = "never" +# in uv config, or the host is offline), fall back to any available Python on +# local hosts rather than blocking setup; on CI, fail the task instead. function _ensure_python() { - local request="$1" - if uv python find "$request" > /dev/null 2>&1; then + local request="$1" out _fallback + if out=$(uv python find "$request" 2>&1); then return 0 fi - echo "Python \"$request\" was not found on this host; asking uv to install it..." + # Show why find failed: e.g. an interpreter in the toolchain dir that uv + # cannot run (wrong architecture, broken install), or none at all. + echo "Python \"$request\" was not found on this host:" >&2 + sed 's/^/ /' <<<"$out" >&2 + echo "Asking uv to install Python \"$request\"..." if uv python install "$request"; then return 0 fi + echo "uv could not install Python \"$request\"; looking for another interpreter..." + # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE here: when the requested + # toolchain interpreter is broken they would steer the fallback right back to + # it. Local setup only — on CI a provisioning failure must fail the task + # rather than silently run the tests on a different Python than requested. + if [ "${CI:-}" != "true" ] && \ + _fallback=$(env -u UV_PYTHON_SEARCH_PATH -u UV_PYTHON_PREFERENCE \ + uv python find ">=3.9" 2>/dev/null); then + echo "Using fallback interpreter: $_fallback" + export UV_PYTHON="$_fallback" + return 0 + fi echo "ERROR: uv could not find or install Python \"$request\"." >&2 return 1 } From 3e7943ef06448df361c70a4f529fe43551c4aa76 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 5 Oct 2026 06:59:28 -0500 Subject: [PATCH 3/6] PYTHON-6051 Trim comments in setup-uv-python.sh --- .evergreen/scripts/setup-uv-python.sh | 50 ++++++++++----------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/.evergreen/scripts/setup-uv-python.sh b/.evergreen/scripts/setup-uv-python.sh index b4454edd4e..5c63833c3c 100755 --- a/.evergreen/scripts/setup-uv-python.sh +++ b/.evergreen/scripts/setup-uv-python.sh @@ -6,22 +6,19 @@ # or an interpreter path ("/usr/bin/python3.11"). # # Exports: -# UV_PYTHON_SEARCH_PATH - the Python toolchain bin dir for the request, so uv +# UV_PYTHON_SEARCH_PATH - the toolchain bin dir for the request, so uv # uses the toolchain Python instead of downloading one. -# UV_PYTHON_PREFERENCE - "system" so the toolchain wins over managed installs. -# A preference set by the task is left alone. -# UV_PYTHON - the Python interpreter uv uses; defaults to CPython -# 3.10 when the task does not set one. +# UV_PYTHON_PREFERENCE - "system" so the toolchain wins over managed installs; +# a preference set by the task is left alone. +# UV_PYTHON - the Python uv uses; defaults to CPython 3.10. set -euo pipefail HERE=$(dirname ${BASH_SOURCE:-$0}) HERE="$( cd -- "$HERE" > /dev/null 2>&1 && pwd )" ROOT=$(dirname "$(dirname $HERE)") -# A .venv whose interpreter was removed (e.g. a deleted uv-managed Python) -# makes every `uv python find` fail, even for interpreters that exist, and -# blocks `uv sync` too. The venv is a build artifact, so remove it and let -# `uv sync` recreate it. +# A .venv whose interpreter was removed breaks every `uv python find` and +# `uv sync`. It is a build artifact, so remove it and let `uv sync` recreate it. for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scripts/python.exe"; do if [ -L "$_py" ] && [ ! -e "$_py" ]; then echo "Removing broken .venv (its interpreter is gone); uv sync will recreate it." @@ -31,26 +28,21 @@ for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scrip done unset _py -# Source the env files to pick up common variables. if [ -f $HERE/env.sh ]; then . $HERE/env.sh fi -# Get variables defined in test-env.sh. if [ -f $HERE/test-env.sh ]; then . $HERE/test-env.sh fi -# Default to a known-good Python so behavior is deterministic when a task does -# not pin one. Selecting the uv binary is separate and driven by the required -# uv version in pyproject.toml. +# Default to a known-good Python when the task does not pin one. export UV_PYTHON="${UV_PYTHON:-3.10}" -# Print the Python toolchain bin dir for a version like "3.10" or "3.14t". +# Print the toolchain bin dir for a version like "3.10" or "3.14t". function _toolchain_dir() { local version="$1" dir - # Only plain CPython versions live in the toolchain. - [[ "$version" =~ ^[0-9]+\.[0-9]+t?$ ]] || return 1 + [[ "$version" =~ ^[0-9]+\.[0-9]+t?$ ]] || return 1 # plain CPython only if [ "Windows_NT" = "${OS:-}" ]; then local winver="${version%t}" winver="${winver//./}" @@ -72,17 +64,15 @@ function _toolchain_dir() { echo "$dir" } -# Make sure uv can provide the requested Python, downloading it if needed. -# If the request cannot be found or installed (e.g. python-downloads = "never" -# in uv config, or the host is offline), fall back to any available Python on -# local hosts rather than blocking setup; on CI, fail the task instead. +# Make sure uv can provide the requested Python, installing it if needed. If +# the request cannot be found or installed, fall back to any available Python +# on local hosts rather than blocking setup; on CI, fail the task instead. function _ensure_python() { local request="$1" out _fallback if out=$(uv python find "$request" 2>&1); then return 0 fi - # Show why find failed: e.g. an interpreter in the toolchain dir that uv - # cannot run (wrong architecture, broken install), or none at all. + # Show why find failed: e.g. an interpreter uv cannot run, or none at all. echo "Python \"$request\" was not found on this host:" >&2 sed 's/^/ /' <<<"$out" >&2 echo "Asking uv to install Python \"$request\"..." @@ -90,10 +80,8 @@ function _ensure_python() { return 0 fi echo "uv could not install Python \"$request\"; looking for another interpreter..." - # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE here: when the requested - # toolchain interpreter is broken they would steer the fallback right back to - # it. Local setup only — on CI a provisioning failure must fail the task - # rather than silently run the tests on a different Python than requested. + # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE: they would steer the + # fallback right back to the broken interpreter. Local setup only. if [ "${CI:-}" != "true" ] && \ _fallback=$(env -u UV_PYTHON_SEARCH_PATH -u UV_PYTHON_PREFERENCE \ uv python find ">=3.9" 2>/dev/null); then @@ -109,7 +97,7 @@ _search_path="" _skip_ensure="" if [[ "$UV_PYTHON" == */* || "$UV_PYTHON" == *\\* ]]; then - # An explicit interpreter path; uv uses it as-is, so probe/install is skipped. + # An explicit interpreter path; uv uses it as-is, so skip the probe. if [ ! -x "$UV_PYTHON" ]; then echo "ERROR: UV_PYTHON=$UV_PYTHON does not exist or is not executable." >&2 exit 1 @@ -119,10 +107,8 @@ elif _dir=$(_toolchain_dir "$UV_PYTHON"); then _search_path="$_dir" fi -# Point uv at the toolchain Python when there is one and the task did not set -# its own preference: a task-level UV_PYTHON_PREFERENCE wins (PYTHON-6135). -# On CI the toolchain dir is already first on PATH (configure-env.sh), so this -# mainly benefits local hosts and later steps. +# Point uv at the toolchain Python when the task did not set its own +# preference; a task-level UV_PYTHON_PREFERENCE wins (PYTHON-6135). if [ -n "$_search_path" ] && [ -z "${UV_PYTHON_PREFERENCE:-}" ]; then export UV_PYTHON_SEARCH_PATH="$_search_path" export UV_PYTHON_PREFERENCE="system" From 4a832920857c9be0b83859c224efdb8d97814507 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 5 Oct 2026 08:00:38 -0500 Subject: [PATCH 4/6] Revert "PYTHON-6051 Trim comments in setup-uv-python.sh" This reverts commit 3e7943ef06448df361c70a4f529fe43551c4aa76. --- .evergreen/scripts/setup-uv-python.sh | 50 +++++++++++++++++---------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/.evergreen/scripts/setup-uv-python.sh b/.evergreen/scripts/setup-uv-python.sh index 5c63833c3c..b4454edd4e 100755 --- a/.evergreen/scripts/setup-uv-python.sh +++ b/.evergreen/scripts/setup-uv-python.sh @@ -6,19 +6,22 @@ # or an interpreter path ("/usr/bin/python3.11"). # # Exports: -# UV_PYTHON_SEARCH_PATH - the toolchain bin dir for the request, so uv +# UV_PYTHON_SEARCH_PATH - the Python toolchain bin dir for the request, so uv # uses the toolchain Python instead of downloading one. -# UV_PYTHON_PREFERENCE - "system" so the toolchain wins over managed installs; -# a preference set by the task is left alone. -# UV_PYTHON - the Python uv uses; defaults to CPython 3.10. +# UV_PYTHON_PREFERENCE - "system" so the toolchain wins over managed installs. +# A preference set by the task is left alone. +# UV_PYTHON - the Python interpreter uv uses; defaults to CPython +# 3.10 when the task does not set one. set -euo pipefail HERE=$(dirname ${BASH_SOURCE:-$0}) HERE="$( cd -- "$HERE" > /dev/null 2>&1 && pwd )" ROOT=$(dirname "$(dirname $HERE)") -# A .venv whose interpreter was removed breaks every `uv python find` and -# `uv sync`. It is a build artifact, so remove it and let `uv sync` recreate it. +# A .venv whose interpreter was removed (e.g. a deleted uv-managed Python) +# makes every `uv python find` fail, even for interpreters that exist, and +# blocks `uv sync` too. The venv is a build artifact, so remove it and let +# `uv sync` recreate it. for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scripts/python.exe"; do if [ -L "$_py" ] && [ ! -e "$_py" ]; then echo "Removing broken .venv (its interpreter is gone); uv sync will recreate it." @@ -28,21 +31,26 @@ for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scrip done unset _py +# Source the env files to pick up common variables. if [ -f $HERE/env.sh ]; then . $HERE/env.sh fi +# Get variables defined in test-env.sh. if [ -f $HERE/test-env.sh ]; then . $HERE/test-env.sh fi -# Default to a known-good Python when the task does not pin one. +# Default to a known-good Python so behavior is deterministic when a task does +# not pin one. Selecting the uv binary is separate and driven by the required +# uv version in pyproject.toml. export UV_PYTHON="${UV_PYTHON:-3.10}" -# Print the toolchain bin dir for a version like "3.10" or "3.14t". +# Print the Python toolchain bin dir for a version like "3.10" or "3.14t". function _toolchain_dir() { local version="$1" dir - [[ "$version" =~ ^[0-9]+\.[0-9]+t?$ ]] || return 1 # plain CPython only + # Only plain CPython versions live in the toolchain. + [[ "$version" =~ ^[0-9]+\.[0-9]+t?$ ]] || return 1 if [ "Windows_NT" = "${OS:-}" ]; then local winver="${version%t}" winver="${winver//./}" @@ -64,15 +72,17 @@ function _toolchain_dir() { echo "$dir" } -# Make sure uv can provide the requested Python, installing it if needed. If -# the request cannot be found or installed, fall back to any available Python -# on local hosts rather than blocking setup; on CI, fail the task instead. +# Make sure uv can provide the requested Python, downloading it if needed. +# If the request cannot be found or installed (e.g. python-downloads = "never" +# in uv config, or the host is offline), fall back to any available Python on +# local hosts rather than blocking setup; on CI, fail the task instead. function _ensure_python() { local request="$1" out _fallback if out=$(uv python find "$request" 2>&1); then return 0 fi - # Show why find failed: e.g. an interpreter uv cannot run, or none at all. + # Show why find failed: e.g. an interpreter in the toolchain dir that uv + # cannot run (wrong architecture, broken install), or none at all. echo "Python \"$request\" was not found on this host:" >&2 sed 's/^/ /' <<<"$out" >&2 echo "Asking uv to install Python \"$request\"..." @@ -80,8 +90,10 @@ function _ensure_python() { return 0 fi echo "uv could not install Python \"$request\"; looking for another interpreter..." - # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE: they would steer the - # fallback right back to the broken interpreter. Local setup only. + # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE here: when the requested + # toolchain interpreter is broken they would steer the fallback right back to + # it. Local setup only — on CI a provisioning failure must fail the task + # rather than silently run the tests on a different Python than requested. if [ "${CI:-}" != "true" ] && \ _fallback=$(env -u UV_PYTHON_SEARCH_PATH -u UV_PYTHON_PREFERENCE \ uv python find ">=3.9" 2>/dev/null); then @@ -97,7 +109,7 @@ _search_path="" _skip_ensure="" if [[ "$UV_PYTHON" == */* || "$UV_PYTHON" == *\\* ]]; then - # An explicit interpreter path; uv uses it as-is, so skip the probe. + # An explicit interpreter path; uv uses it as-is, so probe/install is skipped. if [ ! -x "$UV_PYTHON" ]; then echo "ERROR: UV_PYTHON=$UV_PYTHON does not exist or is not executable." >&2 exit 1 @@ -107,8 +119,10 @@ elif _dir=$(_toolchain_dir "$UV_PYTHON"); then _search_path="$_dir" fi -# Point uv at the toolchain Python when the task did not set its own -# preference; a task-level UV_PYTHON_PREFERENCE wins (PYTHON-6135). +# Point uv at the toolchain Python when there is one and the task did not set +# its own preference: a task-level UV_PYTHON_PREFERENCE wins (PYTHON-6135). +# On CI the toolchain dir is already first on PATH (configure-env.sh), so this +# mainly benefits local hosts and later steps. if [ -n "$_search_path" ] && [ -z "${UV_PYTHON_PREFERENCE:-}" ]; then export UV_PYTHON_SEARCH_PATH="$_search_path" export UV_PYTHON_PREFERENCE="system" From a33d24e187c5cff71cf5f17ba65d0fddfd1d5e30 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 5 Oct 2026 08:06:05 -0500 Subject: [PATCH 5/6] PYTHON-6051 Trim new comments in setup-uv-python.sh --- .evergreen/scripts/setup-uv-python.sh | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/.evergreen/scripts/setup-uv-python.sh b/.evergreen/scripts/setup-uv-python.sh index b4454edd4e..e264905bc0 100755 --- a/.evergreen/scripts/setup-uv-python.sh +++ b/.evergreen/scripts/setup-uv-python.sh @@ -18,10 +18,8 @@ HERE=$(dirname ${BASH_SOURCE:-$0}) HERE="$( cd -- "$HERE" > /dev/null 2>&1 && pwd )" ROOT=$(dirname "$(dirname $HERE)") -# A .venv whose interpreter was removed (e.g. a deleted uv-managed Python) -# makes every `uv python find` fail, even for interpreters that exist, and -# blocks `uv sync` too. The venv is a build artifact, so remove it and let -# `uv sync` recreate it. +# A .venv whose interpreter was removed breaks every `uv python find` and +# `uv sync`. It is a build artifact, so remove it and let `uv sync` recreate it. for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scripts/python.exe"; do if [ -L "$_py" ] && [ ! -e "$_py" ]; then echo "Removing broken .venv (its interpreter is gone); uv sync will recreate it." @@ -73,16 +71,13 @@ function _toolchain_dir() { } # Make sure uv can provide the requested Python, downloading it if needed. -# If the request cannot be found or installed (e.g. python-downloads = "never" -# in uv config, or the host is offline), fall back to any available Python on -# local hosts rather than blocking setup; on CI, fail the task instead. +# If that fails, fall back to any available Python on local hosts; on CI, fail. function _ensure_python() { local request="$1" out _fallback if out=$(uv python find "$request" 2>&1); then return 0 fi - # Show why find failed: e.g. an interpreter in the toolchain dir that uv - # cannot run (wrong architecture, broken install), or none at all. + # Show why find failed: e.g. an interpreter uv cannot run, or none at all. echo "Python \"$request\" was not found on this host:" >&2 sed 's/^/ /' <<<"$out" >&2 echo "Asking uv to install Python \"$request\"..." @@ -90,10 +85,8 @@ function _ensure_python() { return 0 fi echo "uv could not install Python \"$request\"; looking for another interpreter..." - # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE here: when the requested - # toolchain interpreter is broken they would steer the fallback right back to - # it. Local setup only — on CI a provisioning failure must fail the task - # rather than silently run the tests on a different Python than requested. + # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE: they would steer the + # fallback right back to the broken interpreter. Local setup only. if [ "${CI:-}" != "true" ] && \ _fallback=$(env -u UV_PYTHON_SEARCH_PATH -u UV_PYTHON_PREFERENCE \ uv python find ">=3.9" 2>/dev/null); then From ee130e40d5ee837826e2e2117cf4c4353e4c97f3 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 5 Oct 2026 10:21:36 -0500 Subject: [PATCH 6/6] address review --- .evergreen/scripts/setup-uv-python.sh | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.evergreen/scripts/setup-uv-python.sh b/.evergreen/scripts/setup-uv-python.sh index e264905bc0..2d91cc6dc6 100755 --- a/.evergreen/scripts/setup-uv-python.sh +++ b/.evergreen/scripts/setup-uv-python.sh @@ -14,29 +14,33 @@ # 3.10 when the task does not set one. set -euo pipefail -HERE=$(dirname ${BASH_SOURCE:-$0}) +HERE=$(dirname "${BASH_SOURCE:-$0}") HERE="$( cd -- "$HERE" > /dev/null 2>&1 && pwd )" -ROOT=$(dirname "$(dirname $HERE)") +ROOT=$(dirname "$(dirname "$HERE")") # A .venv whose interpreter was removed breaks every `uv python find` and # `uv sync`. It is a build artifact, so remove it and let `uv sync` recreate it. +# A removed base interpreter leaves a dangling symlink on Linux/macOS and a +# launcher that will not start on Windows, so probe by running the interpreter. for _py in "$ROOT/.venv/bin/python3" "$ROOT/.venv/bin/python" "$ROOT/.venv/Scripts/python.exe"; do - if [ -L "$_py" ] && [ ! -e "$_py" ]; then - echo "Removing broken .venv (its interpreter is gone); uv sync will recreate it." - rm -rf "$ROOT/.venv" + if [ -e "$_py" ] || [ -L "$_py" ]; then + if ! "$_py" -c 'import sys' > /dev/null 2>&1; then + echo "Removing broken .venv (its interpreter will not start); uv sync will recreate it." + rm -rf "$ROOT/.venv" + fi break fi done unset _py # Source the env files to pick up common variables. -if [ -f $HERE/env.sh ]; then - . $HERE/env.sh +if [ -f "$HERE/env.sh" ]; then + . "$HERE/env.sh" fi # Get variables defined in test-env.sh. -if [ -f $HERE/test-env.sh ]; then - . $HERE/test-env.sh +if [ -f "$HERE/test-env.sh" ]; then + . "$HERE/test-env.sh" fi # Default to a known-good Python so behavior is deterministic when a task does @@ -85,10 +89,11 @@ function _ensure_python() { return 0 fi echo "uv could not install Python \"$request\"; looking for another interpreter..." - # Ignore UV_PYTHON_SEARCH_PATH/UV_PYTHON_PREFERENCE: they would steer the - # fallback right back to the broken interpreter. Local setup only. + # Ignore UV_PYTHON and friends: they would steer the fallback right back to + # the broken interpreter. Local setup only: the Evergreen agent exports + # CI=true for every task command. if [ "${CI:-}" != "true" ] && \ - _fallback=$(env -u UV_PYTHON_SEARCH_PATH -u UV_PYTHON_PREFERENCE \ + _fallback=$(env -u UV_PYTHON -u UV_PYTHON_SEARCH_PATH -u UV_PYTHON_PREFERENCE \ uv python find ">=3.9" 2>/dev/null); then echo "Using fallback interpreter: $_fallback" export UV_PYTHON="$_fallback"