From aac4141a509ca8ea82e7cfea7c4788950877aefc Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 23 Jul 2026 01:47:02 -0400 Subject: [PATCH 1/3] fix(ci): pin the discovered Python to the venv/setup-python interpreter The manylinux/musllinux images added Python 3.15 and dropped 3.13t; FindPython's version scan then picked /usr/local/bin/python3.15 over the uv-created venv (Python_ROOT_DIR is only a hint). Similarly, the macOS and Windows 3.14t jobs picked a system 3.14 over setup-python's free-threaded interpreter. Pin the interpreter explicitly in both places, and drop the 3.13t manylinux jobs. Assisted-by: ClaudeCode:claude-fable-5 --- .github/workflows/ci.yml | 4 ---- .github/workflows/reusable-standard.yml | 7 +++++++ CMakeLists.txt | 10 ++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7529df1f71..359741c9b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -240,10 +240,6 @@ jobs: fail-fast: false matrix: include: - - container: quay.io/pypa/manylinux_2_28_x86_64:latest - python-version: '3.13t' - - container: quay.io/pypa/musllinux_1_2_x86_64:latest - python-version: '3.13t' - container: quay.io/pypa/manylinux_2_28_x86_64:latest python-version: '3.14t' - container: quay.io/pypa/musllinux_1_2_x86_64:latest diff --git a/.github/workflows/reusable-standard.yml b/.github/workflows/reusable-standard.yml index f96116a1e7..3e4bfa3dce 100644 --- a/.github/workflows/reusable-standard.yml +++ b/.github/workflows/reusable-standard.yml @@ -67,6 +67,12 @@ jobs: if: runner.os != 'Windows' run: echo "CMAKE_GENERATOR=Ninja" >> "$GITHUB_ENV" + # FindPython's version scan can pick a different interpreter (e.g. + # Homebrew's 3.14 instead of setup-python's 3.14t), so pin it. + - name: Locate Python for CMake + shell: bash + run: echo "PYTHON_EXE=$(python -c 'import sys, pathlib; print(pathlib.Path(sys.executable).as_posix())')" >> "$GITHUB_ENV" + - name: Configure run: > cmake -S. -Bbuild -Werror=dev @@ -74,6 +80,7 @@ jobs: -DPYBIND11_PYTEST_ARGS=-v -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON + -DPYTHON_EXECUTABLE=${{ env.PYTHON_EXE }} ${{ inputs.cmake-args }} - name: Build diff --git a/CMakeLists.txt b/CMakeLists.txt index bca0c22dc0..584f0f6a45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,16 @@ if(PYBIND11_MASTER_PROJECT) set(Python_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.venv") endif() endif() + + # Python_ROOT_DIR is only a hint; a newer Python elsewhere on the system + # still wins the version scan, so pin the venv's interpreter directly. + if(DEFINED Python_ROOT_DIR AND NOT DEFINED Python_EXECUTABLE) + if(WIN32 AND EXISTS "${Python_ROOT_DIR}/Scripts/python.exe") + set(Python_EXECUTABLE "${Python_ROOT_DIR}/Scripts/python.exe") + elseif(EXISTS "${Python_ROOT_DIR}/bin/python") + set(Python_EXECUTABLE "${Python_ROOT_DIR}/bin/python") + endif() + endif() endif() set(PYBIND11_HEADERS From 5db58f48a2bc027e6971a6904097397edc600f3f Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 24 Jul 2026 01:07:21 -0400 Subject: [PATCH 2/3] ci: use setup-python's python-path output instead of a locate step Assisted-by: ClaudeCode:claude-fable-5 --- .github/workflows/reusable-standard.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/reusable-standard.yml b/.github/workflows/reusable-standard.yml index 3e4bfa3dce..8739763959 100644 --- a/.github/workflows/reusable-standard.yml +++ b/.github/workflows/reusable-standard.yml @@ -34,6 +34,7 @@ jobs: - uses: actions/checkout@v7 - name: Setup Python ${{ inputs.python-version }} + id: python uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version }} @@ -69,10 +70,6 @@ jobs: # FindPython's version scan can pick a different interpreter (e.g. # Homebrew's 3.14 instead of setup-python's 3.14t), so pin it. - - name: Locate Python for CMake - shell: bash - run: echo "PYTHON_EXE=$(python -c 'import sys, pathlib; print(pathlib.Path(sys.executable).as_posix())')" >> "$GITHUB_ENV" - - name: Configure run: > cmake -S. -Bbuild -Werror=dev @@ -80,7 +77,7 @@ jobs: -DPYBIND11_PYTEST_ARGS=-v -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON - -DPYTHON_EXECUTABLE=${{ env.PYTHON_EXE }} + -DPYTHON_EXECUTABLE=${{ steps.python.outputs.python-path }} ${{ inputs.cmake-args }} - name: Build From 00c4c2bf7a72b0a66f6e355379e05b61f171ed0e Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 24 Jul 2026 09:34:08 -0400 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Ralf W. Grosse-Kunstleve --- .github/workflows/reusable-standard.yml | 5 +++-- CMakeLists.txt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable-standard.yml b/.github/workflows/reusable-standard.yml index 8739763959..6081f801eb 100644 --- a/.github/workflows/reusable-standard.yml +++ b/.github/workflows/reusable-standard.yml @@ -68,8 +68,9 @@ jobs: if: runner.os != 'Windows' run: echo "CMAKE_GENERATOR=Ninja" >> "$GITHUB_ENV" - # FindPython's version scan can pick a different interpreter (e.g. - # Homebrew's 3.14 instead of setup-python's 3.14t), so pin it. + # Pass setup-python's resolved interpreter path to CMake so FindPython + # does not select a different interpreter (e.g. Homebrew's 3.14 instead + # of setup-python's 3.14t). - name: Configure run: > cmake -S. -Bbuild -Werror=dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 584f0f6a45..ddafecd7b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,8 +178,9 @@ if(PYBIND11_MASTER_PROJECT) endif() endif() - # Python_ROOT_DIR is only a hint; a newer Python elsewhere on the system - # still wins the version scan, so pin the venv's interpreter directly. + # Python_ROOT_DIR is only a search hint, so FindPython may select a newer + # Python elsewhere. Set Python_EXECUTABLE to the venv's interpreter path + # to bypass interpreter discovery. if(DEFINED Python_ROOT_DIR AND NOT DEFINED Python_EXECUTABLE) if(WIN32 AND EXISTS "${Python_ROOT_DIR}/Scripts/python.exe") set(Python_EXECUTABLE "${Python_ROOT_DIR}/Scripts/python.exe")