Compare commits

...

72 Commits

Author SHA1 Message Date
Michał
f8b1d7ae09
pyenv-exec: add the --environment option for programs that embed libpython without a path (#3537)
---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: native-api <vano@mail.mipt.ru>
2026-10-02 11:17:30 +03:00
Ayush
6ff25c51d3
pyenv-binary: allow local definitions to override published packages (#3577) 2026-10-02 05:19:21 +03:00
Ivan Pozdeev
42c75f3c53 2.8.7 2026-10-01 09:22:36 +03:00
pyenv-bot[bot]
e258d55f1f
Add CPython 3.10.22, 3.11.17 (#3576)
Co-authored-by: native-api <2670332+native-api@users.noreply.github.com>
2026-10-01 09:18:55 +03:00
pyenv-bot[bot]
627e0aa921
Add CPython 3.14.8 (#3574)
---------

Co-authored-by: native-api <2670332+native-api@users.noreply.github.com>
Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-10-01 07:41:27 +03:00
pyenv-bot[bot]
3d51eb919b
Add CPython 3.12.15, 3.13.16 (#3575)
Co-authored-by: native-api <2670332+native-api@users.noreply.github.com>
2026-10-01 06:11:20 +03:00
Ayush
2e3d62a129
tests: python-buid: use helpers from core (#3572) 2026-09-30 06:28:46 +03:00
Zhaoqi Xu
699e27fb27
init: honor custom PYENV_ROOT in init setup tips (#3569) 2026-09-29 02:41:17 +03:00
native-api
d9b158620e
Speed up permission fix step (#3571)
Saves several seconds for large installations like Anaconda
2026-09-29 01:11:44 +03:00
Ivan Pozdeev
bb15db59a4 graalpython: make python* symlinks 2026-09-28 13:06:24 +03:00
Ivan Pozdeev
60bfb906e1 Use new fixture 2026-09-28 13:04:27 +03:00
exurd
2439bee2c5
Add PyPy v8.0.0 (#3552)
* remove OpenSSL source build
PyPy searches dependencies with pkg-config which XCode CLT do not ship, so it cannot build without Homebrew or MacPorts anyway
* Use Homebrew/MacPorts OpenSSL

---------

Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-09-28 02:01:44 +03:00
exurd
ab74141ab4
Fix minimum macOS version check for PyPy v7.3.8+ (#3570)
* Switch pypy*-7.3.8-aarch64 to -portable
Regular version is no longer available for download

---------

Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-09-27 12:11:20 +03:00
native-api
e9334284e1
Merge pull request #3561 from n0tl3ss/fix/python-build-download-progress
python-build: show download progress in interactive terminals
2026-09-27 11:31:14 +03:00
Nemanja Mikic
8339b9b033 python-build: show download progress in interactive terminals
---
Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-09-27 11:00:13 +03:00
Ivan Pozdeev
67dbc6e930 stub: support ** to match any number of arguments 2026-09-27 10:59:03 +03:00
Ayush
513364609d
pyenv-binary: install published CPython packages (#3567) 2026-09-25 23:45:13 +03:00
exurd
3d1dda120b
python-build: Add add_pypy.py for pypy versions (#3566)
* python-build: add `add_pypy.py` for pypy versions

couldn't help myself ;P

python-build; add_pypy.py: ensure ensurepip is correct

python-build; add_pypy.py: check file extension

python-build; add_pypy.py: update os x version check to 10.15

python-build; add_pypy.py: remove outdated comment

python-build; add_pypy.py: cleanup comment

* Update add_pypy.py

* Remove comments irrelevant to reading the code
2026-09-25 10:13:34 +03:00
exurd
5434a7e3e9
Add PyPy v7.3.21 (#3564)
---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-09-25 02:19:33 +03:00
native-api
49cc565e1c
Merge pull request #3553 from exurd/pr/pypy-v7.3.23
Add PyPy v7.3.23
2026-09-24 14:20:14 +03:00
Ivan Pozdeev
a55c9df84d CI: install gdbm as part of prerequisites 2026-09-24 12:19:13 +03:00
Ivan Pozdeev
08021a03ab python-build: Support automatically picking PyPy as bootstrap version 2026-09-24 12:18:57 +03:00
exurd
9ac7b27486 Add PyPy v7.3.23 2026-09-24 12:04:24 +03:00
native-api
df5372511c
python-build: create pypy* symlinks for PyPy (#3562)
Source and some older versions builds do not create them
2026-09-24 07:23:52 +03:00
native-api
a3c666e177
install-prerequisites: add an option for optional dependencies (#3560) 2026-09-24 00:12:25 +03:00
native-api
26370b7f24
python-build: create PEP 394 symlinks for PyPy (#3559) 2026-09-23 13:34:23 +03:00
Michael Šimáček
beb4f2ffd2
Add GraalPy 3.13 25.4.4 (#3558) 2026-09-23 09:50:21 +03:00
David Lawson
4eea9b7848
python-build: create PEP 394 symlinks for Pyston (#3557)
* Consolidate build_package_pyston2_2 into build_package_pyston
There's no longer a difference

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-09-23 09:49:52 +03:00
Ayush
249f8d888e
CI: publish Apple Silicon macOS binaries (#3556)
* pyenv-binary: relocate macOS text paths
* CI: publish Apple Silicon macOS binaries
* pyenv-binary: preserve unrelated bytecode
* CI: stabilize macOS binary package names
2026-09-22 01:12:32 +03:00
Mingyang Wu
7db7714ff7
Fix rehash repair of individually corrupted shims (#3540) 2026-09-21 13:02:14 +03:00
Ivan Pozdeev
3787bacc91 2.8.6 2026-09-17 10:06:03 +03:00
Ivan Pozdeev
c3550235e4 README: document XCode 27 downstream patches 2026-09-17 08:23:37 +03:00
13steinj
7d55c1a7d9
Add miniconda3 26.7.1-0, 26.7.1-1 and miniforge3 26.5.3-0, 26.7.2-0 (#3550)
Adds latest miniconda releases 26.7.1-0, 26.7.1-1 for Python 3.10–3.14
and miniforge releases 26.5.3-0, 26.7.2-0.

Updates Python verification to 3.14 for miniforge3 starting with
26.5.3-0 and adds Linux riscv64 detection for 26.7.2-0.

Ref: https://github.com/conda-forge/miniforge/releases/tag/26.5.3-0
Ref: https://github.com/conda-forge/miniforge/releases/tag/26.7.2-0
Ref: https://www.anaconda.com/docs/getting-started/miniconda/release-notes
2026-09-17 08:20:51 +03:00
native-api
a99ef7fc4e
Backport XCode 27 support to 3.10 (#3549)
Adapted 3.11 downstream patch
2026-09-17 08:20:22 +03:00
native-api
f17a6499b0
Backport XCode 27 support to 3.11 (#3548)
Adapted 3.12 downstream patch
2026-09-17 04:58:50 +03:00
Ivan Pozdeev
36b89575a5 Merge branch 'master' of https://github.com/pyenv/pyenv 2026-09-17 04:47:16 +03:00
Ivan Pozdeev
733afbc04b Add a patch backport script 2026-09-17 04:47:05 +03:00
native-api
3d66ee1fdb
Backport XCode 27 support to 3.12 (#3547)
* Adapted upstream fix (3.13.15): e86913423b
and dependency patch (3.13.14): 7d265b6013
2026-09-17 02:33:37 +03:00
native-api
6c97017989
Backport XCode 27 support to 3.13 (#3546)
* Upstream fix (3.13.15): e86913423b
* Dependency patch (3.13.14): 7d265b6013
2026-09-17 02:31:45 +03:00
native-api
8bd6b02444
Backport XCode 27 support to 3.14 (#3545)
* Upstream fix (3.14.7): 51f6e01941
* Dependency patch (3.14.6): e29411d405

* Test on XCode 27
2026-09-16 20:39:57 +03:00
Ayush
676b71e7b5
pyenv-binary: use xz compression for archives (#3543) 2026-09-15 02:24:23 +03:00
Mingyang Wu
5d43b9a39d
python-build: honor explicitly configured OpenSSL on macOS (#3541)
* python-build: probe OpenSSL from standard dependency discovery

Assisted-by: OpenAI Codex
Signed-off-by: Mingyang Wu <129849514+aprylewu@users.noreply.github.com>
2026-09-15 02:20:52 +03:00
Ayush
eb36c1b1e8
CI: publish Ubuntu binary packages (#3539)
* CI: Add Ubuntu binary publishing workflow
2026-09-11 15:21:26 +03:00
native-api
ef4905cd81
Incorporate the pyenv-link plugin (#3538)
for use in linking binary installations
2026-09-09 02:43:22 +03:00
Ivan Pozdeev
88e9ab13e8 pwsh: Fix error in shell integration if pyenv is on PATH multiple times
Fixes "The term 'pyenv pyenv' is not recognized..."
2026-09-09 02:31:49 +03:00
macayu17
798a1ad603 Incorporate the pyenv-link plugin
* Adapt test_helper for use in plugins
* Add pyenv-link tests
* Add pyenv-link tests to CI
2026-09-09 02:30:53 +03:00
macayu17
fb7f2071fb Add 'plugins/pyenv-link/' from commit '2f8cb2cf1f093e955a72babf0b65a07f84f33522'
git-subtree-dir: plugins/pyenv-link
git-subtree-mainline: ef7a9f5d1417c4ef09d206298f8ec7a284994072
git-subtree-split: 2f8cb2cf1f093e955a72babf0b65a07f84f33522
2026-09-08 02:55:49 +05:30
Michael Newman
ef7a9f5d14
docs: Add link to list of available Python distributions (#3535)
Add a link to the python-build share directory in the intro section
so users can see which Python distributions are supported before
installing pyenv.
2026-09-06 22:14:47 +03:00
Ayush
265b0dcefa
python-build: add build prerequisite installer (#3532) 2026-09-02 17:56:35 +03:00
Michael Šimáček
2548d53706
Update graalpy URLs for 25.3.4.1 (#3533) 2026-09-02 14:47:33 +03:00
Ivan Pozdeev
c293de3650 2.8.5 2026-09-01 18:05:40 +03:00
Ayush
bdfc6b03f3
pyenv-binary: support relocating macOS archives (#3528) 2026-09-01 18:01:23 +03:00
pyenv-bot[bot]
8c46508bd0
Add CPython 3.15.0rc2 (#3530)
Co-authored-by: native-api <2670332+native-api@users.noreply.github.com>
2026-09-01 17:53:59 +03:00
Michael Šimáček
a00e0bc475
Add GraalPy 25.3.4.1 (#3529) 2026-08-31 23:28:40 +03:00
Michael Newman
981559003f
Fix typo 2026-08-29 15:01:30 +03:00
Michael Newman
4733cca31b
Fix typo 2026-08-28 15:36:28 +03:00
native-api
ef2fb22235
Merge pull request #3522 from sujeito-operator/ci-test-everywhere-on-build-logic-change
CI: test on all runners when the build logic changes
2026-08-26 16:05:18 +03:00
sujeito-operator
97900a4aa4 CI: test on all runners when the build logic changes
Co-Authored-By: Ivan Pozdeev <vano@mail.mipt.ru>
2026-08-26 10:09:25 +03:00
sujeito-operator
ecf9a7f9e6 CI: collapse macos_build and ubuntu_build into a single job
Co-Authored-By: Ivan Pozdeev <vano@mail.mipt.ru>
2026-08-26 09:40:01 +03:00
native-api
495550afc8
Merge pull request #3525 from native-api/test_improvements
Test improvements
2026-08-26 06:00:53 +03:00
Ivan Pozdeev
57f1df294b tests: add file names to TAP output
by using a customized formatter
2026-08-26 05:51:24 +03:00
Ivan Pozdeev
14830b18bf tests: skip permission tests if permission bits are being overridden
e.g. if running as root in a docker container
2026-08-26 05:50:04 +03:00
Ivan Pozdeev
032e7af407 tests: consolidate shims tests 2026-08-26 05:49:17 +03:00
native-api
b0cff001ff
tests: Fix "cd: null directory" in OpenSUSE (#3524)
A workaround because tests don't use the Pyenv launcher and setting PYENV_DIR to $PWD at every run invocation is too cumbersome.
2026-08-25 22:43:59 +03:00
Michael Newman
234a87e400
Fix typo 2026-08-17 01:51:28 +03:00
Ayush
50fbc8c6cc
pyenv-binary: record direct system dependencies in Linux/FreeBSD (#3520) 2026-08-15 22:47:27 +03:00
Mészáros Máté Róbert
2f8cb2cf1f
Handle osx specific ln option name (#1)
On OSX `ln` does not have `--symbolic` only `-s`.

* bin/pyenv-link-version

---------

Co-authored-by: yfprojects <62463991+real-yfprojects@users.noreply.github.com>
2023-07-07 14:18:02 +00:00
real-yfprojects
b8d8dee191
Fix output
* bin/pyenv-link-version
2023-06-06 16:59:25 +02:00
real-yfprojects
ba9099392a
Fix completions
* bin/pyenv-link
2023-06-06 16:56:16 +02:00
real-yfprojects
d428be59ec
Write README.
* README.md
2023-06-06 16:45:22 +02:00
real-yfprojects
dffc750fa2
Initial implementation
* bin/pyenv-link

* bin/pyenv-link-version
2023-06-06 16:22:52 +02:00
yfprojects
f46b669f1d
Initial commit 2023-06-06 11:09:59 +00:00
265 changed files with 24947 additions and 467 deletions

44
.github/actions/build-python/action.yml vendored Normal file
View File

@ -0,0 +1,44 @@
name: Build a Python version
description: >
Install python-build's system dependencies for the current runner's OS, build
and check the requested version.
inputs:
python-version:
description: A version as accepted by `pyenv install`.
required: true
runs:
using: composite
steps:
- shell: bash
run: |
#envvars
export PYENV_ROOT="$GITHUB_WORKSPACE"
echo "PYENV_ROOT=$PYENV_ROOT" >> $GITHUB_ENV
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
# The two OSes differ only in this step.
- if: runner.os == 'macOS'
shell: bash
run: |
#prerequisites
brew install openssl readline sqlite3 xz tcl-tk@8 libb2 zstd gdbm
- if: runner.os == 'Linux'
shell: bash
run: |
#prerequisites
pyenv install-prerequisites --all
- shell: bash
run: |
#build
pyenv --debug install ${{ inputs.python-version }} && rc=$? || rc=$?
if [[ $rc -ne 0 ]]; then echo config.log:; cat "${TMPDIR:-/tmp}"/python-build*/*/config.log; false; fi
pyenv global ${{ inputs.python-version }}
pyenv rehash
- shell: bash
run: |
#print version
python --version
python -m pip --version
- shell: python # Prove that actual Python == expected Python
env:
EXPECTED_PYTHON: ${{ inputs.python-version }}
run: import os, sys ; assert sys.version.startswith(os.getenv("EXPECTED_PYTHON"))

62
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,62 @@
name: build
on:
push:
branches: [master]
pull_request: {}
permissions:
contents: read
jobs:
discover_build_logic_change:
if: github.event_name == 'pull_request'
runs-on: ubuntu-slim
env:
FULL_OS_MATRIX: '[
"macos-14",
"macos-15",
"macos-15-intel",
"macos-26",
"macos-26-intel",
"ubuntu-22.04",
"ubuntu-22.04-arm",
"ubuntu-24.04",
"ubuntu-24.04-arm"
]'
outputs:
os: ${{ steps.detect.outputs.os }}
steps:
- uses: actions/checkout@v7
- run: git fetch origin "$GITHUB_BASE_REF"
- id: detect
shell: bash
run: |
if [[ -n $(git diff --name-only "origin/$GITHUB_BASE_REF" -- \
plugins/python-build/bin/python-build \
.github/actions/build-python/action.yml \
.github/workflows/build.yml) ]]
then
printf "%s\n" "os<<!" "$FULL_OS_MATRIX" "!" >> "$GITHUB_OUTPUT"
fi
build:
needs: discover_build_logic_change
# Run when the detection job succeeded *or was skipped* -- but not failed
if: ${{ !cancelled() && !failure() }}
strategy:
fail-fast: false
matrix:
os: ${{ fromJson(needs.discover_build_logic_change.outputs.os || '["macos-latest","ubuntu-latest"]') }}
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/build-python
with:
python-version: ${{ matrix.python-version }}

View File

@ -1,43 +0,0 @@
name: macos_build
on:
push:
branches: [master]
pull_request: {}
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
macos_build:
strategy:
fail-fast: false
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
runs-on: macos-latest
steps:
- uses: actions/checkout@v7
- run: |
brew install openssl readline sqlite3 xz tcl-tk@8 libb2 zstd
- run: |
#envvars
export PYENV_ROOT="$GITHUB_WORKSPACE"
echo "PYENV_ROOT=$PYENV_ROOT" >> $GITHUB_ENV
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
- run: |
#build
pyenv --debug install ${{ matrix.python-version }} && rc=$? || rc=$?
if [[ $rc -ne 0 ]]; then echo config.log:; cat $TMPDIR/python-build*/*/config.log; false; fi
pyenv global ${{ matrix.python-version }}
- run: |
#print version
python --version
python -m pip --version
- shell: python # Prove that actual Python == expected Python
env:
EXPECTED_PYTHON: ${{ matrix.python-version }}
run: import os, sys ; assert sys.version.startswith(os.getenv("EXPECTED_PYTHON"))

View File

@ -96,6 +96,7 @@ jobs:
- macos-15-intel
- macos-26
- macos-26-intel
- xcode-27
exclude: ${{fromJson(needs.discover_modified_scripts.outputs.versions_macos_build_exclude)}}
runs-on: ${{ matrix.os }}
steps:
@ -107,7 +108,7 @@ jobs:
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
- run: |
#prerequisites
brew install openssl readline sqlite3 xz tcl-tk@8 libb2 zstd
brew install openssl readline sqlite3 xz tcl-tk@8 libb2 zstd gdbm
if [[ "${{ matrix.python-version }}" =~ pypy.*-(src|dev) ]]; then
export PYENV_BOOTSTRAP_VERSION=pypy2.7-7
echo "PYENV_BOOTSTRAP_VERSION=$PYENV_BOOTSTRAP_VERSION" >> $GITHUB_ENV
@ -164,6 +165,7 @@ jobs:
- macos-15-intel
- macos-26
- macos-26-intel
- xcode-27
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
@ -220,10 +222,7 @@ jobs:
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
- run: |
#prerequisites
sudo apt-get update -q; sudo apt-get install -yq make build-essential \
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev
pyenv install-prerequisites --all
if [[ "${{ matrix.python-version }}" =~ pypy.*-(src|dev) ]]; then
export PYENV_BOOTSTRAP_VERSION=pypy2.7-7
echo "PYENV_BOOTSTRAP_VERSION=$PYENV_BOOTSTRAP_VERSION" >> $GITHUB_ENV
@ -283,10 +282,7 @@ jobs:
echo "_PYTHON_BUILD_FORCE_SKIP_XZ=1" >> $GITHUB_ENV
- run: |
#prerequisites
sudo apt-get update -q; sudo apt-get install -yq make build-essential \
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
curl libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev
pyenv install-prerequisites
- run: |
#build
pyenv --debug install ${{ matrix.python-version }} && rc=$? || rc=$?

86
.github/workflows/publish_binary.yml vendored Normal file
View File

@ -0,0 +1,86 @@
name: Publish a binary package
on:
workflow_dispatch:
inputs:
version:
description: A CPython version accepted by `pyenv install`
required: true
type: string
platform:
description: Platform to build on
required: true
type: choice
default: ubuntu-24.04
options:
- ubuntu-24.04
- macos-15
permissions:
contents: read
jobs:
publish:
runs-on: ${{ inputs.platform }}
env:
PYENV_ROOT: ${{ github.workspace }}
VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@v7
- name: Install Ubuntu build prerequisites
if: runner.os == 'Linux'
run: ./bin/pyenv install-prerequisites
- name: Install macOS build prerequisites
if: runner.os == 'macOS'
run: brew install openssl readline sqlite3 xz tcl-tk@8 libb2 zstd
- name: Build package
env:
PYTHON_CONFIGURE_OPTS: --enable-optimizations
run: |
VERSION="${VERSION%%:*}"
if [ "$RUNNER_OS" = "macOS" ]; then
entry="${VERSION}-${{ inputs.platform }}-$(uname -m)"
else
entry="$(./bin/pyenv binary package-name "$VERSION")"
fi
echo "entry=$entry" >> "$GITHUB_ENV"
mkdir dist
cd dist
"$GITHUB_WORKSPACE/bin/pyenv" binary package --verbose \
"$VERSION:$entry" \
--archive-base-url https://pyenv.github.io/pythons/binaries
- name: Generate GitHub token
uses: actions/create-github-app-token@v3
id: generate-token
with:
app-id: ${{ vars.PYENV_BOT_APP_ID }}
private-key: ${{ secrets.PYENV_BOT_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: pyenv.github.io
permission-contents: write
permission-pull-requests: write
- uses: actions/checkout@v7
with:
repository: pyenv/pyenv.github.io
token: ${{ steps.generate-token.outputs.token }}
path: site
- name: Update downloads
run: |
mkdir -p site/pythons/binaries
cp "dist/$entry.tar.xz" "dist/$entry.meta" "dist/$entry" \
site/pythons/binaries/
cd site/pythons
./update.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
with:
path: site
branch: auto_add_binary/${{ env.entry }}
title: Add CPython ${{ env.entry }}
commit-message: Add CPython ${{ env.entry }}
body: |
Built from pyenv/pyenv@${{ github.sha }} with profile-guided optimization enabled.
Part of pyenv/pyenv#2334.
token: ${{ steps.generate-token.outputs.token }}

View File

@ -1,43 +0,0 @@
name: ubuntu_build
on:
push:
branches: [master]
pull_request: {}
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
ubuntu_build:
strategy:
fail-fast: false
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- run: |
sudo apt-get update -q; sudo apt install -yq make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
# https://github.com/pyenv/pyenv#installation
- run: pwd
- env:
PYENV_ROOT: /home/runner/work/pyenv/pyenv
run: |
echo $PYENV_ROOT
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
bin/pyenv --debug install ${{ matrix.python-version }}
bin/pyenv global ${{ matrix.python-version }}
bin/pyenv rehash
- run: python --version
- run: python -m pip --version
- shell: python # Prove that actual Python == expected Python
env:
EXPECTED_PYTHON: ${{ matrix.python-version }}
run: import os, sys ; assert sys.version.startswith(os.getenv("EXPECTED_PYTHON"))

View File

@ -1,5 +1,52 @@
# Version History
## Release v2.8.7
* Fix rehash repair of individually corrupted shims by @aprylewu in https://github.com/pyenv/pyenv/pull/3540
* CI: publish Apple Silicon macOS binaries by @macayu17 in https://github.com/pyenv/pyenv/pull/3556
* python-build: create PEP 394 symlinks for Pyston by @dmrlawson in https://github.com/pyenv/pyenv/pull/3557
* Add GraalPy 3.13 25.4.4 by @msimacek in https://github.com/pyenv/pyenv/pull/3558
* python-build: create PEP 394 symlinks for PyPy by @native-api in https://github.com/pyenv/pyenv/pull/3559
* install-prerequisites: add an option for optional dependencies by @native-api in https://github.com/pyenv/pyenv/pull/3560
* python-build: create pypy* symlinks for PyPy by @native-api in https://github.com/pyenv/pyenv/pull/3562
* Add PyPy v7.3.23 by @exurd in https://github.com/pyenv/pyenv/pull/3553
* Add PyPy v7.3.21 by @exurd in https://github.com/pyenv/pyenv/pull/3564
* python-build: Add `add_pypy.py` for pypy versions by @exurd in https://github.com/pyenv/pyenv/pull/3566
* pyenv-binary: install published CPython packages by @macayu17 in https://github.com/pyenv/pyenv/pull/3567
* python-build: show download progress in interactive terminals by @n0tl3ss in https://github.com/pyenv/pyenv/pull/3561
* Fix minimum macOS version check for PyPy v7.3.8+ by @exurd in https://github.com/pyenv/pyenv/pull/3570
* Add PyPy v8.0.0 by @exurd in https://github.com/pyenv/pyenv/pull/3552
* python-build: Speed up permission fix step by @native-api in https://github.com/pyenv/pyenv/pull/3571
* fix(init): honor custom PYENV_ROOT in init setup tips by @r3wretrhy in https://github.com/pyenv/pyenv/pull/3569
* tests: python-build: use helpers from core by @macayu17 in https://github.com/pyenv/pyenv/pull/3572
* Add CPython 3.12.15, 3.13.16 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3575
* Add CPython 3.14.8 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3574
* Add CPython 3.10.22, 3.11.17 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3576
## Release v2.8.6
* Update graalpy URLs for 25.3.4.1 by @msimacek in https://github.com/pyenv/pyenv/pull/3533
* python-build: add build prerequisite installer by @macayu17 in https://github.com/pyenv/pyenv/pull/3532
* docs: Add link to list of available Python distributions by @michaelbnewman in https://github.com/pyenv/pyenv/pull/3535
* Incorporate the `pyenv-link` plugin by @macayu17 in https://github.com/pyenv/pyenv/pull/3538
* CI: publish Ubuntu binary packages by @macayu17 in https://github.com/pyenv/pyenv/pull/3539
* python-build: honor explicitly configured OpenSSL on macOS by @aprylewu in https://github.com/pyenv/pyenv/pull/3541
* pyenv-binary: use xz compression for archives by @macayu17 in https://github.com/pyenv/pyenv/pull/3543
* Backport XCode 27 support to 3.14 by @native-api in https://github.com/pyenv/pyenv/pull/3545
* Backport XCode 27 support to 3.13; add missing 3.13.11t by @native-api in https://github.com/pyenv/pyenv/pull/3546
* Backport XCode 27 support to 3.12 by @native-api in https://github.com/pyenv/pyenv/pull/3547
* Backport XCode 27 support to 3.11 by @native-api in https://github.com/pyenv/pyenv/pull/3548
* Backport XCode 27 support to 3.10 by @native-api in https://github.com/pyenv/pyenv/pull/3549
* Add miniconda3 26.7.1-0, 26.7.1-1 and miniforge3 26.5.3-0, 26.7.2-0 by @13steinj in https://github.com/pyenv/pyenv/pull/3550
## Release v2.8.5
* pyenv-binary: record direct system dependencies in Linux/FreeBSD by @macayu17 in https://github.com/pyenv/pyenv/pull/3520
* tests: Fix "cd: null directory" in OpenSUSE by @native-api in https://github.com/pyenv/pyenv/pull/3524
* Test improvements by @native-api in https://github.com/pyenv/pyenv/pull/3525
* CI: test on all runners when the build logic changes by @sujeito-operator in https://github.com/pyenv/pyenv/pull/3522
* Add GraalPy 25.3.4.1 by @msimacek in https://github.com/pyenv/pyenv/pull/3529
* Add CPython 3.15.0rc2 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3530
* pyenv-binary: support relocating macOS archives by @macayu17 in https://github.com/pyenv/pyenv/pull/3528
## Release v2.8.4
* CI: Add macos_26_intel by @native-api in https://github.com/pyenv/pyenv/pull/3514
* pyenv-binary: check FreeBSD system libraries by @macayu17 in https://github.com/pyenv/pyenv/pull/3511

View File

@ -315,7 +315,7 @@ Lists all Python versions with the given command installed.
## `pyenv exec`
Usage: pyenv exec <command> [arg1 arg2...]
Usage: pyenv exec [-N|--environment] <command> [arg1 arg2...]
Runs an executable by first preparing PATH so that the selected Python
version's `bin` directory is at the front.
@ -326,7 +326,18 @@ For example, if the currently selected Python version is 3.9.7:
is equivalent to:
PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
PYENV_VERSION="3.9.7" PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
The `--environment` option sets `PYTHONHOME` and `LD_LIBRARY_PATH` (`DYLD_LIBRARY_PATH` in macOS) in the program's environment.
This is needed to run programs that embed Python by loading `libpython` without specifying rpath or an explicit path.
This breaks linking for programs that expect to link to a different `libpython` with the same name as one
in selected Python -- thus it's not done by default.
In macOS, System Integrity Protection (SIP) removes `DYLD_LIBRARY_PATH` from a process' environment
upon `exec` (not `fork`) if the executable being run is protected. The protection covers preinstalled system software
(including preinstalled shells) and does not cover user-installed apps and 3rd-party software. See
[About System Integrity Protection on your Mac - Apple Support](https://support.apple.com/en-us/102149)
for details.
## `pyenv root`

View File

@ -10,11 +10,14 @@ TEST_PYTHON_BUILD_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuf
TEST_BINARY_DOCKER_PREFIX = test-binary-docker
TEST_BINARY_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_BINARY_DOCKER_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_BINARY_DOCKER_PREFIX)))
TEST_LINK_DOCKER_PREFIX = test-link-docker
TEST_LINK_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_LINK_DOCKER_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_LINK_DOCKER_PREFIX)))
TEST_BATS_IMAGE_PREFIX = test-pyenv-docker-image
TEST_BATS_IMAGE_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_BATS_IMAGE_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_BATS_IMAGE_PREFIX)))
.PHONY: test-docker
test-docker: $(TEST_UNIT_DOCKER_PREFIX) $(TEST_PYTHON_BUILD_DOCKER_PREFIX) $(TEST_BINARY_DOCKER_PREFIX)
test-docker: $(TEST_UNIT_DOCKER_PREFIX) $(TEST_PYTHON_BUILD_DOCKER_PREFIX) $(TEST_BINARY_DOCKER_PREFIX) $(TEST_LINK_DOCKER_PREFIX)
.PHONY: $(TEST_UNIT_DOCKER_PREFIX)
$(TEST_UNIT_DOCKER_PREFIX): $(TEST_UNIT_DOCKER_TARGETS)
@ -62,7 +65,8 @@ $(TEST_PYTHON_BUILD_DOCKER_TARGETS): $(TEST_PYTHON_BUILD_DOCKER_PREFIX)-% : $(TE
$${CI+-e CI="$${CI}"} \
$(INTERACTIVE) \
$(DOCKER_IMAGE):$(DOCKER_TAG) \
bats $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/python-build/test/$${BATS_FILE_FILTER}
bats $${CI:+-F "/code/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/python-build/test/$${BATS_FILE_FILTER}
.PHONY: $(TEST_BINARY_DOCKER_PREFIX)
$(TEST_BINARY_DOCKER_PREFIX): $(TEST_BINARY_DOCKER_TARGETS)
@ -84,7 +88,31 @@ $(TEST_BINARY_DOCKER_TARGETS): $(TEST_BINARY_DOCKER_PREFIX)-% : $(TEST_BATS_IMAG
$${CI+-e CI="$${CI}"} \
$(INTERACTIVE) \
$(DOCKER_IMAGE):$(DOCKER_TAG) \
bats $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/pyenv-binary/test/$${BATS_FILE_FILTER}
bats $${CI:+-F "/code/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/pyenv-binary/test/$${BATS_FILE_FILTER}
.PHONY: $(TEST_LINK_DOCKER_PREFIX)
$(TEST_LINK_DOCKER_PREFIX): $(TEST_LINK_DOCKER_TARGETS)
.PHONY: $(TEST_LINK_DOCKER_TARGETS)
$(TEST_LINK_DOCKER_TARGETS): DOCKER_IMAGE = $(TEST_BATS_IMAGE_PREFIX)
$(TEST_LINK_DOCKER_TARGETS): GNU = $(if $(findstring -gnu-,$@),True,False)
$(TEST_LINK_DOCKER_TARGETS): BASH = $(filter $(TEST_BASH_VERSIONS),$(subst -, ,$@))
$(TEST_LINK_DOCKER_TARGETS): DOCKER_TAG = bash-$(BASH)-gnu-$(GNU)
$(TEST_LINK_DOCKER_TARGETS): INTERACTIVE = $(if $(findstring true,$(CI)),,-ti)
$(TEST_LINK_DOCKER_TARGETS): $(TEST_LINK_DOCKER_PREFIX)-% : $(TEST_BATS_IMAGE_PREFIX)-%
$(info Running test with docker image '$(DOCKER_IMAGE):$(DOCKER_TAG)')
docker run \
--init \
-v $(PWD):/code:ro \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
-u "$$(id -u $$(whoami)):$$(id -g $$(whoami))" \
$${CI+-e CI="$${CI}"} \
$(INTERACTIVE) \
$(DOCKER_IMAGE):$(DOCKER_TAG) \
bats $${CI:+-F "/code/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/pyenv-link/test/$${BATS_FILE_FILTER}
# Build all images needed for bats under docker
.PHONY: $(TEST_BATS_IMAGE_PREFIX)
@ -108,22 +136,28 @@ $(TEST_BATS_IMAGE_TARGETS):
./ ; \
fi
.PHONY: test test-unit test-python-build test-binary
.PHONY: test test-unit test-python-build test-binary test-link
# Do not pass in user flags to build tests.
unexport PYTHON_CFLAGS
unexport PYTHON_CONFIGURE_OPTS
test: test-unit test-python-build test-binary
test: test-unit test-python-build test-binary test-link
test-unit: bats
PATH="./bats/bin:$$PATH" test/run
test-python-build: bats
cd plugins/python-build && $(PWD)/bats/bin/bats $${CI:+--tap} $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER}
cd plugins/python-build && $(PWD)/bats/bin/bats $${CI:+-F "$(PWD)/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER}
test-binary: bats
cd plugins/pyenv-binary && $(PWD)/bats/bin/bats $${CI:+--tap} $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER}
cd plugins/pyenv-binary && $(PWD)/bats/bin/bats $${CI:+-F "$(PWD)/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER}
test-link: bats
cd plugins/pyenv-link && $(PWD)/bats/bin/bats $${CI:+-F "$(PWD)/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER}
.SECONDARY: bats-$(TEST_BATS_VERSION)
bats-$(TEST_BATS_VERSION):

View File

@ -13,6 +13,8 @@ This project was forked from [rbenv](https://github.com/rbenv/rbenv) and
* Lets you **change the global Python version** on a per-user basis.
* Provides support for **per-project Python versions**.
* Supports **multiple Python distributions**: CPython, PyPy, Stackless Python, Jython, and more.
See the [full list of available versions](https://github.com/pyenv/pyenv/tree/master/plugins/python-build/share/python-build).
* Allows you to **override the Python version** with an environment
variable.
* Searches for commands from **multiple versions of Python at a time**.
@ -307,6 +309,7 @@ Though we don't actively maintain those patches, since existing releases never c
it's safe to assume that they will continue working until there are further incompatible changes
in a later version of those environments.
* *3.10.x-3.14.x* : XCode 27
* *3.7.8-3.7.15, 3.8.4-3.8.12, 3.9.0-3.9.7* : XCode 13.3
* *3.5.10, 3.6.15* : MacOS 11+ and XCode 13.3
* *2.7.18* : MacOS 10.15+ and Apple Silicon

View File

@ -12,7 +12,7 @@
set -e
[ -n "$PYENV_DEBUG" ] && set -x
version="2.8.4"
version="2.8.7"
git_revision=""
if cd "${BASH_SOURCE%/*}" 2>/dev/null && git remote -v 2>/dev/null | grep -q pyenv; then

View File

@ -2,7 +2,17 @@
#
# Summary: Run an executable with the selected Python version
#
# Usage: pyenv exec <command> [arg1 arg2...]
# Usage: pyenv exec [-N|--environment] <command> [arg1 arg2...]
#
# -N/--environment Set PYTHONHOME and LD_LIBRARY_PATH (DYLD_LIBRARY_PATH in macOS)
# envvars for the running command.
# This allows to run programs that embed Python without using rpath or
# exact library path to libpython.
# WARNING: For the running command and its child processes, this will
# break linkage for programs that expect to be linked to a different
# libpython instance with the same name!
# WARNING: In macOS, DYLD_LIBRARY_PATH will be unset by the system for
# processes covered by System Integrity Protection.
#
# Runs an executable by first preparing PATH so that the selected Python
# version's `bin' directory is at the front.
@ -18,9 +28,16 @@ set -e
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
echo --environment
exec pyenv-shims --short
fi
unset MODIFY_ENV
if [ "$1" = "-N" ] || [ "$1" = "--environment" ]; then
MODIFY_ENV=true
shift
fi
PYENV_VERSION="$(pyenv-version-name -f)"
PYENV_COMMAND="$1"
@ -54,4 +71,27 @@ if [ "${PYENV_BIN_PATH#${PYENV_ROOT}}" != "${PYENV_BIN_PATH}" ]; then
# Only add to $PATH for non-system version.
export PATH="${PYENV_BIN_PATH}:${PATH}"
fi
if [ -n "$MODIFY_ENV" ]; then
# Check if multiple Python versions are selected
VERSIONS=$(pyenv-prefix)
if [[ "$VERSIONS" == *:* ]]; then
VERSION="${VERSIONS%%:*}"
echo "pyenv: Warning: multiple Python versions are selected." \
"Setting environment variables for the first one, (${VERSION#$PYENV_ROOT})" >&2
else
VERSION="$VERSIONS"
fi
# Assign the correct version of PYTHONHOME
export PYTHONHOME="$VERSION"
case "$(uname -s)" in
Darwin)
export DYLD_LIBRARY_PATH="${PYTHONHOME}/lib${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}"
;;
*)
export LD_LIBRARY_PATH="${PYTHONHOME}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
;;
esac
fi
exec "$PYENV_COMMAND_PATH" "$@"

View File

@ -189,8 +189,76 @@ function help_() {
} >&2
}
# True when tips/install should keep the portable default root form.
function pyenv_root_is_default() {
[[ ${PYENV_ROOT} == "${HOME}/.pyenv" ]]
}
# Escape a value for inclusion inside double quotes in a POSIX shell script.
function escape_for_double_quoted_posix() {
local s="$1"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//\$/\\\$}"
s="${s//\`/\\\`}"
printf '%s' "$s"
}
# Escape a value for inclusion inside double quotes in a fish script.
function escape_for_double_quoted_fish() {
local s="$1"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//\$/\\\$}"
printf '%s' "$s"
}
# Escape a value for inclusion inside single quotes in a PowerShell script.
function escape_for_single_quoted_pwsh() {
local s="$1"
# Bash 3.2 (macOS / CI docker): avoid \' in ${//} replacement —
# it becomes a literal backslash. Double single-quotes via a var instead.
local q="'"
s="${s//${q}/${q}${q}}"
printf '%s' "$s"
}
# Emit the PYENV_ROOT assignment line for tips/--install (posix|fish|pwsh).
# Portable default keeps $HOME / $Env:HOME; custom roots are quoted per target shell.
function print_pyenv_root_assignment() {
case "$1" in
posix )
if pyenv_root_is_default; then
echo 'export PYENV_ROOT="$HOME/.pyenv"'
else
printf 'export PYENV_ROOT="%s"\n' "$(escape_for_double_quoted_posix "${PYENV_ROOT}")"
fi
;;
fish )
if pyenv_root_is_default; then
# Keep master's expandable $HOME form (fish expands unquoted $HOME).
echo 'set -Ux PYENV_ROOT $HOME/.pyenv'
else
printf 'set -Ux PYENV_ROOT "%s"\n' "$(escape_for_double_quoted_fish "${PYENV_ROOT}")"
fi
;;
pwsh )
if pyenv_root_is_default; then
echo '$Env:PYENV_ROOT="$Env:HOME/.pyenv"'
else
# Single-quoted PowerShell literal: no $ / backtick expansion.
printf "\$Env:PYENV_ROOT='%s'\n" "$(escape_for_single_quoted_pwsh "${PYENV_ROOT}")"
fi
;;
* )
echo "pyenv: internal error: unknown shell family for PYENV_ROOT assignment: $1" >&2
return 1
;;
esac
}
function print_posix_shell_setup() {
echo 'export PYENV_ROOT="$HOME/.pyenv"'
print_pyenv_root_assignment posix
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"'
echo 'eval "$(pyenv init - '$shell')"'
}
@ -200,7 +268,7 @@ function print_fish_shell_setup() {
}
function print_fish_user_path_setup() {
echo 'set -Ux PYENV_ROOT $HOME/.pyenv'
print_pyenv_root_assignment fish
echo 'if functions -q fish_add_path'
echo ' test -d $PYENV_ROOT/bin; and fish_add_path $PYENV_ROOT/bin'
echo 'else'
@ -209,7 +277,7 @@ function print_fish_user_path_setup() {
}
function print_pwsh_shell_setup() {
echo '$Env:PYENV_ROOT="$Env:HOME/.pyenv"'
print_pyenv_root_assignment pwsh
echo 'if (Test-Path -LP "$Env:PYENV_ROOT/bin" -PathType Container) {'
echo ' $Env:PATH="$Env:PYENV_ROOT/bin:$Env:PATH" }'
echo 'iex ((pyenv init -) -join "`n")'
@ -473,12 +541,12 @@ function pyenv {
}
if ( ("${commands[*]}" -split ' ') -contains \$command ) {
\$shell_cmds = (& (get-command -commandtype application pyenv) sh-\$command \$args)
\$shell_cmds = (& (get-command -commandtype application pyenv -totalcount 1) sh-\$command \$args)
if ( \$shell_cmds.Count -gt 0 ) {
iex (\$shell_cmds -join "\`n")
}
} else {
& (get-command -commandtype application pyenv) \$command \$args
& (get-command -commandtype application pyenv -totalcount 1) \$command \$args
}
}
EOS

View File

@ -80,10 +80,8 @@ fi
unset tested_for_other_write_errors
# The prototype shim file is a script that re-execs itself, passing
# its filename and any arguments to `pyenv exec`. This file is
# hard-linked for every executable and then removed. The linking
# technique is fast, uses less disk space than unique files, and also
# serves as a locking mechanism.
# its filename and any arguments to `pyenv exec`. This file is copied
# for every executable and then removed. It also serves as a lock.
create_prototype_shim() {
cat > "$PROTOTYPE_SHIM_PATH" <<SH
#!/usr/bin/env bash
@ -100,18 +98,30 @@ fi
exec "$(command -v pyenv)" exec "\$program" "\$@"
SH
chmod +x "$PROTOTYPE_SHIM_PATH"
local LC_ALL=C
IFS= read -r -d '' PROTOTYPE_SHIM_CONTENTS < "$PROTOTYPE_SHIM_PATH" || true
PROTOTYPE_SHIM_READ_SIZE=$((${#PROTOTYPE_SHIM_CONTENTS} + 1))
}
# If the contents of the prototype shim file differ from the contents
# of the first shim in the shims directory, assume pyenv has been
# upgraded and the existing shims need to be removed.
remove_outdated_shims() {
local shim
for shim in "$SHIM_PATH"/*; do
if ! diff "$PROTOTYPE_SHIM_PATH" "$shim" >/dev/null 2>&1; then
rm -f "$SHIM_PATH"/*
# Install a shim when it is first registered, replacing an existing copy
# if it was overwritten. Hooks can then customize it without a later
# registration overwriting their changes.
install_shims() {
local shim file shim_contents
# Count bytes consistently across Bash versions, including multibyte paths.
local LC_ALL=C
for shim; do
file="${SHIM_PATH}/${shim}"
if [[ -f "$file" || ( -L "$file" && ! -e "$file" ) ]]; then
shim_contents=
# Read with a builtin to avoid a subprocess per shim. A successful
# read means a NUL or extra character was found. Limit the read in
# case a large file was accidentally written over a shim.
if IFS= read -r -d '' -n "$PROTOTYPE_SHIM_READ_SIZE" shim_contents 2>/dev/null < "$file" || [[ $shim_contents != "$PROTOTYPE_SHIM_CONTENTS" ]]; then
rm -f "$file"
fi
fi
break
[ -e "$file" ] || cp "$PROTOTYPE_SHIM_PATH" "$file"
done
}
@ -132,7 +142,10 @@ if ((${BASH_VERSINFO[0]} > 3)); then
# Registers the name of a shim to be generated.
register_shim() {
registered_shims["$1"]=1
if [[ ! ${registered_shims["$1"]} ]]; then
install_shims "$1"
registered_shims["$1"]=1
fi
}
# Install all shims registered via `make_shims` or `register_shim` directly.
@ -162,7 +175,10 @@ else # Same for bash < 4.
registered_shims=" "
register_shim() {
registered_shims="${registered_shims}${1} "
if [[ "$registered_shims" != *" ${1} "* ]]; then
install_shims "$1"
registered_shims="${registered_shims}${1} "
fi
}
install_registered_shims() {
@ -188,7 +204,6 @@ shopt -s nullglob
# Create the prototype shim, then register shims for all known
# executables.
create_prototype_shim
remove_outdated_shims
# shellcheck disable=SC2046
make_shims $(pyenv-versions --executables)

View File

@ -11,7 +11,7 @@ find_local_version_file() {
# Nonexistent paths are UB as of this writing.
# Relative ones cause a failure but absolute ones don't
[[ $root != /* ]] && root=$(CDPATH= cd -- "$root" && pwd)
# Original Rbenv code supports UNC notaion for Cygwin/MinGW
# Original Rbenv code supports UNC notation for Cygwin/MinGW
# (https://github.com/rbenv/rbenv/pull/529)
# POSIX.1-2024 still allows to treat //<name> in implementation-specific manner
# (https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html#tag_04_16)
@ -38,7 +38,9 @@ find_local_version_file() {
if [ -n "$target_dir" ]; then
find_local_version_file "$target_dir"
else
find_local_version_file "$PYENV_DIR" || {
# In tests, PYENV_DIR is not set, ultimately leading to "cd: null directory" in OpenSUSE
# While most `cd` implementations treat an empty argument the same as missing, that's still wrong
find_local_version_file "${PYENV_DIR:=$PWD}" || {
[ "$PYENV_DIR" != "$PWD" ] && find_local_version_file "$PWD"
} || echo "${PYENV_ROOT}/version"
fi

1
plugins/.gitignore vendored
View File

@ -3,4 +3,5 @@
!/version-ext-compat
!/python-build
!/pyenv-binary
!/pyenv-link
/python-build/test/build

View File

@ -14,8 +14,30 @@ architecture and a compatible libc) and have the recorded system libraries. It
is not portable across, say, glibc and musl, or to an older glibc; the platform
and dependency metadata exist to catch that.
Installing a binary package requires `tar` with xz support (typically provided
by the `xz` package).
## Commands
### `pyenv binary install <version>`
Installs a matching published package from pyenv.github.io under `<version>`.
The command selects by OS, architecture and distribution; on macOS, an archive
built on an older major release can also be used. Available packages and their
definition checksums are recorded in `share/pyenv-binary/versions`. Add an entry
there when publishing a new package. The definition checks its system-library
requirements when an `ldconfig` cache is available; otherwise, it warns and
proceeds.
```sh
pyenv binary install 3.14.7
```
A definition with the selected package entry's name in a plugin's
`share/python-build` directory overrides the published definition. The normal
Python-Build search order applies, including `PYTHON_BUILD_DEFINITIONS`.
Local definitions are installed without downloading the stock definition.
### `pyenv binary package [-v|--verbose] <version>[:<entry>] --archive-base-url <url>`
Installs `<version>` from source under a separate name, packages that install
@ -29,7 +51,7 @@ Pass `-v` to show build progress from `pyenv install`.
```sh
pyenv binary package 3.12.7 \
--archive-base-url https://example.com/binaries
# On Debian 12 x86_64, writes 3.12.7-debian-12-x86_64.tar.gz,
# On Debian 12 x86_64, writes 3.12.7-debian-12-x86_64.tar.xz,
# its .meta file and a `3.12.7-debian-12-x86_64' definition.
pyenv binary package 3.12.7:company-python \
@ -52,12 +74,13 @@ pyenv binary package-name 3.12.7
# 3.12.7-debian-12-x86_64
```
### `pyenv binary save <version> [<output-dir>] [--name <name>]`
### `pyenv binary save <version> [<output-dir>] [--name <name>] [--source-version <version>]`
Packs an installed version into `<version>-<platform>.tar.gz` (relative paths)
Packs an installed version into `<version>-<platform>.tar.xz` (relative paths)
and writes `<version>-<platform>.meta` describing the build platform (OS, arch,
distro and libc version) and the system libraries the build links against. Use
`--name` to set a different base name for both files.
`--name` to set a different base name for both files. `--source-version` records
the source version when the installed version has a different name.
```sh
pyenv binary save 3.12.7 ./dist
@ -78,17 +101,18 @@ needs are present.
```sh
pyenv binary generate-installer ./dist/3.12.7-linux-x86_64.meta \
--archive-url https://example.com/3.12.7-linux-x86_64.tar.gz \
--archive-url https://example.com/3.12.7-linux-x86_64.tar.xz \
-o "$(pyenv root)/plugins/python-build/share/python-build/3.12.7-linux-x86_64"
pyenv install 3.12.7-linux-x86_64
```
### `pyenv binary relocate <prefix>`
### `pyenv binary relocate <prefix> [<build-prefix>]`
Rewrites the rpaths of a Python tree unpacked into `<prefix>` so the interpreter
and its extension modules load the bundled libraries from there rather than from
the path the archive was built at. Uses `patchelf`. The generated definition
calls this; you rarely run it by hand.
the path the archive was built at. Linux and FreeBSD use `patchelf`; macOS
requires the original `<build-prefix>`. The generated definition calls this;
you rarely run it by hand.
Relocation is implemented for Linux; macOS is not wired up yet.
Relocation is implemented for Linux, FreeBSD and macOS.

View File

@ -14,7 +14,7 @@
# into the definition; `pyenv binary save' writes the two together.
#
# <metadata-file> A .meta file written by `pyenv binary save'.
# The corresponsing binary package written by `pyenv binary save'
# The corresponding binary package written by `pyenv binary save'
# needs to be present alongside it.
# --archive-url <url> The URL for the resulting installation script to download
# the package from.
@ -55,7 +55,7 @@ if [ -z "$metadata" ] || [ -z "$archive_url" ]; then
exit 1
fi
version="" os="" arch="" distro="" libc="" archive=""
version="" os="" arch="" distro="" libc="" build_prefix="" archive=""
deps=""
while IFS='=' read -r key value; do
case "$key" in
@ -64,6 +64,7 @@ while IFS='=' read -r key value; do
arch ) arch="$value" ;;
distro ) distro="$value" ;;
libc ) libc="$value" ;;
build_prefix ) build_prefix="$value" ;;
archive ) archive="$value" ;;
dep ) deps="${deps:+$deps }$value" ;;
esac
@ -78,10 +79,9 @@ for field in version os arch archive; do
fi
done
# macOS relocation needs install_name_tool and a different rpath scheme, so it is
# not supported yet. Other systems relocate with patchelf.
if [ "$os" = "Darwin" ]; then
echo "pyenv-binary: macOS archives are not supported yet" >&2
# Mach-O load commands contain the prefix where Python was built.
if [ "$os" = "Darwin" ] && [ -z "$build_prefix" ]; then
echo "pyenv-binary: metadata is missing \`build_prefix'" >&2
exit 1
fi
@ -122,6 +122,7 @@ emit() {
printf 'EXPECT_OS=%q\n' "$os"
printf 'EXPECT_ARCH=%q\n' "$arch"
printf 'EXPECT_LIBC=%q\n' "$libc"
printf 'BUILD_PREFIX=%q\n' "$build_prefix"
printf 'VERSION=%q\n' "$version"
printf 'ARCHIVE_URL=%q\n' "$archive_url"
printf 'SHA256=%q\n' "$sha256"
@ -185,13 +186,29 @@ elif [ -n "$DEPS" ]; then
echo "pyenv-binary: cannot check required system libraries (ldconfig cache unavailable)" >&2
fi
if ! command -v patchelf >/dev/null 2>&1; then
echo "pyenv-binary: need patchelf to relocate the binary" >&2
exit 1
fi
case "$os" in
Darwin )
for tool in otool install_name_tool; do
if ! command -v "$tool" >/dev/null 2>&1; then
echo "pyenv-binary: need ${tool} to relocate the binary" >&2
exit 1
fi
done
;;
* )
if ! command -v patchelf >/dev/null 2>&1; then
echo "pyenv-binary: need patchelf to relocate the binary" >&2
exit 1
fi
;;
esac
build_package_relocate() {
pyenv binary relocate "$PREFIX_PATH"
if [ "$os" = "Darwin" ]; then
pyenv binary relocate "$PREFIX_PATH" "$BUILD_PREFIX"
else
pyenv binary relocate "$PREFIX_PATH"
fi
}
install_package "Python-${VERSION}-binary" "${ARCHIVE_URL}#${SHA256}" copy relocate

View File

@ -0,0 +1,130 @@
#!/usr/bin/env bash
#
# Summary: Install a published binary package
#
# Usage: pyenv binary install <version>
#
# Selects a compatible package from pyenv.github.io and installs it under
# <version>. Ordinary `pyenv install' is unchanged.
#
set -e
[ -n "$PYENV_DEBUG" ] && set -x
if [ "$1" = "--complete" ]; then
exit
fi
if [ "$#" -ne 1 ]; then
pyenv-help --usage binary-install >&2
exit 1
fi
case "$1" in
*/* | .. | . | *[[:cntrl:]]* )
echo "pyenv-binary: invalid version name \`$1'" >&2
exit 1
;;
esac
requested="$1"
os="$(uname -s)"
arch="$(uname -m)"
case "$os" in
Linux )
if [ -r /etc/os-release ]; then
distro="$(. /etc/os-release && printf '%s %s' "${ID:-}" "${VERSION_ID:-}")"
elif type -p lsb_release >/dev/null; then
distro="$(lsb_release -si) $(lsb_release -sr)"
fi
distro="$(printf '%s' "$distro" | tr '[:upper:]' '[:lower:]')"
;;
Darwin )
distro="macos $(sw_vers -productVersion)"
;;
esac
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
base_url="https://pyenv.github.io/pythons/binaries"
manifest_dir="$(dirname "${BASH_SOURCE[0]}")/../share/pyenv-binary/versions"
case "$requested" in
*.*.* ) manifests=( "$manifest_dir/${requested%.*}" ) ;;
*.* ) manifests=( "$manifest_dir/$requested" ) ;;
* ) manifests=( "$manifest_dir/$requested".* ) ;;
esac
matches="$tmpdir/matches"
: > "$matches"
for manifest in "${manifests[@]}"; do
[ -f "$manifest" ] || continue
while IFS=$'\t' read -r source_version name target_os target_arch target_distro sha256; do
case "$source_version" in
"$requested" | "$requested".* ) ;;
* ) continue ;;
esac
[[ "$source_version" =~ ^[0-9]+(\.[0-9]+){1,2}$ ]] || continue
[ "$target_os" = "$os" ] && [ "$target_arch" = "$arch" ] || continue
case "$name" in
"" | . | .. | *[!A-Za-z0-9._-]* ) continue ;;
esac
case "$os" in
Linux ) [ "$(printf '%s' "$target_distro" | tr '[:upper:]' '[:lower:]')" = "$distro" ] || continue ;;
Darwin )
target_version="${target_distro#macos }"
[ "$target_version" != "$target_distro" ] || continue
host_version="${distro#macos }"
[[ "$target_version" =~ ^[0-9]+(\.[0-9]+){1,2}$ ]] || continue
[[ "$host_version" =~ ^[0-9]+(\.[0-9]+){1,2}$ ]] || continue
IFS=. read -r target_major target_minor target_patch <<< "$target_version"
IFS=. read -r host_major host_minor host_patch <<< "$host_version"
target_patch="${target_patch:-0}"
host_patch="${host_patch:-0}"
[ "$host_major" -ge "$target_major" ] || continue
if [ "$host_major" -eq "$target_major" ]; then
[ "$host_minor" -ge "$target_minor" ] || continue
if [ "$host_minor" -eq "$target_minor" ]; then
[ "$host_patch" -ge "$target_patch" ] || continue
fi
fi
;;
* ) continue ;;
esac
printf '%s\t%s\t%s\n' "$source_version" "$name" "$sha256" >> "$matches"
done < "$manifest"
done
selection="$(sort -t. -k1,1nr -k2,2nr -k3,3nr "$matches" | head -n1)"
IFS=$'\t' read -r version entry expected_sha <<< "$selection"
if [ -z "$entry" ]; then
echo "pyenv-binary: no binary available for $requested on $os/$arch" >&2
exit 1
fi
definitions="$(pyenv-install --list --bare)" || definitions=""
if printf '%s\n' "$definitions" | grep -qxF -- "$entry"; then
pyenv-install "$entry:$version"
exit
fi
if ! [[ "$expected_sha" =~ ^[0-9a-fA-F]{64}$ ]]; then
echo "pyenv-binary: invalid checksum for $entry" >&2
exit 1
fi
expected_sha="$(printf '%s' "$expected_sha" | tr '[:upper:]' '[:lower:]')"
curl -fsSL -o "$tmpdir/$entry" "$base_url/$entry"
if command -v sha256sum >/dev/null 2>&1; then
actual_sha="$(sha256sum "$tmpdir/$entry")"; actual_sha="${actual_sha%% *}"
elif command -v shasum >/dev/null 2>&1; then
actual_sha="$(shasum -a 256 "$tmpdir/$entry")"; actual_sha="${actual_sha%% *}"
elif command -v openssl >/dev/null 2>&1; then
actual_sha="$(openssl dgst -sha256 "$tmpdir/$entry")"; actual_sha="${actual_sha##* }"
else
echo "pyenv-binary: need sha256sum, shasum or openssl to verify $entry" >&2
exit 1
fi
if [ "$actual_sha" != "$expected_sha" ]; then
echo "pyenv-binary: checksum mismatch for $entry" >&2
exit 1
fi
pyenv-install "$tmpdir/$entry:$version"

View File

@ -7,7 +7,7 @@
# Installs <version> from source under a separate entry name, saves it as a
# binary package, then emits a python-build definition for that package.
# The archive, metadata and definition are written to the current directory
# as <entry>.tar.gz, <entry>.meta and <entry>.
# as <entry>.tar.xz, <entry>.meta and <entry>.
#
# <version> A version `pyenv install' knows how to build.
# <entry> The optional name to build under and install the
@ -16,7 +16,7 @@
# -v,--verbose Show build progress from `pyenv install'.
# --archive-base-url <url>
# Where the archive will be hosted; the definition
# downloads it from <url>/<entry>.tar.gz.
# downloads it from <url>/<entry>.tar.xz.
#
set -e
[ -n "$PYENV_DEBUG" ] && set -x
@ -75,18 +75,11 @@ latest )
;;
esac
os="$(uname -s)"
# `generate-installer' refuses a macOS archive, so the last step here cannot
# succeed on one. Give up before compiling rather than after it.
if [ "$os" = "Darwin" ]; then
echo "pyenv-binary: macOS archives are not supported yet" >&2
exit 1
fi
# `pyenv install' puts a `<version>:<alias>' build under versions/<alias>.
pyenv-install ${verbose:+--verbose} "$spec"
pyenv-binary-save "$entry" "$PWD" --name "$entry"
source_version="$(pyenv-latest -f -k "${spec%%:*}")"
source_version="${source_version##*/}"
pyenv-binary-save "$entry" "$PWD" --name "$entry" --source-version "$source_version"
pyenv-binary-generate-installer "${entry}.meta" \
--archive-url "${archive_base_url%/}/${entry}.tar.gz" -o "$entry"
--archive-url "${archive_base_url%/}/${entry}.tar.xz" -o "$entry"

View File

@ -1,12 +1,13 @@
#!/usr/bin/env bash
#
# Summary: Rewrite an unpacked Python's rpaths so it runs from its prefix
# Summary: Rewrite an unpacked Python's library paths so it runs from its prefix
#
# Usage: pyenv binary relocate <prefix>
# Usage: pyenv binary relocate <prefix> [<build-prefix>]
#
# Rewrites the rpaths of a Python tree that was unpacked into <prefix> so the
# interpreter and its extension modules load the bundled libraries from their
# new location rather than the path it was built at. Requires patchelf.
# Rewrites the library paths of a Python tree that was unpacked into <prefix>
# so the interpreter and its extension modules load the bundled libraries from
# their new location rather than the path it was built at. Requires patchelf on
# Linux and FreeBSD, or otool and install_name_tool on macOS.
#
# The definition that `pyenv binary generate-installer' produces calls this
# after `install_package ... copy' has laid the tree down.
@ -24,6 +25,100 @@ if [ -z "$prefix" ]; then
exit 1
fi
if [ "$(uname -s)" = "Darwin" ]; then
build_prefix="${2%/}"
if [ -z "$build_prefix" ]; then
echo "pyenv-binary: need the original build prefix to relocate a macOS binary" >&2
exit 1
fi
for tool in otool install_name_tool; do
if ! command -v "$tool" >/dev/null 2>&1; then
echo "pyenv-binary: need ${tool} to relocate the binary" >&2
exit 1
fi
done
relocate_macho() {
local file="$1" new_rpath="$2"
local load_commands install_ids rpaths dependency install_id rpath replacement
load_commands="$(otool -L "$file")"
install_ids="$(otool -D "$file" 2>/dev/null || true)"
rpaths="$(otool -l "$file")"
install_id="$(printf '%s\n' "$install_ids" | sed -n '2s/^[[:space:]]*//p')"
while IFS= read -r dependency; do
case "$dependency" in
"$build_prefix"/lib/* )
if [ "$dependency" != "$install_id" ]; then
replacement="@rpath/${dependency#"$build_prefix"/lib/}"
install_name_tool -change "$dependency" "$replacement" "$file"
fi
;;
esac
done < <(printf '%s\n' "$load_commands" | tail -n +2 | sed -E \
's/^[[:space:]]*//; s/[[:space:]]+\(compatibility version.*$//')
case "$install_id" in
"$build_prefix"/lib/* )
replacement="@rpath/${install_id#"$build_prefix"/lib/}"
install_name_tool -id "$replacement" "$file"
;;
esac
while IFS= read -r rpath; do
if [ "$rpath" = "$build_prefix/lib" ]; then
install_name_tool -rpath "$rpath" "$new_rpath" "$file"
fi
done < <(printf '%s\n' "$rpaths" | awk '
/cmd LC_RPATH/ { found = 1; next }
found && /^[[:space:]]*path / {
sub(/^[[:space:]]*path /, "")
sub(/ \(offset [0-9]+\)$/, "")
print
found = 0
}
')
}
found=0
for file in "$prefix"/bin/*; do
[[ -f $file && -x $file && ! -L $file ]] || continue
otool -L "$file" >/dev/null 2>&1 || continue
relocate_macho "$file" '@executable_path/../lib'
found=1
done
if [ "$found" -eq 0 ]; then
echo "pyenv-binary: found no interpreter to relocate under \`${prefix}/bin'" >&2
exit 1
fi
for file in "$prefix"/lib/*.dylib; do
[[ -f $file && ! -L $file ]] || continue
relocate_macho "$file" '@loader_path'
done
while IFS= read -r so; do
relocate_macho "$so" '@loader_path/../..'
done < <(find "$prefix" -type f -path '*/lib/python*/lib-dynload/*.so')
# CPython records its installation prefix in generated scripts and build
# metadata. Bytecode can also retain source filenames from the build tree.
build_prefix_pattern="$(printf '%s\n' "$build_prefix" | sed 's/[][\\.^$*|]/\\&/g')"
prefix_replacement="$(printf '%s\n' "$prefix" | sed 's/[\\&|]/\\&/g')"
while IFS= read -r file; do
if LC_ALL=C grep -IqF "$build_prefix" "$file"; then
sed -i.bak "s|${build_prefix_pattern}|${prefix_replacement}|g" "$file"
rm -f "${file}.bak"
fi
done < <(find "$prefix" -type f ! -name '*.pyc' ! -name '*.pyo')
while IFS= read -r file; do
if LC_ALL=C grep -aqF "$build_prefix" "$file"; then
rm -f "$file"
fi
done < <(find "$prefix" -type f \( -name '*.pyc' -o -name '*.pyo' \))
exit
fi
# patchelf can add an rpath and write one of any length; chrpath can only shorten
# an existing one, which is not enough to relocate every build, so require it.
if ! command -v patchelf >/dev/null 2>&1; then

View File

@ -2,9 +2,9 @@
#
# Summary: Save an installed Python version as a relocatable archive
#
# Usage: pyenv binary save <version> [<output-dir>] [--name <name>]
# Usage: pyenv binary save <version> [<output-dir>] [--name <name>] [--source-version <version>]
#
# Packs an installed version into a relocatable .tar.gz (relative paths) and
# Packs an installed version into a relocatable .tar.xz (relative paths) and
# writes a metadata file listing the build platform and the system libraries
# it links against, so an installer can check compatibility before unpacking.
#
@ -12,6 +12,7 @@
# <output-dir> Where to write the archive and metadata (default: `.').
# --name <name> Use <name> as the archive and metadata base name instead of
# <version>-<platform>.
# --source-version <version> Record the version used to build a renamed install.
#
set -e
[ -n "$PYENV_DEBUG" ] && set -x
@ -19,18 +20,23 @@ set -e
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
echo --name
echo --source-version
exec pyenv-versions --bare
fi
version=""
output_dir=""
package_name=""
source_version=""
while [ $# -gt 0 ]; do
case "$1" in
--name )
[ $# -ge 2 ] && [ -n "$2" ] || { echo "pyenv-binary: --name needs a value" >&2; exit 1; }
package_name="$2"; shift 2 ;;
--source-version )
[ $# -ge 2 ] && [ -n "$2" ] && [ "${2#-}" = "$2" ] || { echo "pyenv-binary: --source-version needs a value" >&2; exit 1; }
source_version="$2"; shift 2 ;;
-* )
echo "pyenv-binary: unknown option \`$1'" >&2; exit 1 ;;
* )
@ -49,7 +55,7 @@ done
output_dir="${output_dir:-$PWD}"
if [ -z "$version" ]; then
echo "Usage: pyenv binary save <version> [<output-dir>] [--name <name>]" >&2
echo "Usage: pyenv binary save <version> [<output-dir>] [--name <name>] [--source-version <version>]" >&2
exit 1
fi
@ -69,6 +75,14 @@ case "$package_name" in
;;
esac
source_version="${source_version:-$version}"
case "$source_version" in
*/* | .. | . | *[[:cntrl:]]* )
echo "pyenv-binary: invalid source version \`${source_version}'" >&2
exit 1
;;
esac
prefix="${PYENV_ROOT}/versions/${version}"
if [ ! -d "${prefix}/bin" ]; then
echo "pyenv-binary: version \`${version}' is not installed" >&2
@ -92,12 +106,16 @@ fi
if [ "$os" = "Linux" ]; then
libc="$(getconf GNU_LIBC_VERSION 2>/dev/null || true)"
fi
if [ "$os" != "Darwin" ] && ! LC_ALL=C readelf --version &>/dev/null; then
echo "pyenv-binary: need readelf to inspect shared libraries" >&2
exit 1
fi
# List the external shared libraries the install links against: those that
# resolve outside its own prefix, so they must already exist on the target.
# The interpreter plus every bundled shared object are inspected.
system_deps() {
local f
local f needed
{
for f in "${prefix}"/bin/python*; do
[ -e "$f" ] && printf '%s\n' "$f"
@ -111,27 +129,40 @@ system_deps() {
otool -L "$f" 2>/dev/null | tail -n +2 | awk -v pfx="${prefix}/" \
'$1 !~ /^@/ && substr($1, 1, length(pfx)) != pfx { print $1 }'
else
ldd "$f" 2>/dev/null | awk -v pfx="${prefix}/" \
'$2 == "=>" && $3 ~ /^\// && substr($3, 1, length(pfx)) != pfx { print $1 }'
# GNU binutils 2.44 writes "(NEEDED) ... [name]"; FreeBSD 15.1 writes
# "NEEDED ... [name]". readelf(1) documents -d, not its text format.
needed="$(LC_ALL=C readelf -dW "$f" 2>/dev/null | awk \
'$2 == "(NEEDED)" || $2 == "NEEDED" { sub(/^.*\[/, ""); sub(/\].*$/, ""); print }' | tr '\n' ' ')"
# Linux and FreeBSD ldd write resolved libraries as
# "name => /absolute/path (address)"; entries without "=>" are ignored.
LC_ALL=C ldd "$f" 2>/dev/null | awk -v needed="$needed" -v pfx="${prefix}/" '
BEGIN {
split(needed, deps, " ")
for (i in deps) direct[deps[i]] = 1
}
$1 in direct && $2 == "=>" && $3 ~ /^\// && substr($3, 1, length(pfx)) != pfx { print $1 }
'
fi
done | sort -u
}
mkdir -p "$output_dir"
package_name="${package_name:-${version}-${platform}}"
archive="${package_name}.tar.gz"
archive="${package_name}.tar.xz"
metadata="${package_name}.meta"
tar -C "$(dirname "$prefix")" -czf "${output_dir}/${archive}" "$(basename "$prefix")"
tar -C "$(dirname "$prefix")" -cJf "${output_dir}/${archive}" "$(basename "$prefix")"
{
echo "# pyenv-binary metadata"
echo "version=${version}"
echo "source_version=${source_version}"
echo "os=${os}"
echo "arch=${arch}"
echo "platform=${platform}"
[ -n "$distro" ] && echo "distro=${distro}"
[ -n "$libc" ] && echo "libc=${libc}"
echo "build_prefix=${prefix}"
echo "archive=${archive}"
system_deps | while IFS= read -r dep; do
[ -n "$dep" ] && echo "dep=${dep}"

View File

@ -0,0 +1,3 @@
source_version entry os arch distro sha256
3.14.7 3.14.7-macos-15-arm64 Darwin arm64 macos 15.7.9 8a8ff86b520c3b5da00b49e04a5345b7a28f2f9e8da5a9ae43b8ac309e8f3e55
3.14.7 3.14.7-ubuntu-24.04-x86_64 Linux x86_64 ubuntu 24.04 e63dbcb981ec9ba83a2bc9b4d8b369620cec4aa45394559d719c5606ee9ff718

View File

@ -6,6 +6,7 @@ create_meta() {
local os="${1-Linux}"
local arch="${2-x86_64}"
local libc="${3-glibc 2.17}"
local build_prefix="${4-}"
local archive="${BATS_TEST_TMPDIR}/3.12.7.tar.gz"
local meta="${BATS_TEST_TMPDIR}/sample.meta"
@ -20,6 +21,7 @@ create_meta() {
echo "os=${os}"
echo "arch=${arch}"
[ -z "$libc" ] || echo "libc=${libc}"
[ -z "$build_prefix" ] || echo "build_prefix=${build_prefix}"
echo "archive=${archive##*/}"
} > "$meta"
echo "$meta"
@ -58,10 +60,20 @@ create_meta() {
assert_failure
}
@test "refuses macOS metadata" {
@test "fails when macOS metadata is missing the build prefix" {
run pyenv-binary-generate-installer "$(create_meta Darwin arm64 '')" \
--archive-url http://x/a.tar.gz
assert_failure "pyenv-binary: macOS archives are not supported yet"
assert_failure "pyenv-binary: metadata is missing \`build_prefix'"
}
@test "quotes the macOS build prefix in the generated definition" {
local out="${BATS_TEST_TMPDIR}/definition"
pyenv-binary-generate-installer \
"$(create_meta Darwin arm64 '' '/build prefix/$name')" \
--archive-url http://example.com/a.tar.gz -o "$out"
run grep '^BUILD_PREFIX=' "$out"
assert_success 'BUILD_PREFIX=/build\ prefix/\$name'
}
@test "fails when required metadata is missing" {
@ -117,6 +129,58 @@ create_meta() {
assert_failure "pyenv-binary: need patchelf to relocate the binary"
}
@test "checks for otool before installing a macOS archive" {
local out="${BATS_TEST_TMPDIR}/definition"
pyenv-binary-generate-installer \
"$(create_meta Darwin arm64 '' /build/3.12.7)" \
--archive-url http://example.com/a.tar.gz -o "$out"
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_path_executable install_name_tool true
PATH="$(path_without otool)" run bash "$out"
assert_failure "pyenv-binary: need otool to relocate the binary"
}
@test "checks for install_name_tool before installing a macOS archive" {
local out="${BATS_TEST_TMPDIR}/definition"
pyenv-binary-generate-installer \
"$(create_meta Darwin arm64 '' /build/3.12.7)" \
--archive-url http://example.com/a.tar.gz -o "$out"
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_path_executable otool true
PATH="$(path_without install_name_tool)" run bash "$out"
assert_failure "pyenv-binary: need install_name_tool to relocate the binary"
}
@test "the generated macOS definition preserves both relocation arguments" {
local archive="${BATS_TEST_TMPDIR}/3.12.7.tar.gz"
local cache="${BATS_TEST_TMPDIR}/cache"
local definition="${BATS_TEST_TMPDIR}/definition"
local prefix="${BATS_TEST_TMPDIR}/install"
pyenv-binary-generate-installer \
"$(create_meta Darwin arm64 '' '/build prefix/$name')" \
--archive-url http://example.com/3.12.7.tar.gz -o "$definition"
mkdir -p "$cache"
cp "$archive" "${cache}/Python-3.12.7-binary.tar.gz"
create_stub pyenv 'printf "argc=%s\narg1=%s\narg2=%s\narg3=%s\narg4=%s\n" "$#" "$1" "$2" "$3" "$4"'
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_stub sw_vers 'echo 15.5'
create_stub ldconfig true
create_path_executable otool true
create_path_executable install_name_tool true
PYTHON_BUILD_CACHE_PATH="$cache" run \
"${BATS_TEST_DIRNAME}/../../python-build/bin/python-build" "$definition" "$prefix"
assert_success
assert_line "argc=4"
assert_line "arg1=binary"
assert_line "arg2=relocate"
assert_line "arg3=${prefix}"
assert_line 'arg4=/build prefix/$name'
assert_line "Installed Python-3.12.7-binary to ${prefix}"
}
@test "fails when the archive is not beside the metadata" {
local meta="$(create_meta)"
rm "${BATS_TEST_TMPDIR}/3.12.7.tar.gz"

View File

@ -0,0 +1,203 @@
#!/usr/bin/env bats
load test_helper
host_distro() {
if [ -r /etc/os-release ]; then
. /etc/os-release
printf '%s %s' "$ID" "$VERSION_ID" | tr '[:upper:]' '[:lower:]'
else
printf '%s %s' "$(lsb_release -si)" "$(lsb_release -sr)" | tr '[:upper:]' '[:lower:]'
fi
}
use_manifest() {
local plugin="${BATS_TEST_TMPDIR}/plugin"
mkdir -p "$plugin/libexec" "$plugin/share/pyenv-binary/versions"
cp "${BATS_TEST_DIRNAME}/../libexec/pyenv-binary-install" "$plugin/libexec/"
PATH="$plugin/libexec:$PATH"
printf 'source_version\tentry\tos\tarch\tdistro\tsha256\n' > "$plugin/share/pyenv-binary/versions/3.14"
definition_sha="4c4ed1afbfdaa1e4c3bf7bbb82d730cecb7e384da91eea4f3cc093fd545524d6"
}
stub_downloads() {
create_stub curl <<'STUB'
output=""
while [ "$#" -gt 0 ]; do
case "$1" in
-o ) output="$2"; shift ;;
http* ) url="$1" ;;
esac
shift
done
case "$url" in
*/3.14.7-ubuntu-24.04-x86_64 | */3.14.7-macos-15-arm64 | */3.14.10-ubuntu-24.04-x86_64 ) printf definition > "$output" ;;
* ) exit 1 ;;
esac
STUB
}
@test "rejects a modified published definition" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
use_manifest
printf '3.14.7\t3.14.7-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\t%064d\n' \
"$(host_distro)" 0 >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
stub_downloads
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub pyenv-install '[ "$1" = --list ] && exit; echo installed'
run pyenv-binary-install 3.14.7
assert_failure
[[ "$output" == *'checksum mismatch'* ]]
}
@test "completion does not offer source-only versions" {
create_stub pyenv-install 'echo 3.14.7'
run pyenv-binary-install --complete
assert_success ""
}
@test "a plugin definition overrides a published binary without its checksum" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
use_manifest
export TMPDIR="$BATS_TEST_TMPDIR/temp"
mkdir -p "$TMPDIR"
local entry="3.14.7-ubuntu-24.04-x86_64"
printf '3.14.7\t%s\tLinux\tx86_64\t%s\t%s\n' "$entry" \
"$(host_distro)" "" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub curl 'touch "$BATS_TEST_TMPDIR/downloaded"; exit 1'
PATH="${BATS_TEST_DIRNAME}/../../python-build/bin:$PATH"
mkdir -p "$PYENV_ROOT/plugins/first/share/python-build" "$PYENV_ROOT/plugins/second/share/python-build"
printf '%s\n' 'mkdir -p "$PREFIX_PATH"; echo first > "$PREFIX_PATH/marker"' \
> "$PYENV_ROOT/plugins/first/share/python-build/$entry"
echo 'exit 1' > "$PYENV_ROOT/plugins/second/share/python-build/$entry"
run pyenv-binary-install 3.14
assert_success ""
assert_equal first "$(cat "$PYENV_ROOT/versions/3.14.7/marker")"
[ ! -e "$BATS_TEST_TMPDIR/downloaded" ]
assert_equal "" "$(find "$TMPDIR" -mindepth 1 -maxdepth 1 -type d)"
}
@test "an explicit definition path takes precedence over a plugin definition" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
use_manifest
local entry="3.14.7-ubuntu-24.04-x86_64"
printf '3.14.7\t%s\tLinux\tx86_64\t%s\t%s\n' "$entry" \
"$(host_distro)" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub curl 'touch "$BATS_TEST_TMPDIR/downloaded"; exit 1'
PATH="${BATS_TEST_DIRNAME}/../../python-build/bin:$PATH"
export PYTHON_BUILD_DEFINITIONS="$BATS_TEST_TMPDIR/custom definitions"
mkdir -p "$PYTHON_BUILD_DEFINITIONS" "$PYENV_ROOT/plugins/custom/share/python-build"
printf '%s\n' 'mkdir -p "$PREFIX_PATH"; echo custom > "$PREFIX_PATH/marker"' \
> "$PYTHON_BUILD_DEFINITIONS/$entry"
echo 'exit 1' > "$PYENV_ROOT/plugins/custom/share/python-build/$entry"
run pyenv-binary-install 3.14.7
assert_success ""
assert_equal custom "$(cat "$PYENV_ROOT/versions/3.14.7/marker")"
[ ! -e "$BATS_TEST_TMPDIR/downloaded" ]
}
@test "rejects an invalid published checksum when definition lookup fails" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
use_manifest
printf '3.14.7\t3.14.7-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\tinvalid\n' \
"$(host_distro)" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub pyenv-install 'exit 1'
create_stub curl 'touch "$BATS_TEST_TMPDIR/downloaded"; exit 1'
run pyenv-binary-install 3.14.7
assert_failure "pyenv-binary: invalid checksum for 3.14.7-ubuntu-24.04-x86_64"
[ ! -e "$BATS_TEST_TMPDIR/downloaded" ]
}
@test "installs a matching published binary with an uppercase checksum" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
use_manifest
local uppercase_sha="$(printf '%s' "$definition_sha" | tr '[:lower:]' '[:upper:]')"
printf '3.14.7\t3.14.7-macos-15-arm64\tDarwin\tarm64\tmacos 15.7.9\t%s\n' \
"$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
printf '3.14.7\t3.14.7-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\t%s\n' \
"$(host_distro | tr '[:lower:]' '[:upper:]')" "$uppercase_sha" \
>> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
stub_downloads
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub pyenv-install <<'STUB'
[ "$1" = --list ] && exit
definition="${1%:*}"
printf '%s:%s\n' "${definition##*/}" "${1##*:}"
cat "$definition"
STUB
run pyenv-binary-install 3.14
assert_success "3.14.7-ubuntu-24.04-x86_64:3.14.7
definition"
}
@test "a version prefix selects the latest published binary" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
use_manifest
printf '3.14.10\t3.14.10-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\t%s\n' \
"$(host_distro)" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
printf '3.14.7\t3.14.7-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\t%s\n' \
"$(host_distro)" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
stub_downloads
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub pyenv-install '[ "$1" = --list ] && exit; echo "${1##*:}"'
run pyenv-binary-install 3.14
assert_success "3.14.10"
}
@test "fails when no published binary matches the host" {
use_manifest
printf '3.14.7\t3.14.7-macos-15-arm64\tDarwin\tarm64\tmacos 15.7.9\t%s\n' \
"$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
run pyenv-binary-install 3.14.7
assert_failure "pyenv-binary: no binary available for 3.14.7 on Linux/x86_64"
}
@test "does not select a package for another Linux release" {
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 22.04;; esac'
use_manifest
local other_release="ubuntu 24.04"
[ "$(host_distro)" = "$other_release" ] && other_release="ubuntu 22.04"
printf '3.14.7\t3.14.7-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\t%s\n' \
"$other_release" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
run pyenv-binary-install 3.14.7
assert_failure "pyenv-binary: no binary available for 3.14.7 on Linux/x86_64"
}
@test "uses a macOS binary built on an older release" {
use_manifest
printf '3.14.7\t3.14.7-macos-15-arm64\tDarwin\tarm64\tmacos 15.7.9\t%s\n' \
"$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
stub_downloads
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_stub sw_vers 'echo 26.6.2'
create_stub pyenv-install '[ "$1" = --list ] && exit; echo "${1##*:}"'
run pyenv-binary-install 3.14.7
assert_success "3.14.7"
}
@test "rejects a macOS binary built on a newer patch release" {
use_manifest
printf '3.14.7\t3.14.7-macos-15-arm64\tDarwin\tarm64\tmacos 15.7.9\t%s\n' \
"$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_stub sw_vers 'echo 15.7.8'
create_stub pyenv-install '[ "$1" = --list ] && exit; echo installed'
run pyenv-binary-install 3.14.7
assert_failure "pyenv-binary: no binary available for 3.14.7 on Darwin/arm64"
}

View File

@ -10,6 +10,7 @@ stub_build_environment() {
create_stub pyenv-latest 'while (($#)); do case "$1" in -f|-k);; *)break;; esac; shift; done; echo "$*"'
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
create_stub getconf 'echo "glibc 2.17"'
create_stub readelf true
}
@test "-v|--verbose runs pyenv install verbosely" {
@ -65,10 +66,24 @@ pyenv-install --list --bare
run pyenv-binary-package 3.12.7 --archive-base-url http://example.com/binaries
assert_success
assert [ -d "${PYENV_ROOT}/versions/3.12.7-debian-12-x86_64" ]
assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64.tar.gz" ]
assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64.tar.xz" ]
assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64.meta" ]
run grep '^source_version=' "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64.meta"
assert_success "source_version=3.12.7"
run grep '^ARCHIVE_URL=' "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64"
assert_success "ARCHIVE_URL=http://example.com/binaries/3.12.7-debian-12-x86_64.tar.gz"
assert_success "ARCHIVE_URL=http://example.com/binaries/3.12.7-debian-12-x86_64.tar.xz"
}
@test "records the definition name when packaging from a file" {
stub_build_environment
cd "${BATS_TEST_TMPDIR}"
printf 'install_package "foo"\n' > custom-python
run pyenv-binary-package "${BATS_TEST_TMPDIR}/custom-python:custom-build" \
--archive-base-url http://example.com/binaries
assert_success
run grep '^source_version=' custom-build.meta
assert_success "source_version=custom-python"
}
@test "rejects an entry name containing a slash" {
@ -81,10 +96,17 @@ pyenv-install --list --bare
assert_failure "pyenv-binary: \`latest' cannot be used as an entry name"
}
@test "refuses to package on macOS before compiling anything" {
@test "packages on macOS" {
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_stub pyenv-latest 'echo 3.12.7'
create_stub pyenv-install 'echo install'
create_stub pyenv-binary-save 'echo save'
create_stub pyenv-binary-generate-installer 'echo generate-installer'
run pyenv-binary-package 3.12.7:3.12.7-test --archive-base-url http://x/b
assert_failure "pyenv-binary: macOS archives are not supported yet"
assert_success "install
save
generate-installer"
}
@test "writes the archive, metadata and definition under the entry name (integration)" {
@ -95,10 +117,10 @@ pyenv-install --list --bare
--archive-base-url http://example.com/binaries
assert_success
assert [ -d "${PYENV_ROOT}/versions/3.12.7-test" ]
assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-test.tar.gz" ]
assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-test.tar.xz" ]
assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-test.meta" ]
run grep '^ARCHIVE_URL=' "${BATS_TEST_TMPDIR}/3.12.7-test"
assert_success "ARCHIVE_URL=http://example.com/binaries/3.12.7-test.tar.gz"
assert_success "ARCHIVE_URL=http://example.com/binaries/3.12.7-test.tar.xz"
}
@test "correctly joins archive base url with a trailing slash" {
@ -120,5 +142,5 @@ done
run pyenv-binary-package 3.12.7:3.12.7-test \
--archive-base-url http://example.com/binaries/
assert_success
assert_line "pyenv-binary-generate-installer --archive-url http://example.com/binaries/3.12.7-test.tar.gz"
assert_line "pyenv-binary-generate-installer --archive-url http://example.com/binaries/3.12.7-test.tar.xz"
}

View File

@ -4,6 +4,7 @@ load test_helper
_setup() {
create_stub pyenv-help "echo usage"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
}
stub_patchelf() {
@ -21,6 +22,104 @@ create_interpreter() {
chmod +x "${BATS_TEST_TMPDIR}/prefix/bin/python2.7"
}
create_macos_tree() {
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
local lib="${prefix}/lib/python3.12"
local old="/build prefix/3.12.7"
mkdir -p \
"${prefix}/bin" \
"${prefix}/lib/pkgconfig" \
"${lib}/__pycache__" \
"${lib}/lib-dynload" \
"${lib}/site-packages/numpy"
printf '#!/bin/sh\n' > "${prefix}/bin/python3.12"
chmod +x "${prefix}/bin/python3.12"
printf '#!%s/bin/python3.12\n' "$old" > "${prefix}/bin/pip3"
chmod +x "${prefix}/bin/pip3"
printf 'prefix=%s\n' "$old" > "${prefix}/lib/pkgconfig/python-3.12.pc"
printf 'prefix=/build prefix/3x12x7\n' > "${prefix}/lib/pkgconfig/unrelated.pc"
printf 'prefix = "%s"\n' "$old" > "${lib}/_sysconfigdata.py"
printf '\0bytecode:%s/module.py\n' "$old" > "${lib}/__pycache__/module.cpython-312.pyc"
printf '\0bytecode:%s/legacy.py\n' "$old" > "${lib}/legacy.pyo"
printf '\0sourceless bytecode\n' > "${lib}/sourceless.pyc"
touch "${prefix}/lib/libpython3.12.dylib"
touch "${lib}/lib-dynload/_ssl.cpython-312-darwin.so"
touch "${lib}/site-packages/numpy/_multiarray.so"
}
stub_macos_tools() {
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_path_executable install_name_tool \
'echo "$*" >> "${BATS_TEST_TMPDIR}/install-name-tool.log"'
create_path_executable otool <<'STUB'
file="${!#}"
echo "$*" >> "${BATS_TEST_TMPDIR}/otool.log"
old="/build prefix/3.12.7"
case "$1" in
-L )
echo "${file}:"
case "$file" in
*/bin/pip3 )
exit 1
;;
*/bin/python3.12 )
if [ -n "$OTOOL_RELOCATED" ]; then
echo " @rpath/libpython3.12.dylib (compatibility version 3.12.0, current version 3.12.0)"
else
echo " ${old}/lib/libpython3.12.dylib (compatibility version 3.12.0, current version 3.12.0)"
fi
echo " ${old}-other/lib/libother.dylib (compatibility version 1.0.0, current version 1.0.0)"
echo " /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1.0.0)"
echo " /opt/homebrew/lib/libintl.8.dylib (compatibility version 1.0.0, current version 1.0.0)"
echo " @loader_path/liblocal.dylib (compatibility version 1.0.0, current version 1.0.0)"
;;
*/lib/libpython3.12.dylib )
if [ -n "$OTOOL_RELOCATED" ]; then
echo " @rpath/libpython3.12.dylib (compatibility version 3.12.0, current version 3.12.0)"
else
echo " ${old}/lib/libpython3.12.dylib (compatibility version 3.12.0, current version 3.12.0)"
fi
;;
esac
;;
-D )
case "$file" in
*/lib/libpython3.12.dylib )
echo "${file}:"
if [ -n "$OTOOL_RELOCATED" ]; then
echo '@rpath/libpython3.12.dylib'
else
echo "${old}/lib/libpython3.12.dylib"
fi
;;
* )
exit 1
;;
esac
;;
-l )
if [ -n "$OTOOL_RELOCATED" ]; then
case "$file" in
*/bin/* ) rpath='@executable_path/../lib' ;;
*/lib/*.dylib ) rpath='@loader_path' ;;
* ) rpath='@loader_path/../..' ;;
esac
else
rpath="${old}/lib"
fi
cat <<EOF
cmd LC_RPATH
path ${rpath} (offset 12)
cmd LC_RPATH
path /opt/homebrew/lib (offset 12)
cmd LC_RPATH
path @loader_path/vendor (offset 12)
EOF
;;
esac
STUB
}
@test "completion produces nothing" {
run pyenv-binary-relocate --complete
assert_success ""
@ -36,6 +135,31 @@ create_interpreter() {
assert_failure "pyenv-binary: need patchelf to relocate the binary"
}
@test "fails without the original build prefix on macOS" {
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
run pyenv-binary-relocate "${BATS_TEST_TMPDIR}/prefix"
assert_failure "pyenv-binary: need the original build prefix to relocate a macOS binary"
}
@test "fails when otool is not available on macOS" {
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_path_executable install_name_tool true
PATH="$(path_without otool)" run \
pyenv-binary-relocate "${BATS_TEST_TMPDIR}/prefix" /build/3.12.7
assert_failure "pyenv-binary: need otool to relocate the binary"
}
@test "fails when install_name_tool is not available on macOS" {
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
create_path_executable otool true
PATH="$(path_without install_name_tool)" run \
pyenv-binary-relocate "${BATS_TEST_TMPDIR}/prefix" /build/3.12.7
assert_failure "pyenv-binary: need install_name_tool to relocate the binary"
}
@test "fails when the prefix has no interpreter" {
create_path_executable patchelf "exit 0"
mkdir -p "${BATS_TEST_TMPDIR}/prefix"
@ -70,3 +194,56 @@ create_interpreter() {
assert_line "--set-rpath ${BATS_TEST_TMPDIR}/prefix/lib ${lib}/lib-dynload/_ssl.cpython-312-x86_64-linux-gnu.so"
refute_line "--set-rpath ${BATS_TEST_TMPDIR}/prefix/lib ${lib}/site-packages/numpy/_multiarray.so"
}
@test "relocates macOS load commands without changing unrelated entries" {
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
local old="/build prefix/3.12.7"
local lib="${prefix}/lib/python3.12"
create_macos_tree
stub_macos_tools
run pyenv-binary-relocate "$prefix" "$old"
assert_success
run cat "${BATS_TEST_TMPDIR}/install-name-tool.log"
assert_output <<EOF
-change ${old}/lib/libpython3.12.dylib @rpath/libpython3.12.dylib ${prefix}/bin/python3.12
-rpath ${old}/lib @executable_path/../lib ${prefix}/bin/python3.12
-id @rpath/libpython3.12.dylib ${prefix}/lib/libpython3.12.dylib
-rpath ${old}/lib @loader_path ${prefix}/lib/libpython3.12.dylib
-rpath ${old}/lib @loader_path/../.. ${lib}/lib-dynload/_ssl.cpython-312-darwin.so
EOF
run grep -F "${lib}/site-packages/numpy/_multiarray.so" "${BATS_TEST_TMPDIR}/otool.log"
assert_failure
run head -n 1 "${prefix}/bin/pip3"
assert_output "#!${prefix}/bin/python3.12"
run cat "${prefix}/lib/pkgconfig/python-3.12.pc"
assert_output "prefix=${prefix}"
run cat "${prefix}/lib/pkgconfig/unrelated.pc"
assert_output "prefix=/build prefix/3x12x7"
run cat "${lib}/_sysconfigdata.py"
assert_output "prefix = \"${prefix}\""
assert [ ! -e "${lib}/__pycache__/module.cpython-312.pyc" ]
assert [ ! -e "${lib}/legacy.pyo" ]
assert [ -e "${lib}/sourceless.pyc" ]
}
@test "skips already relocated macOS load commands" {
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
create_macos_tree
stub_macos_tools
export OTOOL_RELOCATED=1
run pyenv-binary-relocate "$prefix" "/build prefix/3.12.7"
assert_success
assert [ ! -e "${BATS_TEST_TMPDIR}/install-name-tool.log" ]
}
@test "fails when install_name_tool cannot modify a selected file" {
local prefix="${BATS_TEST_TMPDIR}/prefix&target"
create_macos_tree
stub_macos_tools
create_path_executable install_name_tool 'exit 1'
run pyenv-binary-relocate "$prefix" "/build prefix/3.12.7"
assert_failure ""
}

View File

@ -12,7 +12,7 @@ platform() {
@test "fails with no version given" {
run pyenv-binary-save
assert_failure "Usage: pyenv binary save <version> [<output-dir>] [--name <name>]"
assert_failure "Usage: pyenv binary save <version> [<output-dir>] [--name <name>] [--source-version <version>]"
}
@test "fails for a version that is not installed" {
@ -33,13 +33,13 @@ platform() {
@test "packages an installed version" {
create_version "3.12.7"
local out="${BATS_TEST_TMPDIR}/dist"
local archive="${out}/3.12.7-$(platform).tar.gz"
local archive="${out}/3.12.7-$(platform).tar.xz"
run pyenv-binary-save "3.12.7" "$out"
assert_success "Saved 3.12.7-$(platform).tar.gz and 3.12.7-$(platform).meta to $out"
assert_success "Saved 3.12.7-$(platform).tar.xz and 3.12.7-$(platform).meta to $out"
assert [ -f "$archive" ]
assert [ -f "${out}/3.12.7-$(platform).meta" ]
run tar -tzf "$archive"
run tar -tJf "$archive"
assert_success
assert_line 0 "3.12.7/"
}
@ -49,10 +49,32 @@ platform() {
local out="${BATS_TEST_TMPDIR}/dist"
run pyenv-binary-save "3.12.7" "$out" --name "custom"
assert_success "Saved custom.tar.gz and custom.meta to $out"
assert [ -f "${out}/custom.tar.gz" ]
assert_success "Saved custom.tar.xz and custom.meta to $out"
assert [ -f "${out}/custom.tar.xz" ]
run grep '^archive=' "${out}/custom.meta"
assert_success "archive=custom.tar.gz"
assert_success "archive=custom.tar.xz"
}
@test "records the source version for a renamed build" {
create_version "3.12.7-ubuntu-24.04-x86_64"
local out="${BATS_TEST_TMPDIR}/dist"
run pyenv-binary-save "3.12.7-ubuntu-24.04-x86_64" "$out" \
--name "3.12.7-ubuntu-24.04-x86_64" --source-version "3.12.7"
assert_success
run grep '^source_version=' "${out}/3.12.7-ubuntu-24.04-x86_64.meta"
assert_success "source_version=3.12.7"
}
@test "rejects an option as the source version" {
run pyenv-binary-save "3.12.7" --source-version --name custom
assert_failure "pyenv-binary: --source-version needs a value"
}
@test "rejects control characters in the default source version" {
run pyenv-binary-save $'3.12.7\nsource_version=other'
assert_failure
[[ "$output" == "pyenv-binary: invalid source version"* ]]
}
@test "fails when --name has no value" {
@ -76,10 +98,28 @@ platform() {
assert_success
assert_line "version=3.12.7"
assert_line "platform=$(platform)"
assert_line "archive=3.12.7-$(platform).tar.gz"
assert_line "archive=3.12.7-$(platform).tar.xz"
}
@test "records only the libraries ldd resolves outside the prefix" {
@test "records the original installation prefix" {
create_version "3.12.7"
local out="${BATS_TEST_TMPDIR}/dist"
pyenv-binary-save "3.12.7" "$out" >/dev/null
run grep '^build_prefix=' "${out}/3.12.7-$(platform).meta"
assert_success "build_prefix=${PYENV_ROOT}/versions/3.12.7"
}
@test "fails when readelf is not available" {
create_version "3.12.7"
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
PATH="$(path_without readelf)" run pyenv-binary-save "3.12.7" "${BATS_TEST_TMPDIR}/dist"
assert_failure "pyenv-binary: need readelf to inspect shared libraries"
assert [ ! -e "${BATS_TEST_TMPDIR}/dist/3.12.7-$(platform).tar.xz" ]
}
@test "records only direct libraries resolved outside the prefix" {
create_version "3.12.7"
touch "${PYENV_ROOT}/versions/3.12.7/bin/python3.12"
create_path_executable uname <<'STUB'
@ -97,13 +137,18 @@ cat <<EOF
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4a3b800000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4a3c200000)
EOF
STUB
create_path_executable readelf <<'STUB'
cat <<EOF
0x0000000000000001 (NEEDED) Shared library: [libpython3.12.so.1.0]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
EOF
STUB
run pyenv-binary-save "3.12.7" "${BATS_TEST_TMPDIR}/dist"
assert_success
run grep '^dep=' "${BATS_TEST_TMPDIR}/dist/"*.meta
assert_output "dep=libc.so.6
dep=libm.so.6"
assert_output "dep=libm.so.6"
}
@test "records only the libraries otool resolves outside the prefix" {

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 yfprojects
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,33 @@
# pyenv-link
A [pyenv](https://github.com/pyenv/pyenv) plugin for linking Python installations and virtual environments into your pyenv root.
This plugin recommends the [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv/) plugin.
## Usage
Make an arbitrary virtualenv available through pyenv. This automatically guesses a fitting name from the prompt, the directory name or the location of the venv.
```console
$ pyenv link version .venv
Linked new version named myproject
```
You can also specify a name to use for the venv.
```console
$ pyenv link version .venv myname
Linked new version named myname
```
The same command can give a platform-specific binary installation a shorter name:
```console
$ pyenv link version "$(pyenv root)/versions/3.13.14-linux-x86_64" 3.13.14
Linked new version named 3.13.14
```
Now you can make pyenv activate/use the venv automatically:
```console
$ pyenv local myproject
```

View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
#
# Summary: Link a Python environment as a pyenv version
#
# Usage: pyenv link version [--dry] [--quiet] <path> [<name>]
#
# Link a virtual python environment to pyenvs version directory
# so that the venv can be used like one created with *pyenv-virtualenv*.
#
# <path> should be a path to a Python installation or virtual environment.
set -e
[ -n "$PYENV_DEBUG" ] && set -x
# Provide pyenv completions
case "$1" in
--complete)
if [ -z "$2" ]; then
echo version
else
shift 2
pyenv-link-version --complete "$@"
fi
;;
version)
shift
pyenv-link-version "$@"
exit $?
;;
*)
pyenv-help --usage link >&2
exit 1
;;
esac

View File

@ -0,0 +1,150 @@
#!/usr/bin/env bash
#
# Summary: Link a Python environment as a pyenv version
#
# Usage: pyenv link version [--dry] [--quiet] <path> [<name>]
#
# Link a virtual python environment to pyenvs version directory
# so that the venv can be used like one created with *pyenv-virtualenv*.
#
# <path> should be a path to a Python installation or virtual environment.
# <name> should be string used as a version name it may not be present
# in the pyenv version directory yet.
# If not specified a matching name is guessed from pyvenv.cfg
# or directory name of the venv.
set -e
[ -n "$PYENV_DEBUG" ] && set -x
# functions
if ! {
enable -f "${BASH_SOURCE%/*}"/../../../libexec/pyenv-realpath.dylib realpath ||
type realpath # realpath available?
} >/dev/null 2>&1; then
# realpath requires GNU coreutils to be installed. That's why its bundled with pyenv
echo realpath not available >&2
# work-around when realpath is unavailable
realpath() {
(cd "$1" && pwd)
}
fi
guess_name() {
local venv_dir=$1
local name
# guess venv name from pyvenv.cfg
local pyvenv_cfg_path=$venv_dir/pyvenv.cfg
if [ -f "$pyvenv_cfg_path" ]; then
# if `prompt` key wasn't found the var remains empty
name=$(cut -b 1-1024 "$pyvenv_cfg_path" | sed -n '/^ *prompt *= */s///p')
case "$name" in
\"*\" | \'*\')
name=${name:1:${#name}-2}
;;
esac
fi
# guess venv name from name of venv directory
local venv_dir_name=${venv_dir##*/}
if [ -z "$name" ]; then
case "$venv_dir_name" in
venv | env | .venv | .env | ENV | VENV) ;;
*) name=$venv_dir_name ;;
esac
fi
# guess venv name from name of the parent directory of the venv directory
local venv_dir_parent=${venv_dir%/*}
local venv_dir_parent_name=${venv_dir_parent##*/}
if [ -z "$name" ]; then
name=$venv_dir_parent_name
fi
echo "$name"
}
# process args
POSARGS=()
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
echo --dry
echo --quiet
exit
fi
for arg in "$@"; do
case $arg in
--dry)
dry=true # any value
;;
--quiet)
quiet=true # any value
;;
-*)
pyenv-help --usage link-version >&2
exit 1
;;
*)
POSARGS+=("$arg")
;;
esac
done
if [ ! ${#POSARGS[@]} -le 2 ] || [ ! ${#POSARGS[@]} -ge 1 ]; then
pyenv-help --usage link-version >&2
exit 1
fi
venv_dir=${POSARGS[0]%/}
venv_name=${POSARGS[1]}
# Check venv exists
if [ ! -d "$venv_dir" ]; then
echo "The virtual env you specified doesn't exist"
exit 2
fi
# make venv dir absolute
venv_dir=$(realpath "$venv_dir")
# determine venv name
if [ -z "$venv_name" ]; then
venv_name=$(guess_name "$venv_dir")
fi
case "$venv_name" in
"" | */* | . | .. | *:* | system | *[[:cntrl:]]* )
echo "pyenv-link: invalid version name \`${venv_name}'" >&2
exit 1
;;
esac
versions_dir="$PYENV_ROOT/versions"
pyenv_prefix_path="$versions_dir/$venv_name"
if [ -e "$pyenv_prefix_path" ] || [ -L "$pyenv_prefix_path" ]; then
echo Version "$venv_name" already exists >&2
exit 3
fi
case "$venv_dir" in
"$versions_dir"/*)
link_target=${venv_dir#"$versions_dir"/}
;;
*)
link_target=$venv_dir
;;
esac
# link to pyenv version directory
if [ -z "$dry" ]; then
mkdir -p "$versions_dir"
ln -s "$link_target" "$pyenv_prefix_path"
fi
# output
if [ -z "$quiet" ]; then
echo "Linked new version named $venv_name"
fi

View File

@ -0,0 +1,61 @@
#!/usr/bin/env bats
load test_helper
@test "link completions use the dispatcher" {
run pyenv completions link
assert_success
assert_output <<OUT
--help
version
OUT
run pyenv completions link version
assert_success
assert_output <<OUT
--help
--dry
--quiet
OUT
}
@test "link requires a version path" {
run pyenv-link version
assert_failure "Usage: pyenv link version [--dry] [--quiet] <path> [<name>]"
}
@test "links an installed binary under its plain version name" {
create_alt_executable_in_version "3.13.14-linux-x86_64" python 'echo linked-python'
run pyenv-link version "$PYENV_ROOT/versions/3.13.14-linux-x86_64" 3.13.14
assert_success "Linked new version named 3.13.14"
assert_equal "3.13.14-linux-x86_64" "$(readlink "$PYENV_ROOT/versions/3.13.14")"
PYENV_VERSION=3.13.14 run pyenv exec python
assert_success "linked-python"
}
@test "links external paths containing spaces into a fresh root" {
mkdir -p "$PYENV_TEST_DIR/external env/bin"
run pyenv-link version "$PYENV_TEST_DIR/external env" custom
assert_success "Linked new version named custom"
assert_equal "$PYENV_TEST_DIR/external env" "$(readlink "$PYENV_ROOT/versions/custom")"
}
@test "refuses a dangling destination link" {
mkdir -p "$PYENV_ROOT/versions" "$PYENV_TEST_DIR/source"
ln -s missing "$PYENV_ROOT/versions/dangling"
run pyenv-link version "$PYENV_TEST_DIR/source" dangling
assert_failure "Version dangling already exists"
assert_equal missing "$(readlink "$PYENV_ROOT/versions/dangling")"
}
@test "rejects invalid version names" {
mkdir -p "$PYENV_TEST_DIR/source"
for name in ../outside . .. 'foo/bar' 'foo:bar' system; do
run pyenv-link version "$PYENV_TEST_DIR/source" "$name"
assert_failure "pyenv-link: invalid version name \`$name'"
assert [ ! -e "$PYENV_ROOT/outside" ]
done
echo "prompt = '../outside'" > "$PYENV_TEST_DIR/source/pyvenv.cfg"
run pyenv-link version "$PYENV_TEST_DIR/source"
assert_failure "pyenv-link: invalid version name \`../outside'"
assert [ ! -e "$PYENV_ROOT/outside" ]
}

View File

@ -0,0 +1 @@
../../../test/test_helper.bash

View File

@ -54,8 +54,11 @@ Or, if you would like to install the latest development release:
## Usage
Before you begin, you should ensure that your build environment has the proper
system dependencies for compiling the wanted Python Version (see our [recommendations](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)).
On Ubuntu, Debian, and Mint, install the recommended build dependencies with:
pyenv install-prerequisites
For other environments, see our [build environment recommendations](https://github.com/pyenv/pyenv/wiki#suggested-build-environment).
### Using `pyenv install` with pyenv
@ -361,4 +364,3 @@ git diff --name-only master \
- Filter out any which don't live where python-build keeps its build scripts
- Look only at the file name (i.e. the python version name)
- Run a new docker container for each, building that version

View File

@ -261,7 +261,7 @@ for i in "${!DEFINITIONS[@]}"; do
PYENV_BOOTSTRAP_VERSION="${PYENV_RPYTHON_VERSION}"
else
for version in $(pyenv-versions --bare | sort -r); do
if [[ "${version}" == "2.7"* ]]; then
if [[ "${version}" =~ ^(2\.7|pypy2\.7) ]]; then
PYENV_BOOTSTRAP_VERSION="$version"
break
fi
@ -275,7 +275,7 @@ for i in "${!DEFINITIONS[@]}"; do
fi
done
else
echo "pyenv-install: $VERSION_NAME: PyPy requires Python 2.7 to build from source." >&2
echo "pyenv-install: $VERSION_NAME: PyPy requires Python 2.7 to build from source. You can specify the version to use by setting the PYENV_BOOTSTRAP_VERSION environment variable." >&2
exit 1
fi
;;

View File

@ -0,0 +1,64 @@
#!/usr/bin/env bash
#
# Summary: Install Python build prerequisites on Debian-based systems
#
# Usage: pyenv install-prerequisites [-a|--all]
#
# -a/--all Also install optional dependencies (for rarely used modules)
#
set -e
[ -n "$PYENV_DEBUG" ] && set -x
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
echo --all
exit
fi
usage() {
pyenv-help install-prerequisites 2>/dev/null
[ -z "$1" ] || exit "$1"
}
all=
while (($#)); do
case "$1" in
-h|--help)
usage 0
;;
-a|--all)
all=1
;;
*)
usage 1 >&2
;;
esac
shift
done
if ! command -v apt-get >/dev/null; then
echo "pyenv: installing build prerequisites is not supported on this system" >&2
exit 1
fi
prerequisites=(
make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev
libsqlite3-dev curl git llvm libncurses5-dev libncursesw5-dev xz-utils
tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libzstd-dev
)
optional=(
libgdbm-dev
)
if [ "$(id -u)" -eq 0 ]; then
apt_get=(apt-get)
elif command -v sudo >/dev/null; then
apt_get=(sudo apt-get)
else
echo "pyenv: sudo is required to install build prerequisites" >&2
exit 1
fi
"${apt_get[@]}" update -q
"${apt_get[@]}" install -yq "${prerequisites[@]}" ${all:+"${optional[@]}"}

View File

@ -14,7 +14,7 @@
# -g/--debug Build a debug version
#
PYTHON_BUILD_VERSION="2.8.4"
PYTHON_BUILD_VERSION="2.8.7"
OLDIFS="$IFS"
@ -425,6 +425,18 @@ http_head_aria2c() {
aria2c --dry-run --no-conf=true ${ARIA2_OPTS} "$1" >&4 2>&1
}
# Shows interactive output of a program
# while also logging it.
# Usage:
# command <switches forcing interactive output to non-terminal> 2>&1 | interactive_output; rc=${PIPESTATUS[0]}
interactive_output() {
if [ -n "$VERBOSE" ]; then
cat >> "$LOG_PATH"
else
tee -a "$LOG_PATH" >&3
fi
}
http_get_aria2c() {
# aria2c always treats -o argument as a relative path
local out dir_out;
@ -447,7 +459,26 @@ http_get_aria2c() {
dir_out="$HOME"
fi
if aria2c --allow-overwrite=true --no-conf=true -d "${dir_out}" -o "${out}" ${ARIA2_OPTS} "$1" >&4; then
local aria2c_progress=
# aria2c prints status to stdout rather than stderr.
# As a result, when stdout is redirected, it becomes line-buffered,
# and status messages (which are divided by CRs) are not seen
# until a summary message with some LFs is printed.
# So we have to print summaries often as a crutch.
# But need to make the interval reasonable because each summary is
# several lines long which, made too often, becomes obnoxious.
[ -t 3 ] && aria2c_progress="--summary-interval=5"
local cmd
cmd=(aria2c --allow-overwrite=true --no-conf=true -d "${dir_out}" -o "${out}" ${aria2c_progress} ${ARIA2_OPTS} "$1")
if [ -t 3 ]; then
"${cmd[@]}" 2>&1 | interactive_output
ret=${PIPESTATUS[0]}
else
"${cmd[@]}" >&4
ret=$?
fi
if [ "$ret" -eq 0 ]; then
[ -n "$2" ] || cat "${dir_out:-.}/${out}"
else
false
@ -471,7 +502,21 @@ http_get_curl() {
local curl_is_snap;
if [[ $(command -v curl) == "/snap/"* ]]; then curl_is_snap=1; fi
if [[ -n $2 && -n $curl_is_snap ]]; then out="$HOME/$(basename "$2")"; else out="$2"; fi
curl -q -o "${out:--}" -sSLf ${CURL_OPTS} "$1" || return $?
local curl_progress=
if [ -t 3 ]; then
curl_progress="--no-silent"
fi
local cmd
cmd=(curl -q -o "${out:--}" -sSLf ${CURL_OPTS} ${curl_progress} "$1")
if [ -t 3 ]; then
exec 5>&1
"${cmd[@]}" 3>&1 1>&5 2>&3 3>&- | interactive_output
ret=${PIPESTATUS[0]}
exec 5>&-
[ "$ret" -eq 0 ] || return "$ret"
else
"${cmd[@]}" || return $?
fi
if [[ -n $out && -n $curl_is_snap ]]; then mv "$out" "$2"; fi
}
@ -480,7 +525,21 @@ http_head_wget() {
}
http_get_wget() {
wget -nv ${WGET_OPTS} -O "${2:--}" "$1"
local wget_progress="-nv"
if [ -t 3 ]; then
wget_progress="-nv --show-progress --progress=bar:force:noscroll"
fi
local cmd
cmd=(wget ${WGET_OPTS} ${wget_progress} -O "${2:--}" "$1")
if [ -t 3 ]; then
exec 5>&1
"${cmd[@]}" 3>&1 1>&5 2>&3 3>&- | interactive_output
ret=${PIPESTATUS[0]}
exec 5>&-
return "$ret"
else
"${cmd[@]}"
fi
}
fetch_tarball() {
@ -873,6 +932,7 @@ build_package_standard_build() {
if [ "$package_var_name" = "PYTHON" ]; then
if can_use_homebrew; then
configured_with_openssl || use_homebrew_openssl || true
use_custom_tcltk || use_homebrew_tcltk || true
use_homebrew_readline || true
use_homebrew_ncurses || true
@ -885,6 +945,7 @@ build_package_standard_build() {
fi
fi
if can_use_macports; then
configured_with_openssl || use_macports_openssl || true
use_custom_tcltk || true
use_macports_readline || true
use_macports_ncurses || true
@ -996,27 +1057,29 @@ build_package_jython_builder() {
( cd "dist" && build_package_jython )
}
build_package_pyston2_2() {
# currently supported version 2.2 and 2.3
build_package_pyston() {
build_package_copy
mkdir -p "${PREFIX_PATH}/bin" "${PREFIX_PATH}/lib"
local bin
shopt -s nullglob
for bin in "bin/"*; do
if [ -f "${bin}" ] && [ -x "${bin}" ] && [ ! -L "${bin}" ]; then
case "${bin##*/}" in
"pyston"* )
( cd "${PREFIX_PATH}/bin" && ln -fs "${bin##*/}" "python" )
;;
esac
fi
done
shopt -u nullglob
# Pyston tarballs provide an executable with a version-specific naming scheme
# and `pyston` and `pyston3` symlinks to it.
make_python_symlinks pyston
}
build_package_pyston() {
# currently supported version 2.3.1v2 and higher
build_package_copy
# Add missing `python', `pythonX' and `pythonX.Y' symlinks as per PEP 394.
make_python_symlinks() {
local seeder_basename version_suffix real_interpreter
local -a interpreter_names
seeder_basename="${1:?}"; shift
(($#)) && interpreter_names=("$@") || interpreter_names=(python)
local real_interpreter
real_interpreter=$(resolve_link "${PREFIX_PATH}/bin/$seeder_basename" || echo $seeder_basename)
# Use syntax accepted in both Py2 and Py3. Even though current Py2 holdouts (e.g. PyPy) support e.g. print()
version_suffix=$("${PREFIX_PATH}/bin/$seeder_basename" -c 'import sys; sys.stdout.write("%d.%d\n" % sys.version_info[:2])')
for interpreter_name in "${interpreter_names[@]}"; do
for name in "$interpreter_name" "$interpreter_name${version_suffix%.*}" "$interpreter_name${version_suffix}"; do
[[ -e "${PREFIX_PATH}/bin/$name" ]] || ln -fs "${real_interpreter}" "${PREFIX_PATH}/bin/$name"
done
done
}
build_package_ironpython() {
@ -1112,30 +1175,38 @@ pyston_architecture() {
# Note: not used by graalpy >= 23.3.0 anymore
build_package_graalpython() {
build_package_copy
ln -fs "${PREFIX_PATH}/bin/graalpython" "${PREFIX_PATH}/bin/python"
make_python_symlinks graalpython
}
build_package_pypy() {
build_package_copy
mkdir -p "${PREFIX_PATH}/bin" "${PREFIX_PATH}/lib"
local bin
shopt -s nullglob
for bin in "bin/"*; do
if [ -f "${bin}" ] && [ -x "${bin}" ] && [ ! -L "${bin}" ]; then
case "${bin##*/}" in
"libpypy"* )
( cd "${PREFIX_PATH}/lib" && ln -fs "../bin/${bin##*/}" "${bin##*/}" )
;;
"pypy"* )
( cd "${PREFIX_PATH}/bin" && ln -fs "${bin##*/}" "python" )
;;
esac
for bin in "bin/libpypy"*; do
if [[ -f "${bin}" && -x "${bin}" && ! -L "${bin}" ]]; then
ln -fs "../bin/${bin##*/}" "${PREFIX_PATH}/lib/${bin##*/}"
fi
done
# PyPy source builds may create only a pypy* executable with a version-sepecific name
local seeder= seeder_candidate
for seeder_candidate in "${PREFIX_PATH}/bin/"pypy*; do
if [[ -f $seeder_candidate && -x $seeder_candidate ]]; then
seeder="${seeder_candidate##*/}"
break
fi
done
shopt -u nullglob
[[ -n $seeder ]] || {
echo "python-build: Cannot find a valid PyPy executable in \`${PREFIX_PATH}/bin'" >&4
exit 1
}
make_python_symlinks "$seeder" pypy python
}
build_package_pypy_builder() {
use_homebrew_openssl || use_macports_openssl || true
if [ -f "rpython/bin/rpython" ]; then # pypy 2.x
if [ -z "${PYPY_OPTS}" ]; then
local PYPY_OPTS="--opt=jit --batch --make-jobs=$(num_cpu_cores)"
@ -1201,6 +1272,7 @@ anaconda_architecture() {
"aarch64" ) echo "Linux-aarch64" ;;
"i386" | "i486" | "i586" | "i686" | "i786" ) echo "Linux-x86" ;;
"ppc64le" ) echo "Linux-ppc64le" ;;
"riscv64" ) echo "Linux-riscv64" ;;
"x86_64" ) echo "Linux-x86_64" ;;
* ) return 1 ;;
esac
@ -1258,7 +1330,7 @@ cleanup_builtin_patches() {
fix_directory_permissions() {
# Ensure installed directories are not world-writable
find "$PREFIX_PATH" -type d \( -perm -020 -o -perm -002 \) -exec chmod go-w {} \;
find "$PREFIX_PATH" -type d \( -perm -020 -o -perm -002 \) -exec chmod go-w {} \+
}
require_java7() {
@ -1705,8 +1777,17 @@ build_package_mac_readline() {
build_package_standard "$@"
}
configured_with_openssl() {
local arg
for arg in ${CONFIGURE_OPTS} ${PYTHON_CONFIGURE_OPTS} "${PYTHON_CONFIGURE_OPTS_ARRAY[@]}"; do
[[ "$arg" =~ ^--with-openssl(=|$) ]] && return 0
done
return 1
}
has_broken_mac_openssl() {
is_mac || return 1
configured_with_openssl && return 1
local openssl_version="$(/usr/bin/openssl version 2>/dev/null || true)"
if [[ $openssl_version = "OpenSSL 0.9.8"?* || $openssl_version = "LibreSSL"* ]]; then
if can_use_homebrew; then
@ -2757,7 +2838,8 @@ else
BUILD_PATH="$PYTHON_BUILD_BUILD_PATH"
fi
exec 4<> "$LOG_PATH" # open the log file at fd 4
# Append mode needed to be able to `tee` to it at the same time
exec 4>> "$LOG_PATH"
if [ -n "$VERBOSE" ]; then
tail -f "$LOG_PATH" &
TAIL_PID=$!

View File

@ -89,6 +89,9 @@ def py_version(version):
# transition points:
# https://github.com/conda-forge/miniforge/blame/main/Miniforge3/construct.yaml
# look for "- python <version>" in non-pypy branch and which tag the commit is first in
if version_tuple_ >= (26,5,3):
# https://github.com/conda-forge/miniforge/commit/8ae029d5f17e34e93fec2d9bfe708ba9175adf08
return "314"
if version_tuple_ >= (26,1):
# https://github.com/conda-forge/miniforge/commit/0016367731e52c67234d6d0e7e6a24c6bf7673e4
return "313"

View File

@ -0,0 +1,221 @@
#!/usr/bin/env python3
"""Rudimentary script to add PyPY releases automagically.
Requires requests-html.
Checks the PyPy download archives for new versions,
then writes a build script for any which do not exist locally,
saving it to plugins/python-build/share/python-build.
Written and tested in *CPython* 3.9.6. PyPy3 compatibility is not
guaranteed, but it should work.
"""
from pathlib import Path
import argparse
import logging
import re
import sys
from requests_html import HTMLSession
# https://downloads.python.org/pypy/versions.json doesn't contain
# checksums, so using checksums.html instead.
# More convenient than calculating them from downloads.
PYPY_REPO = "https://downloads.python.org/pypy/"
PYPY_CHECKSUMS = "https://pypy.org/checksums.html"
here = Path(__file__).resolve()
OUT_DIR: Path = here.parent.parent / "share" / "python-build"
EXCLUDED_RELEASES = [] # none for now
# Note: Remember to escape/unescape curly braces when editing the bash script
SCRIPT_BIN = """
VERSION='{version_pypy}'
PYVER='{version_python}'
# https://www.pypy.org/checksums.html
aarch64_hash={checksum_aarch64}
linux32_hash={checksum_linux32}
linux64_hash={checksum_linux64}
osarm64_hash={checksum_osarm64}
osx64_hash={checksum_osx64}
### end of manual settings - following lines same for every download
function err_no_binary {{
local archmsg="${{1}}"
local ver="pypy${{PYVER}}-v${{VERSION}}-src"
local url="https://downloads.python.org/pypy/${{ver}}.tar.{file_ext}"
{{ echo
colorize 1 "ERROR"
echo ": The binary distribution of PyPy is not available for ${{archmsg}}."
echo "try '${{url}}' to build from source."
echo
}} >&2
exit 1
}}
function pypy_pkg_data {{
# pypy architecture tag
local ARCH="${{1}}"
# defaults
local cmd='install_package' # use {file_ext}
local pkg="${{ARCH}}" # assume matches
local ext='tar.{file_ext}'
local hash='' # undefined
# select the hash, fix pkg if not match ARCH
case "${{ARCH}}" in
'linux-aarch64' )
hash="${{aarch64_hash}}"
pkg='aarch64'
;;
'linux' )
hash="${{linux32_hash}}"
pkg='linux32'
;;
'linux64' )
hash="${{linux64_hash}}"
;;
'osarm64' )
hash="${{osarm64_hash}}"
pkg='macos_arm64'
;;
'osx64' )
if require_osx_version "10.15"; then
hash="${{osx64_hash}}"
pkg='macos_x86_64'
else
err_no_binary "${{ARCH}}, OS X < 10.15"
fi
;;
* )
err_no_binary "${{ARCH}}"
;;
esac
local basever="pypy${{PYVER}}-v${{VERSION}}"
local baseurl="https://downloads.python.org/pypy/${{basever}}"
# result - command, package dir, url+hash
echo "${{cmd}}" "${{basever}}-${{pkg}}" "${{baseurl}}-${{pkg}}.${{ext}}#${{hash}}"
}}
# determine command, package directory, url+hash
declare -a pd="$(pypy_pkg_data "$(pypy_architecture 2>/dev/null || true)")"
# install
${{pd[0]}} "${{pd[1]}}" "${{pd[2]}}" 'pypy' "verify_py${{PYVER//./}}" '{ensurepip}'
""".lstrip()
SCRIPT_SRC = """
VERSION='{version_pypy}'
PYVER='{version_python}'
# https://www.pypy.org/checksums.html
hash={checksum_src}
### end of manual settings - following lines same for every download
ver="pypy${{PYVER}}-v${{VERSION}}-src"
url="https://downloads.python.org/pypy/${{ver}}.tar.{file_ext}"
prefer_openssl11
install_package "openssl-1.1.1f" "https://www.openssl.org/source/openssl-1.1.1f.tar.gz#186c6bfe6ecfba7a5b48c47f8a1673d0f3b0e5ba2e25602dd23b629975da3f35" mac_openssl --if has_broken_mac_openssl
install_package "${{ver}}" "${{url}}#${{hash}}" 'pypy_builder' "verify_py${{PYVER//./}}" '{ensurepip}'
""".lstrip()
args = None
logger = logging.getLogger(__name__)
def main() -> bool:
html_session = HTMLSession()
response = html_session.get(PYPY_CHECKSUMS)
page = response.html
checksum_blocks = page.find("pre.literal-block")
for csum_block in checksum_blocks:
python_version, pypy_version = parse_pypy_ver(csum_block.text)
py_it = f"pypy{python_version}-{pypy_version}"
if py_it not in EXCLUDED_RELEASES:
vbin_path = OUT_DIR.joinpath(py_it)
vsrc_path = OUT_DIR.joinpath(py_it+"-src")
kwargs = None
for ps in ((vbin_path, SCRIPT_BIN), (vsrc_path, SCRIPT_SRC)):
if not ps[0].is_file():
kwargs = kwargs or parse_checksums_ext(csum_block.text)
code = ps[1].format(
version_pypy=pypy_version,
version_python=python_version,
ensurepip="ensurepip" if not python_version == "2.7" else "ensurepip_lt21",
**kwargs # which are:
# checksum_aarch64
# checksum_linux32
# checksum_linux64
# checksum_osarm64
# checksum_osx64
# checksum_src
# file_ext
)
if not args.dry_run:
with open(file=ps[0], mode="w", encoding="utf-8") as f:
f.write(code)
f.close()
else:
print(f"---- DRY RUN SCRIPT FOR {ps[0]} ----")
print(code)
def parse_pypy_ver(csum_block:str) -> tuple[str,str]:
"""Gets the PyPy name from the checksum block."""
match = re.findall(r"pypy([0-9]\.[0-9]+)\-v([0-9]\.[0-9]\.[0-9]+)", csum_block)
match = set(match)
if len(match) == 1:
return match.pop()
return ""
def parse_checksums_ext(csum_block:str) -> dict:
"""Gets the checksums and ext for each platform (excluding win64) from the checksum block."""
chksm_ex = {
r"aarch64": "",
r"linux32": "",
r"linux64": "",
r"macos_arm64": "",
r"macos_x86_64": "",
r"src": "",
}
ext = set()
for ex in chksm_ex:
match = re.findall(r"([a-z0-9]+) pypy[0-9]\.[0-9]+\-v[0-9]\.[0-9]\.[0-9]+-"+ex+r".tar.(gz|bz2)", csum_block)
chksm_ex[ex] = match[0][0]
ext.add(match[0][1])
# if both gz and bz2, prefer bz2
ext = ext.pop() if len(ext) == 1 else "bz2"
return {
"checksum_aarch64": chksm_ex["aarch64"],
"checksum_linux32": chksm_ex["linux32"],
"checksum_linux64": chksm_ex["linux64"],
"checksum_osarm64": chksm_ex["macos_arm64"],
"checksum_osx64": chksm_ex["macos_x86_64"],
"checksum_src": chksm_ex["src"],
"file_ext": ext
}
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"-d", "--dry-run", action="store_true",
help="Do not write scripts, just report them to stdout",
)
args = parser.parse_args()
#sys.excepthook seems to have no effect in Github Actions
try:
sys.exit(main())
except Exception:
logging.exception("Unhandled exception occurred")
sys.exit(2)

View File

@ -0,0 +1,27 @@
# source this in Bash
# cd to git repo of CPython
_python_build_dir=$(cd "${BASH_SOURCE%/*}/.."; pwd -P)
backport() {
[[ $# -lt 2 ]] && { echo "usage: $FUNCNAME <commit_hash> <CPython version>..." >&2; return 1; }
(set -euxo pipefail
sha="${1:?}"
shift
for b; do
git checkout "Branch_v$b" || git checkout -b "Branch_v$b" "v$b"
git cherry-pick "$sha"
git format-patch -1
patch_dir="$_python_build_dir/share/python-build/$b/Python-$b"
shopt -s nullglob
pp=("$patch_dir"/*.patch)
patch_offset=${#pp[@]}
shopt -u nullglob
unset pp
mkdir -p "$patch_dir"
for f in *.patch; do
mv "$f" "$patch_dir/$(printf '%04d' $((${f::4}+patch_offset)))${f:4}"
done
done)
}

View File

@ -0,0 +1,9 @@
prefer_openssl3
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
install_package "openssl-3.6.5" "https://github.com/openssl/openssl/releases/download/openssl-3.6.5/openssl-3.6.5.tar.gz#a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.10.22" "https://www.python.org/ftp/python/3.10.22/Python-3.10.22.tar.xz#c61fe9b1a1a7ec2a0b0388e664187c378a5325a89e3606d220abf5bdfccb2543" standard verify_py310 copy_python_gdb ensurepip
else
install_package "Python-3.10.22" "https://www.python.org/ftp/python/3.10.22/Python-3.10.22.tgz#9448b34d16f8e3db0964ac3ed9fb283197747543c2c021f283ffd2c8b7287357" standard verify_py310 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,11 @@
prefer_openssl3
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
export PYTHON_BUILD_TCLTK_USE_PKGCONFIG=1
install_package "openssl-3.6.5" "https://github.com/openssl/openssl/releases/download/openssl-3.6.5/openssl-3.6.5.tar.gz#a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.11.17" "https://www.python.org/ftp/python/3.11.17/Python-3.11.17.tar.xz#bfb74ad39efae27cda510f134ab408e00f9992c56851cfc0b1cdb5646da11599" standard verify_py311 copy_python_gdb ensurepip
else
install_package "Python-3.11.17" "https://www.python.org/ftp/python/3.11.17/Python-3.11.17.tgz#53cdee63ac4bf12387b7b33a53d3b1f8f4941cad73807a7b4fe91bb001ef004a" standard verify_py311 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,11 @@
prefer_openssl3
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
export PYTHON_BUILD_TCLTK_USE_PKGCONFIG=1
install_package "openssl-3.6.5" "https://github.com/openssl/openssl/releases/download/openssl-3.6.5/openssl-3.6.5.tar.gz#a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.12.15" "https://www.python.org/ftp/python/3.12.15/Python-3.12.15.tar.xz#c2c4321961fab0fb999d66e0cecf521c2ab3994c7992873ea99e306c1094fd5a" standard verify_py312 copy_python_gdb ensurepip
else
install_package "Python-3.12.15" "https://www.python.org/ftp/python/3.12.15/Python-3.12.15.tgz#de1a241a519e0a3374fea98988d0b52c886743f9d953f23be8269cc7b59c5fab" standard verify_py312 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,11 @@
prefer_openssl3
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
export PYTHON_BUILD_TCLTK_USE_PKGCONFIG=1
install_package "openssl-3.6.5" "https://github.com/openssl/openssl/releases/download/openssl-3.6.5/openssl-3.6.5.tar.gz#a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.13.16" "https://www.python.org/ftp/python/3.13.16/Python-3.13.16.tar.xz#f4b1bfb3c79b5bb11b8d228a12504163b4c0dab4d679828d8f5f26b6cb6ab35d" standard verify_py313 copy_python_gdb ensurepip
else
install_package "Python-3.13.16" "https://www.python.org/ftp/python/3.13.16/Python-3.13.16.tgz#cfac63bddf956deafb1172ca131ae5dcaafd6f95056086e233fca205593ed427" standard verify_py313 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,2 @@
export PYTHON_BUILD_FREE_THREADING=1
source "${BASH_SOURCE[0]%t}"

View File

@ -0,0 +1,11 @@
prefer_openssl3_to_4
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
export PYTHON_BUILD_TCLTK_USE_PKGCONFIG=1
install_package "openssl-4.0.3" "https://github.com/openssl/openssl/releases/download/openssl-4.0.3/openssl-4.0.3.tar.gz#325b5c806167c13b40b1ffeadfe0248197c00eccc4cf123ec1e28d2d2fd216d9" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.14.8" "https://www.python.org/ftp/python/3.14.8/Python-3.14.8.tar.xz#c2215904f02b175596dc49351585104f4bc20341e1c47378b26a2c274360ce73" standard verify_py314 copy_python_gdb ensurepip
else
install_package "Python-3.14.8" "https://www.python.org/ftp/python/3.14.8/Python-3.14.8.tgz#a65b20a728f169f4e66ae143f40b1bd3d33c38d770251663f627c9767b79b210" standard verify_py314 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,2 @@
export PYTHON_BUILD_FREE_THREADING=1
source "${BASH_SOURCE[0]%t}"

View File

@ -1,11 +0,0 @@
prefer_openssl3
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
export PYTHON_BUILD_TCLTK_USE_PKGCONFIG=1
install_package "openssl-4.0.1" "https://github.com/openssl/openssl/releases/download/openssl-4.0.1/openssl-4.0.1.tar.gz#2db3f3a0d6ea4b59e1f094ace2c8cd536dffb87cdc39084c5afa1e6f7f37dd09" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.15.0rc1" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0rc1.tar.xz#f84dad680ab2147417d2739355c2678f0f9acffe4ae8ef77895de1454b384b07" standard verify_py315 copy_python_gdb ensurepip
else
install_package "Python-3.15.0rc1" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0rc1.tgz#32c2b9878bbd6ac3ceb138c5b6c880345ce9d33388b399378c0da6fc7cb3bfbc" standard verify_py315 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,11 @@
prefer_openssl3
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
export PYTHON_BUILD_TCLTK_USE_PKGCONFIG=1
install_package "openssl-4.0.2" "https://github.com/openssl/openssl/releases/download/openssl-4.0.2/openssl-4.0.2.tar.gz#736b467530f916737b7031310ccb21d8218c6229e61e8e160cd1d3458cd543a8" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.3" "https://ftpmirror.gnu.org/readline/readline-8.3.tar.gz#fe5383204467828cd495ee8d1d3c037a7eba1389c22bc6a041f627976f9061cc" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.15.0rc2" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0rc2.tar.xz#8d93af5eaaaea5adfd41bd786a7ba3f03f2ad1ab57c6a65e0b963deab91d5ad7" standard verify_py315 copy_python_gdb ensurepip
else
install_package "Python-3.15.0rc2" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0rc2.tgz#164dbb80f5e1fdd8768387724bfa014da1000401b2015d872a2396c8b858b829" standard verify_py315 copy_python_gdb ensurepip
fi

View File

@ -0,0 +1,2 @@
export PYTHON_BUILD_FREE_THREADING=1
source "${BASH_SOURCE[0]%t}"

View File

@ -0,0 +1,50 @@
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
VERSION='25.3.4.1'
RELEASE_TAG='graal-25.3.4'
colorize 1 "GraalPy 23.1 and later installed by python-build use the faster Oracle GraalVM distribution" && echo
colorize 1 "Oracle GraalVM uses the GFTC license, which is free for development and production use, see https://medium.com/graalvm/161527df3d76" && echo
colorize 1 "The GraalVM Community Edition variant of GraalPy is also available, under the name graalpy3.13-community-${VERSION}" && echo
graalpy_arch="$(graalpy_architecture 2>/dev/null || true)"
case "$graalpy_arch" in
"linux-amd64" )
checksum="23515b4e659d645960517b0ceedb90faa84fcb01f0f4497beca5868a1b1ae3ea"
;;
"linux-aarch64" )
checksum="53b80e284e444540ae7cb67349af3dd8f6c1848fbf6abb5051742ac745f1f33d"
;;
"macos-aarch64" )
checksum="8ac33b5a5d0ee872751595211508fd826f47051ff6e6614032aed1de071eebab"
;;
* )
{ echo
colorize 1 "ERROR"
echo ": No binary distribution of GraalPy is available for $(uname -sm)."
echo
} >&2
exit 1
;;
esac
install_package "graalpy3.13-${VERSION}" "https://github.com/oracle/graalpython/releases/download/${RELEASE_TAG}/graalpy3.13-${VERSION}-${graalpy_arch}.tar.gz#${checksum}" "copy" ensurepip

View File

@ -0,0 +1,50 @@
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
VERSION='25.4.4'
RELEASE_TAG='graal-25.4.4'
colorize 1 "GraalPy 23.1 and later installed by python-build use the faster Oracle GraalVM distribution" && echo
colorize 1 "Oracle GraalVM uses the GFTC license, which is free for development and production use, see https://medium.com/graalvm/161527df3d76" && echo
colorize 1 "The GraalVM Community Edition variant of GraalPy is also available, under the name graalpy3.13-community-${VERSION}" && echo
graalpy_arch="$(graalpy_architecture 2>/dev/null || true)"
case "$graalpy_arch" in
"linux-amd64" )
checksum="8b72e6e513d06976e5c8e051228d69d541fde76d05d5f907eaef4bb31db83af4"
;;
"linux-aarch64" )
checksum="1323dc064583efd1d6b696d3a9f9e4b1ff8facd0f7cc2b69fe0a0bf7ef06ea1a"
;;
"macos-aarch64" )
checksum="aacd819b5c3b6889b6a6275d8009ec1e8e3fe27cf7b77265710a1c9ea931bedd"
;;
* )
{ echo
colorize 1 "ERROR"
echo ": No binary distribution of GraalPy is available for $(uname -sm)."
echo
} >&2
exit 1
;;
esac
install_package "graalpy3.13-${VERSION}" "https://github.com/oracle/graalpython/releases/download/${RELEASE_TAG}/graalpy3.13-${VERSION}-${graalpy_arch}.tar.gz#${checksum}" "copy" ensurepip

View File

@ -0,0 +1,45 @@
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
VERSION='25.3.4.1'
RELEASE_TAG='graal-25.3.4'
graalpy_arch="$(graalpy_architecture 2>/dev/null || true)"
case "$graalpy_arch" in
"linux-amd64" )
checksum="5e239616c8352488585f58d33991d262e8c627483741778ad43d39a4830176ad"
;;
"linux-aarch64" )
checksum="13007ecfe8180e91f1060de60a2ba6ce88f38faa4a36574b34143a492e8c660e"
;;
"macos-aarch64" )
checksum="e2cf7ae230478ad8d100ad868f75e3addb174d81e7f550322ea5e74cab066644"
;;
* )
{ echo
colorize 1 "ERROR"
echo ": No binary distribution of GraalPy is available for $(uname -sm)."
echo
} >&2
exit 1
;;
esac
install_package "graalpy3.13-community-${VERSION}" "https://github.com/oracle/graalpython/releases/download/${RELEASE_TAG}/graalpy3.13-community-${VERSION}-${graalpy_arch}.tar.gz#${checksum}" "copy" ensurepip

View File

@ -0,0 +1,45 @@
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
VERSION='25.4.4'
RELEASE_TAG='graal-25.4.4'
graalpy_arch="$(graalpy_architecture 2>/dev/null || true)"
case "$graalpy_arch" in
"linux-amd64" )
checksum="a038c8fa650f3bd17046f3cb8609b271e07b0e21fdb8527f10726beee442b93d"
;;
"linux-aarch64" )
checksum="5d0fab1a2f541b387dbf3fbf6b123a5836a0bc99937076f34aeb29282ee246c1"
;;
"macos-aarch64" )
checksum="dce08327e8ccb48423cc50f72a5137d4ff8c9da8ff7319525a69e2e68ac637cd"
;;
* )
{ echo
colorize 1 "ERROR"
echo ": No binary distribution of GraalPy is available for $(uname -sm)."
echo
} >&2
exit 1
;;
esac
install_package "graalpy3.13-community-${VERSION}" "https://github.com/oracle/graalpython/releases/download/${RELEASE_TAG}/graalpy3.13-community-${VERSION}-${graalpy_arch}.tar.gz#${checksum}" "copy" ensurepip

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py310_26.7.1-0-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py310_26.7.1-0-Linux-aarch64.sh#caf3e9652f32f40d8755c22678c315f6305c04f68c47ff3e76e625d26f17f59b" "miniconda" verify_py310
;;
"Linux-x86_64" )
install_script "Miniconda3-py310_26.7.1-0-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py310_26.7.1-0-Linux-x86_64.sh#acc1cda57155ecacb854b49bb5875eadb6500d1ea70176f44e8b7a321f59d620" "miniconda" verify_py310
;;
"MacOSX-arm64" )
install_script "Miniconda3-py310_26.7.1-0-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py310_26.7.1-0-MacOSX-arm64.sh#07b3e50a23a39db29c8dde820a4ab662532086a5da849a466f582f180115bce9" "miniconda" verify_py310
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py310_26.7.1-1-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py310_26.7.1-1-Linux-aarch64.sh#1a77b0376464ab4a35df7ec033ee86875b9a932d29d985ce5bc2e4a16790e153" "miniconda" verify_py310
;;
"Linux-x86_64" )
install_script "Miniconda3-py310_26.7.1-1-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py310_26.7.1-1-Linux-x86_64.sh#fb1af4c45e6e73fe193c2398b4346b1e45522f729cdfccfdb18f6c765954dbd9" "miniconda" verify_py310
;;
"MacOSX-arm64" )
install_script "Miniconda3-py310_26.7.1-1-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py310_26.7.1-1-MacOSX-arm64.sh#56c8b663e389605596fef71797367f30fa60ddc3022630c1bca309a09e833661" "miniconda" verify_py310
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py311_26.7.1-0-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py311_26.7.1-0-Linux-aarch64.sh#f20e0a792cea183252f832f2ba68b05f34ddb2f728d97c64a2adf04ebaaca62d" "miniconda" verify_py311
;;
"Linux-x86_64" )
install_script "Miniconda3-py311_26.7.1-0-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py311_26.7.1-0-Linux-x86_64.sh#b5e7fa2d712bfc4b2d1d300e3ebbd9064491420efdb520753ab4e2e10f09ed75" "miniconda" verify_py311
;;
"MacOSX-arm64" )
install_script "Miniconda3-py311_26.7.1-0-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py311_26.7.1-0-MacOSX-arm64.sh#6415f748347a56c7b4a60271aad7bb85b8365f00aae69eacc2cd1612cd8955ac" "miniconda" verify_py311
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py311_26.7.1-1-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py311_26.7.1-1-Linux-aarch64.sh#3dec21b8c8612be0fdff92938c010752eb2ee46d413b74cac68d4c9547270937" "miniconda" verify_py311
;;
"Linux-x86_64" )
install_script "Miniconda3-py311_26.7.1-1-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py311_26.7.1-1-Linux-x86_64.sh#a6f98e6e19d5b7897ae887cd6af931eb863459f86ffd1a09cc370124cab0993e" "miniconda" verify_py311
;;
"MacOSX-arm64" )
install_script "Miniconda3-py311_26.7.1-1-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py311_26.7.1-1-MacOSX-arm64.sh#da6322bf9a213536df5ce630da2a249b9fb6d433f439b84be07003a790be6be6" "miniconda" verify_py311
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py312_26.7.1-0-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py312_26.7.1-0-Linux-aarch64.sh#391edcfaef0e70b7047834a86e48f5686eb0fe1e7612a086ca73e0084ffea45f" "miniconda" verify_py312
;;
"Linux-x86_64" )
install_script "Miniconda3-py312_26.7.1-0-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py312_26.7.1-0-Linux-x86_64.sh#3d33f72fcb35134ab68a7775021a0ee6d22b8a4dd9139d9c9798792e933ee132" "miniconda" verify_py312
;;
"MacOSX-arm64" )
install_script "Miniconda3-py312_26.7.1-0-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py312_26.7.1-0-MacOSX-arm64.sh#1d9cb2f5c6ea2ce48711ba42f62c2b9e14094a8ef9781c98981bb9b9d9813862" "miniconda" verify_py312
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py312_26.7.1-1-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py312_26.7.1-1-Linux-aarch64.sh#f6d64a1565e713429683720f59dd6661f5131c2f959a4830438eb1969cde23f7" "miniconda" verify_py312
;;
"Linux-x86_64" )
install_script "Miniconda3-py312_26.7.1-1-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py312_26.7.1-1-Linux-x86_64.sh#b27f60ab63e77eeab50a5417c989120f767e863df32400190d4c7262369f8695" "miniconda" verify_py312
;;
"MacOSX-arm64" )
install_script "Miniconda3-py312_26.7.1-1-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py312_26.7.1-1-MacOSX-arm64.sh#fc46408196d7383fcb03e1235b6891a5983fa3e0f56877eec7b27950130e7605" "miniconda" verify_py312
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py313_26.7.1-0-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py313_26.7.1-0-Linux-aarch64.sh#e556d9805217d9798fa5fca0e190905c218025b552cee1fc2526dc55e498744d" "miniconda" verify_py313
;;
"Linux-x86_64" )
install_script "Miniconda3-py313_26.7.1-0-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py313_26.7.1-0-Linux-x86_64.sh#3ad92b3b7fc3c82d6b649f76c688c89ae70b3eb267cc6bee8e657084a0ee3748" "miniconda" verify_py313
;;
"MacOSX-arm64" )
install_script "Miniconda3-py313_26.7.1-0-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py313_26.7.1-0-MacOSX-arm64.sh#1dfed26e3e7fe750a5626734cf9b4edb0ca0a55f3e9e395dba3ef8daeb79ecb5" "miniconda" verify_py313
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py313_26.7.1-1-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py313_26.7.1-1-Linux-aarch64.sh#669e8f11248e97473ff058d97eb02b6c8e67f6c853e230f7a88cce95303c9fce" "miniconda" verify_py313
;;
"Linux-x86_64" )
install_script "Miniconda3-py313_26.7.1-1-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py313_26.7.1-1-Linux-x86_64.sh#c26cbbd996d5ada0bec054b49a37fab690e2f91125701e458df6cca73da9482b" "miniconda" verify_py313
;;
"MacOSX-arm64" )
install_script "Miniconda3-py313_26.7.1-1-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py313_26.7.1-1-MacOSX-arm64.sh#689068fd5c3aaeb0137aad1202dd1743d4d8b62cf3b4b487e53787ef8a04feae" "miniconda" verify_py313
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py314_26.7.1-0-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py314_26.7.1-0-Linux-aarch64.sh#f1f9342b74c24e320f927f1d315784fa9f8ea3124aab9ead2f188ee9771f4430" "miniconda" verify_py314
;;
"Linux-x86_64" )
install_script "Miniconda3-py314_26.7.1-0-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py314_26.7.1-0-Linux-x86_64.sh#f87bfab5ccdcb80894518f868c80cc321ac1ebc7d18d07792d59895bbc30b313" "miniconda" verify_py314
;;
"MacOSX-arm64" )
install_script "Miniconda3-py314_26.7.1-0-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py314_26.7.1-0-MacOSX-arm64.sh#933860616eff59f858f94ee086be1a645b8d1710cf449a078d22de14e8755468" "miniconda" verify_py314
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
export CONDA_PLUGINS_AUTO_ACCEPT_TOS=true
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniconda3-py314_26.7.1-1-Linux-aarch64" "https://repo.anaconda.com/miniconda/Miniconda3-py314_26.7.1-1-Linux-aarch64.sh#e31545afd7462d3c9c33b154c7a101c5acb5e01b69380b6994651aead6942893" "miniconda" verify_py314
;;
"Linux-x86_64" )
install_script "Miniconda3-py314_26.7.1-1-Linux-x86_64" "https://repo.anaconda.com/miniconda/Miniconda3-py314_26.7.1-1-Linux-x86_64.sh#e8b25b92b262499141c5bd57a98d3c008024185fa951494b9cd9b6d94e72338b" "miniconda" verify_py314
;;
"MacOSX-arm64" )
install_script "Miniconda3-py314_26.7.1-1-MacOSX-arm64" "https://repo.anaconda.com/miniconda/Miniconda3-py314_26.7.1-1-MacOSX-arm64.sh#9bdf85d31ea3b4b85ef26b2762d68e2d849fdd38b608fb5272127acef802ff75" "miniconda" verify_py314
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniconda is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,25 @@
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniforge3-26.5.3-0-Linux-aarch64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.5.3-0/Miniforge3-26.5.3-0-Linux-aarch64.sh#0391e42075a7632e9665d6e728387ee6b905f6c3e704d3513e1c1133d0d69b89" "miniconda" verify_py314
;;
"Linux-ppc64le" )
install_script "Miniforge3-26.5.3-0-Linux-ppc64le.sh" "https://github.com/conda-forge/miniforge/releases/download/26.5.3-0/Miniforge3-26.5.3-0-Linux-ppc64le.sh#a77ac9485c7ae7287b2c8eaa38caf44d661509eb0134643f10a7e816ce414ac2" "miniconda" verify_py314
;;
"Linux-x86_64" )
install_script "Miniforge3-26.5.3-0-Linux-x86_64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.5.3-0/Miniforge3-26.5.3-0-Linux-x86_64.sh#14db468222ad564658656f769506056209b6dc375f5e7dfd31eb5ebbf08fa529" "miniconda" verify_py314
;;
"MacOSX-arm64" )
install_script "Miniforge3-26.5.3-0-MacOSX-arm64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.5.3-0/Miniforge3-26.5.3-0-MacOSX-arm64.sh#0d765919d3ccfd1f89147aa1cf8133bfc55b3a3c13f5bacdcc091c33132fddd2" "miniconda" verify_py314
;;
"MacOSX-x86_64" )
install_script "Miniforge3-26.5.3-0-MacOSX-x86_64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.5.3-0/Miniforge3-26.5.3-0-MacOSX-x86_64.sh#0266a7bfeb12165286133145717bef0d88070f1b76710beb6a62fec4e88371a1" "miniconda" verify_py314
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniforge is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,28 @@
case "$(anaconda_architecture 2>/dev/null || true)" in
"Linux-aarch64" )
install_script "Miniforge3-26.7.2-0-Linux-aarch64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.7.2-0/Miniforge3-26.7.2-0-Linux-aarch64.sh#89b786c8d2c8b0fda7553914c1314ae4ddaa094503802f279377b19ac4463cb2" "miniconda" verify_py314
;;
"Linux-ppc64le" )
install_script "Miniforge3-26.7.2-0-Linux-ppc64le.sh" "https://github.com/conda-forge/miniforge/releases/download/26.7.2-0/Miniforge3-26.7.2-0-Linux-ppc64le.sh#466e6af6766fe3d9aea18a7a6431d480f3a64995d53e8cbd438ca5a064b2c945" "miniconda" verify_py314
;;
"Linux-riscv64" )
install_script "Miniforge3-26.7.2-0-Linux-riscv64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.7.2-0/Miniforge3-26.7.2-0-Linux-riscv64.sh#a82efd1197849cd6755c080bd883ed376eda09080f52bfe9051912afdd05c281" "miniconda" verify_py314
;;
"Linux-x86_64" )
install_script "Miniforge3-26.7.2-0-Linux-x86_64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.7.2-0/Miniforge3-26.7.2-0-Linux-x86_64.sh#281b0ac7d550802efc81af633225a5e6116d29ae72f3ab4eae7168c3931a4c05" "miniconda" verify_py314
;;
"MacOSX-arm64" )
install_script "Miniforge3-26.7.2-0-MacOSX-arm64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.7.2-0/Miniforge3-26.7.2-0-MacOSX-arm64.sh#d70bfa2e97afcda96927c9b9ca0e2316cb7750e4ce651c94388267cbe9588711" "miniconda" verify_py314
;;
"MacOSX-x86_64" )
install_script "Miniforge3-26.7.2-0-MacOSX-x86_64.sh" "https://github.com/conda-forge/miniforge/releases/download/26.7.2-0/Miniforge3-26.7.2-0-MacOSX-x86_64.sh#b00e7798658f92721a3ae2f6b9832695ffc6baf07758894d726268055359f6c5" "miniconda" verify_py314
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of Miniforge is not available for $(anaconda_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
;;
esac

View File

@ -0,0 +1,109 @@
From 639cdfe83c371bcc87969cb6db926bc360135ac9 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 1baa145e3ed..b67faee87a8 100755
--- a/configure
+++ b/configure
@@ -11709,7 +11709,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11719,7 +11719,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -11762,6 +11762,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 3e6c07c2793..c431bf42398 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3680,7 +3680,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3690,7 +3690,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3712,6 +3712,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 6fa96938bf9512e0205b279801a181ff2666df34 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 2e7e0b7e0a7..04e72587bbf 100755
--- a/configure
+++ b/configure
@@ -11940,7 +11940,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11950,7 +11950,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -11993,6 +11993,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 0c069141478..96bcd704a07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3702,7 +3702,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3712,7 +3712,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3734,6 +3734,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 3cf76ece0608dbb12ff03e7c8d406e7b7db2b267 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From a57787f02b8748622e4d6ca503bfda5eea2952ec Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From e7a4c51e2b860939fd571d9062ae48d65a8ef6ce Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From dec047356c85880ccde9ceb08aec873150ebb6ce Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From aa13fa0dccef42fe23311544960cfda52169e89f Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 169cf06dbfe83862835225eb170e199d7060f5c0 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 72b6601d648c31b0f970859d820c7cfa6d731ac8 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From e2eacb52f1825425539ae8d777a35ae62ea003ad Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 2c0df425ef4e26366251172e040a9d6cfb1f9471 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 5e98482b7f8a32b769426b279742504aa45ba9a7 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From bc7cf075bc9476e358303855ca4a7c88f2103108 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index a7d2975f1f5..c0b730f2746 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 5aa91cbad35..9eae56f1d31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 95ca265cab510ac5ccf8da44b45234e1d51dcfd7 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From cf8eba395ddf888ce7d9e5e4a257209841aff6a4 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,27 @@
From 3fec519d6b326918f39ceb142ef762042ce8365f Mon Sep 17 00:00:00 2001
From: Ivan Pozdeev <vano@mail.mipt.ru>
Date: Fri, 26 Dec 2025 13:39:21 +0300
Subject: [PATCH] Recognize an argument to -j in MAKEFLAGS
---
setup.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/setup.py b/setup.py
index ad8fb81b218..5666deaf67b 100644
--- a/setup.py
+++ b/setup.py
@@ -307,8 +307,8 @@ def __init__(self, dist):
self.failed_on_import = []
self.missing = []
self.disabled_configure = []
- if '-j' in os.environ.get('MAKEFLAGS', ''):
- self.parallel = True
+ if (m:=re.search(r'(?:^|\s)(?:-j|--jobs)(?:\s+|=)?(\d*)',os.environ.get('MAKEFLAGS', ''))) is not None:
+ self.parallel = int(m.group(1)) if m.group(1) else True
def add(self, ext):
self.extensions.append(ext)
--
2.36.1.windows.1

View File

@ -0,0 +1,109 @@
From cf8eba395ddf888ce7d9e5e4a257209841aff6a4 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 43ec16e5e7b527cff1c9e47699248f04afe8cf37 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 0cc86f9ed76..3c3eb939642 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 547255ff31e..13d44972ea8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 654bafbe923d5a8f7ef7c3dee3f4bc9e4fef0139 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 19f1bd59ba8..5e3f216954e 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 763fc697be7..c06f1a567c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From fb4d6093b2b2e557711a747bae5c16742abf49bc Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 19f1bd59ba8..5e3f216954e 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 763fc697be7..c06f1a567c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From d3864984569660dccaa498b92d8fdabe9d291882 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 19f1bd59ba8..5e3f216954e 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 763fc697be7..c06f1a567c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From c3f875f9d55c7e2040dac25a8afcdd048d87b50b Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index bad619963ad..bb7f6bb1c00 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index cc69015b102..e2ab2faed28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From b1d96618e86c6135eba1556ca096ba1ab69b6973 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index bad619963ad..bb7f6bb1c00 100755
--- a/configure
+++ b/configure
@@ -11951,7 +11951,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11961,7 +11961,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12004,6 +12004,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index cc69015b102..e2ab2faed28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3707,7 +3707,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3717,7 +3717,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3739,6 +3739,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From c6b863db3ae5e6e142d5ea24ac72a3cbc9c68ac9 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.10] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 4b71c4e00f8..bfe3e819fff 100755
--- a/configure
+++ b/configure
@@ -11952,7 +11952,7 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -11962,7 +11962,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -12005,6 +12005,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ac3be3850a9..0b88132edfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3708,7 +3708,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ clock confstr close_range copy_file_range ctermid execv explicit_bzero \
explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
@@ -3718,7 +3718,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
if_nameindex \
initgroups kill killpg lchown lockf linkat lstat lutimes mmap \
memrchr mbrtowc mkdirat mkfifo \
- madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
+ madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
@@ -3740,6 +3740,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 7ebb74cb3b6b0b163d3bd07ea2ef21e5446c505b Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 784f8d30609..bc7c194e866 100755
--- a/configure
+++ b/configure
@@ -14966,7 +14966,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -14976,7 +14976,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15019,6 +15019,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index ab5e1de6fab..f70d17f4cdb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4543,7 +4543,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4553,7 +4553,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4575,6 +4575,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 23afa3cb08eb7a95c5549e46c6275af3bbf0bc93 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 9567ac3a62c..65ed2916e09 100755
--- a/configure
+++ b/configure
@@ -15158,7 +15158,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15168,7 +15168,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15211,6 +15211,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 90008bcae17..0816d477558 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4582,7 +4582,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4592,7 +4592,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4614,6 +4614,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 531b50ba6658c58f015de4f4f8aef8d3ef03ca0d Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index a1ad0ae2510..76a3eec37be 100755
--- a/configure
+++ b/configure
@@ -15209,7 +15209,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15219,7 +15219,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15262,6 +15262,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 7b4000fa9c3..44167040f3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4594,7 +4594,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4604,7 +4604,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4626,6 +4626,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 5699cd1a15ba3f0474ad61aaeb94ad1ad2dfc833 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index a1ad0ae2510..76a3eec37be 100755
--- a/configure
+++ b/configure
@@ -15209,7 +15209,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15219,7 +15219,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15262,6 +15262,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 7b4000fa9c3..44167040f3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4594,7 +4594,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4604,7 +4604,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4626,6 +4626,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From b8b17a685e1e4beac5a00540dde764213200a724 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index a1ad0ae2510..76a3eec37be 100755
--- a/configure
+++ b/configure
@@ -15209,7 +15209,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15219,7 +15219,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15262,6 +15262,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 7b4000fa9c3..44167040f3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4594,7 +4594,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4604,7 +4604,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4626,6 +4626,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 2fa150b3f0bce148cda2d2acf10973941580e9c8 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index a1ad0ae2510..76a3eec37be 100755
--- a/configure
+++ b/configure
@@ -15209,7 +15209,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15219,7 +15219,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15262,6 +15262,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 7b4000fa9c3..44167040f3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4594,7 +4594,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4604,7 +4604,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4626,6 +4626,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From c721b82ced0789df0643b87327440bea4fa8062c Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index a1ad0ae2510..76a3eec37be 100755
--- a/configure
+++ b/configure
@@ -15209,7 +15209,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15219,7 +15219,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15262,6 +15262,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index 7b4000fa9c3..44167040f3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4594,7 +4594,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4604,7 +4604,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4626,6 +4626,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

View File

@ -0,0 +1,109 @@
From 3f03fe05c04c7dbd8ff3206c7f56d41638c90681 Mon Sep 17 00:00:00 2001
From: Ned Deily <nad@python.org>
Date: Wed, 5 Aug 2026 10:30:17 +0300
Subject: [PATCH] (downstream) [3.11] gh-153711: Avoid use of dup3 and pipe2
calls introduced in macOS 27 (#155211)
---
...-08-05-02-02-33.gh-issue-153711.pO9fFb.rst | 3 +++
configure | 23 +++++++++++++++++--
configure.ac | 11 +++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
diff --git a/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
new file mode 100644
index 00000000000..90804c179a4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2026-08-05-02-02-33.gh-issue-153711.pO9fFb.rst
@@ -0,0 +1,3 @@
+On macOS, do not attempt to use the :manpage:`dup3(2)` and
+:manpage:`pipe2(2)` system calls introduced in
+macOS 27 to prevent problems when running on older systems.
diff --git a/configure b/configure
index 5ffa02dcb5b..1b90ed0d119 100755
--- a/configure
+++ b/configure
@@ -15209,7 +15209,7 @@ fi
# checks for library functions
for ac_func in \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -15219,7 +15219,7 @@ for ac_func in \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -15262,6 +15262,25 @@ done
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf '%s\n' "#define HAVE_DUP3 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf '%s\n' "#define HAVE_PIPE2 1" >>confdefs.h
+
+fi
+
+fi
+
ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include <sys/types.h>
#include <dirent.h>
"
diff --git a/configure.ac b/configure.ac
index bfc99cc4268..08c7df52a7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4594,7 +4594,7 @@ fi
# checks for library functions
AC_CHECK_FUNCS([ \
accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
- copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
+ copy_file_range ctermid dup execv explicit_bzero explicit_memset \
faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
@@ -4604,7 +4604,7 @@ AC_CHECK_FUNCS([ \
getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
+ plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
@@ -4626,6 +4626,13 @@ if test "$MACHDEP" != linux; then
AC_CHECK_FUNCS(lchmod)
fi
+# macOS introduced dup3 and pipe2 in macOS 27, late in the
+# lifetime of this version of Python. Rather than adding weaklinking
+# support for them, just continue to ignore them.
+if test "$ac_sys_system" != "Darwin"; then
+ AC_CHECK_FUNCS([dup3 pipe2])
+fi
+
AC_CHECK_DECL(dirfd,
AC_DEFINE(HAVE_DIRFD, 1,
Define if you have the 'dirfd' function or macro.), ,
--
2.55.0.windows.3

Some files were not shown because too many files have changed in this diff Show More