Compare commits

..

16 commits

Author SHA1 Message Date
Ayush 676b71e7b5
pyenv-binary: use xz compression for archives (#3543)
Some checks failed
build / discover_build_logic_change (push) Waiting to run
build / build (push) Blocked by required conditions
pyenv_tests / pyenv_tests (macos-14) (push) Waiting to run
pyenv_tests / pyenv_tests (macos-15) (push) Waiting to run
pyenv_tests / pyenv_tests (macos-15-intel) (push) Waiting to run
pyenv_tests / pyenv_tests (macos-26) (push) Waiting to run
pyenv_tests / pyenv_tests (ubuntu-22.04-arm) (push) Waiting to run
pyenv_tests / pyenv_tests (ubuntu-24.04) (push) Waiting to run
pyenv_tests / pyenv_tests (ubuntu-24.04-arm) (push) Waiting to run
pyenv_tests / pyenv_tests_docker (push) Waiting to run
pyenv_tests / pyenv_tests (ubuntu-22.04) (push) Failing after 1s
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)
Some checks failed
pyenv_tests / pyenv_tests (ubuntu-22.04) (push) Failing after 1s
pyenv_tests / pyenv_tests (macos-15) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15-intel) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-26) (push) Has been cancelled
build / discover_build_logic_change (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-14) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-22.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests_docker (push) Has been cancelled
build / build (push) Has been cancelled
* CI: Add Ubuntu binary publishing workflow
2026-09-11 15:21:26 +03:00
native-api ef4905cd81
Incorporate the pyenv-link plugin (#3538)
Some checks failed
pyenv_tests / pyenv_tests (ubuntu-22.04) (push) Failing after 1s
build / discover_build_logic_change (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-14) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15-intel) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-26) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-22.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests_docker (push) Has been cancelled
build / build (push) Has been cancelled
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: ef7a9f5d14
git-subtree-split: 2f8cb2cf1f
2026-09-08 02:55:49 +05:30
Michael Newman ef7a9f5d14
docs: Add link to list of available Python distributions (#3535)
Some checks failed
pyenv_tests / pyenv_tests (ubuntu-22.04) (push) Failing after 1s
pyenv_tests / pyenv_tests (ubuntu-22.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04) (push) Has been cancelled
build / discover_build_logic_change (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15-intel) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-26) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests_docker (push) Has been cancelled
build / build (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-14) (push) Has been cancelled
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)
Some checks failed
pyenv_tests / pyenv_tests (ubuntu-22.04) (push) Failing after 1s
pyenv_tests / pyenv_tests (ubuntu-24.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests_docker (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-22.04-arm) (push) Has been cancelled
pyenv_tests / pyenv_tests (ubuntu-24.04) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15-intel) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-26) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-14) (push) Has been cancelled
pyenv_tests / pyenv_tests (macos-15) (push) Has been cancelled
build / discover_build_logic_change (push) Has been cancelled
build / build (push) Has been cancelled
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
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
28 changed files with 842 additions and 52 deletions

View file

@ -9,6 +9,12 @@ inputs:
runs: runs:
using: composite using: composite
steps: 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. # The two OSes differ only in this step.
- if: runner.os == 'macOS' - if: runner.os == 'macOS'
shell: bash shell: bash
@ -19,15 +25,7 @@ runs:
shell: bash shell: bash
run: | run: |
#prerequisites #prerequisites
sudo apt-get update -q; sudo apt install -yq make build-essential libssl-dev zlib1g-dev \ pyenv install-prerequisites
libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
- 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
- shell: bash - shell: bash
run: | run: |
#build #build

View file

@ -220,10 +220,7 @@ jobs:
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
- run: | - run: |
#prerequisites #prerequisites
sudo apt-get update -q; sudo apt-get install -yq make build-essential \ pyenv install-prerequisites
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev
if [[ "${{ matrix.python-version }}" =~ pypy.*-(src|dev) ]]; then if [[ "${{ matrix.python-version }}" =~ pypy.*-(src|dev) ]]; then
export PYENV_BOOTSTRAP_VERSION=pypy2.7-7 export PYENV_BOOTSTRAP_VERSION=pypy2.7-7
echo "PYENV_BOOTSTRAP_VERSION=$PYENV_BOOTSTRAP_VERSION" >> $GITHUB_ENV echo "PYENV_BOOTSTRAP_VERSION=$PYENV_BOOTSTRAP_VERSION" >> $GITHUB_ENV
@ -283,10 +280,7 @@ jobs:
echo "_PYTHON_BUILD_FORCE_SKIP_XZ=1" >> $GITHUB_ENV echo "_PYTHON_BUILD_FORCE_SKIP_XZ=1" >> $GITHUB_ENV
- run: | - run: |
#prerequisites #prerequisites
sudo apt-get update -q; sudo apt-get install -yq make build-essential \ pyenv install-prerequisites
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
curl libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev
- run: | - run: |
#build #build
pyenv --debug install ${{ matrix.python-version }} && rc=$? || rc=$? pyenv --debug install ${{ matrix.python-version }} && rc=$? || rc=$?

70
.github/workflows/publish_binary.yml vendored Normal file
View file

@ -0,0 +1,70 @@
name: Publish a binary package
on:
workflow_dispatch:
inputs:
version:
description: A CPython version accepted by `pyenv install`
required: true
type: string
permissions:
contents: read
jobs:
publish_ubuntu:
runs-on: ubuntu-24.04
env:
PYENV_ROOT: ${{ github.workspace }}
VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@v7
- name: Install build prerequisites
run: ./bin/pyenv install-prerequisites
- name: Build package
env:
PYTHON_CONFIGURE_OPTS: --enable-optimizations
run: |
VERSION="${VERSION%%:*}"
entry="$(./bin/pyenv binary package-name "$VERSION")"
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

@ -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_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_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_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))) 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 .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) .PHONY: $(TEST_UNIT_DOCKER_PREFIX)
$(TEST_UNIT_DOCKER_PREFIX): $(TEST_UNIT_DOCKER_TARGETS) $(TEST_UNIT_DOCKER_PREFIX): $(TEST_UNIT_DOCKER_TARGETS)
@ -88,6 +91,29 @@ $(TEST_BINARY_DOCKER_TARGETS): $(TEST_BINARY_DOCKER_PREFIX)-% : $(TEST_BATS_IMAG
bats $${CI:+-F "/code/test/libexec/bats-format-tap-suite"} \ bats $${CI:+-F "/code/test/libexec/bats-format-tap-suite"} \
$${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/pyenv-binary/test/$${BATS_FILE_FILTER} $${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 # Build all images needed for bats under docker
.PHONY: $(TEST_BATS_IMAGE_PREFIX) .PHONY: $(TEST_BATS_IMAGE_PREFIX)
$(TEST_BATS_IMAGE_PREFIX): $(TEST_BATS_IMAGE_TARGETS) $(TEST_BATS_IMAGE_PREFIX): $(TEST_BATS_IMAGE_TARGETS)
@ -110,13 +136,13 @@ $(TEST_BATS_IMAGE_TARGETS):
./ ; \ ./ ; \
fi 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. # Do not pass in user flags to build tests.
unexport PYTHON_CFLAGS unexport PYTHON_CFLAGS
unexport PYTHON_CONFIGURE_OPTS 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 test-unit: bats
PATH="./bats/bin:$$PATH" test/run PATH="./bats/bin:$$PATH" test/run
@ -129,6 +155,10 @@ test-binary: bats
cd plugins/pyenv-binary && $(PWD)/bats/bin/bats $${CI:+-F "$(PWD)/test/libexec/bats-format-tap-suite"} \ 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} $${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) .SECONDARY: bats-$(TEST_BATS_VERSION)
bats-$(TEST_BATS_VERSION): bats-$(TEST_BATS_VERSION):
git clone --depth 1 --branch $(TEST_BATS_VERSION) https://github.com/bats-core/bats-core.git bats-$(TEST_BATS_VERSION) git clone --depth 1 --branch $(TEST_BATS_VERSION) https://github.com/bats-core/bats-core.git 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. * Lets you **change the global Python version** on a per-user basis.
* Provides support for **per-project Python versions**. * 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 * Allows you to **override the Python version** with an environment
variable. variable.
* Searches for commands from **multiple versions of Python at a time**. * Searches for commands from **multiple versions of Python at a time**.

View file

@ -473,12 +473,12 @@ function pyenv {
} }
if ( ("${commands[*]}" -split ' ') -contains \$command ) { 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 ) { if ( \$shell_cmds.Count -gt 0 ) {
iex (\$shell_cmds -join "\`n") iex (\$shell_cmds -join "\`n")
} }
} else { } else {
& (get-command -commandtype application pyenv) \$command \$args & (get-command -commandtype application pyenv -totalcount 1) \$command \$args
} }
} }
EOS EOS

1
plugins/.gitignore vendored
View file

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

View file

@ -14,6 +14,9 @@ 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 is not portable across, say, glibc and musl, or to an older glibc; the platform
and dependency metadata exist to catch that. and dependency metadata exist to catch that.
Installing a binary package requires `tar` with xz support (typically provided
by the `xz` package).
## Commands ## Commands
### `pyenv binary package [-v|--verbose] <version>[:<entry>] --archive-base-url <url>` ### `pyenv binary package [-v|--verbose] <version>[:<entry>] --archive-base-url <url>`
@ -29,7 +32,7 @@ Pass `-v` to show build progress from `pyenv install`.
```sh ```sh
pyenv binary package 3.12.7 \ pyenv binary package 3.12.7 \
--archive-base-url https://example.com/binaries --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. # its .meta file and a `3.12.7-debian-12-x86_64' definition.
pyenv binary package 3.12.7:company-python \ pyenv binary package 3.12.7:company-python \
@ -54,7 +57,7 @@ pyenv binary package-name 3.12.7
### `pyenv binary save <version> [<output-dir>] [--name <name>]` ### `pyenv binary save <version> [<output-dir>] [--name <name>]`
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, and writes `<version>-<platform>.meta` describing the build platform (OS, arch,
distro and libc version) and the system libraries the build links against. Use 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.
@ -78,7 +81,7 @@ needs are present.
```sh ```sh
pyenv binary generate-installer ./dist/3.12.7-linux-x86_64.meta \ 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" -o "$(pyenv root)/plugins/python-build/share/python-build/3.12.7-linux-x86_64"
pyenv install 3.12.7-linux-x86_64 pyenv install 3.12.7-linux-x86_64

View file

@ -7,7 +7,7 @@
# Installs <version> from source under a separate entry name, saves it as a # Installs <version> from source under a separate entry name, saves it as a
# binary package, then emits a python-build definition for that package. # binary package, then emits a python-build definition for that package.
# The archive, metadata and definition are written to the current directory # 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. # <version> A version `pyenv install' knows how to build.
# <entry> The optional name to build under and install the # <entry> The optional name to build under and install the
@ -16,7 +16,7 @@
# -v,--verbose Show build progress from `pyenv install'. # -v,--verbose Show build progress from `pyenv install'.
# --archive-base-url <url> # --archive-base-url <url>
# Where the archive will be hosted; the definition # Where the archive will be hosted; the definition
# downloads it from <url>/<entry>.tar.gz. # downloads it from <url>/<entry>.tar.xz.
# #
set -e set -e
[ -n "$PYENV_DEBUG" ] && set -x [ -n "$PYENV_DEBUG" ] && set -x
@ -80,4 +80,4 @@ pyenv-install ${verbose:+--verbose} "$spec"
pyenv-binary-save "$entry" "$PWD" --name "$entry" pyenv-binary-save "$entry" "$PWD" --name "$entry"
pyenv-binary-generate-installer "${entry}.meta" \ 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

@ -4,7 +4,7 @@
# #
# Usage: pyenv binary save <version> [<output-dir>] [--name <name>] # Usage: pyenv binary save <version> [<output-dir>] [--name <name>]
# #
# 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 # writes a metadata file listing the build platform and the system libraries
# it links against, so an installer can check compatibility before unpacking. # it links against, so an installer can check compatibility before unpacking.
# #
@ -134,10 +134,10 @@ system_deps() {
mkdir -p "$output_dir" mkdir -p "$output_dir"
package_name="${package_name:-${version}-${platform}}" package_name="${package_name:-${version}-${platform}}"
archive="${package_name}.tar.gz" archive="${package_name}.tar.xz"
metadata="${package_name}.meta" 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 "# pyenv-binary metadata"

View file

@ -66,10 +66,10 @@ pyenv-install --list --bare
run pyenv-binary-package 3.12.7 --archive-base-url http://example.com/binaries run pyenv-binary-package 3.12.7 --archive-base-url http://example.com/binaries
assert_success assert_success
assert [ -d "${PYENV_ROOT}/versions/3.12.7-debian-12-x86_64" ] 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" ] assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64.meta" ]
run grep '^ARCHIVE_URL=' "${BATS_TEST_TMPDIR}/3.12.7-debian-12-x86_64" 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 "rejects an entry name containing a slash" { @test "rejects an entry name containing a slash" {
@ -102,10 +102,10 @@ generate-installer"
--archive-base-url http://example.com/binaries --archive-base-url http://example.com/binaries
assert_success assert_success
assert [ -d "${PYENV_ROOT}/versions/3.12.7-test" ] 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" ] assert [ -f "${BATS_TEST_TMPDIR}/3.12.7-test.meta" ]
run grep '^ARCHIVE_URL=' "${BATS_TEST_TMPDIR}/3.12.7-test" 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" { @test "correctly joins archive base url with a trailing slash" {
@ -127,5 +127,5 @@ done
run pyenv-binary-package 3.12.7:3.12.7-test \ run pyenv-binary-package 3.12.7:3.12.7-test \
--archive-base-url http://example.com/binaries/ --archive-base-url http://example.com/binaries/
assert_success 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

@ -33,13 +33,13 @@ platform() {
@test "packages an installed version" { @test "packages an installed version" {
create_version "3.12.7" create_version "3.12.7"
local out="${BATS_TEST_TMPDIR}/dist" 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" 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 "$archive" ]
assert [ -f "${out}/3.12.7-$(platform).meta" ] assert [ -f "${out}/3.12.7-$(platform).meta" ]
run tar -tzf "$archive" run tar -tJf "$archive"
assert_success assert_success
assert_line 0 "3.12.7/" assert_line 0 "3.12.7/"
} }
@ -49,10 +49,10 @@ platform() {
local out="${BATS_TEST_TMPDIR}/dist" local out="${BATS_TEST_TMPDIR}/dist"
run pyenv-binary-save "3.12.7" "$out" --name "custom" run pyenv-binary-save "3.12.7" "$out" --name "custom"
assert_success "Saved custom.tar.gz and custom.meta to $out" assert_success "Saved custom.tar.xz and custom.meta to $out"
assert [ -f "${out}/custom.tar.gz" ] assert [ -f "${out}/custom.tar.xz" ]
run grep '^archive=' "${out}/custom.meta" run grep '^archive=' "${out}/custom.meta"
assert_success "archive=custom.tar.gz" assert_success "archive=custom.tar.xz"
} }
@test "fails when --name has no value" { @test "fails when --name has no value" {
@ -76,7 +76,7 @@ platform() {
assert_success assert_success
assert_line "version=3.12.7" assert_line "version=3.12.7"
assert_line "platform=$(platform)" assert_line "platform=$(platform)"
assert_line "archive=3.12.7-$(platform).tar.gz" assert_line "archive=3.12.7-$(platform).tar.xz"
} }
@test "records the original installation prefix" { @test "records the original installation prefix" {
@ -94,7 +94,7 @@ platform() {
PATH="$(path_without readelf)" run pyenv-binary-save "3.12.7" "${BATS_TEST_TMPDIR}/dist" 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_failure "pyenv-binary: need readelf to inspect shared libraries"
assert [ ! -e "${BATS_TEST_TMPDIR}/dist/3.12.7-$(platform).tar.gz" ] assert [ ! -e "${BATS_TEST_TMPDIR}/dist/3.12.7-$(platform).tar.xz" ]
} }
@test "records only direct libraries resolved outside the prefix" { @test "records only direct libraries resolved 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 ## Usage
Before you begin, you should ensure that your build environment has the proper On Ubuntu, Debian, and Mint, install the recommended build dependencies with:
system dependencies for compiling the wanted Python Version (see our [recommendations](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)).
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 ### 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 - 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) - Look only at the file name (i.e. the python version name)
- Run a new docker container for each, building that version - Run a new docker container for each, building that version

View file

@ -0,0 +1,47 @@
#!/usr/bin/env bash
#
# Summary: Install Python build prerequisites on Debian-based systems
#
# Usage: pyenv install-prerequisites
#
set -e
[ -n "$PYENV_DEBUG" ] && set -x
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
exit
fi
usage() {
pyenv-help install-prerequisites 2>/dev/null
[ -z "$1" ] || exit "$1"
}
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage 0
fi
[ "$#" -eq 0 ] || usage 1 >&2
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
)
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[@]}"

View file

@ -873,6 +873,7 @@ build_package_standard_build() {
if [ "$package_var_name" = "PYTHON" ]; then if [ "$package_var_name" = "PYTHON" ]; then
if can_use_homebrew; then if can_use_homebrew; then
configured_with_openssl || use_homebrew_openssl || true
use_custom_tcltk || use_homebrew_tcltk || true use_custom_tcltk || use_homebrew_tcltk || true
use_homebrew_readline || true use_homebrew_readline || true
use_homebrew_ncurses || true use_homebrew_ncurses || true
@ -885,6 +886,7 @@ build_package_standard_build() {
fi fi
fi fi
if can_use_macports; then if can_use_macports; then
configured_with_openssl || use_macports_openssl || true
use_custom_tcltk || true use_custom_tcltk || true
use_macports_readline || true use_macports_readline || true
use_macports_ncurses || true use_macports_ncurses || true
@ -1705,8 +1707,17 @@ build_package_mac_readline() {
build_package_standard "$@" 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() { has_broken_mac_openssl() {
is_mac || return 1 is_mac || return 1
configured_with_openssl && return 1
local openssl_version="$(/usr/bin/openssl version 2>/dev/null || true)" local openssl_version="$(/usr/bin/openssl version 2>/dev/null || true)"
if [[ $openssl_version = "OpenSSL 0.9.8"?* || $openssl_version = "LibreSSL"* ]]; then if [[ $openssl_version = "OpenSSL 0.9.8"?* || $openssl_version = "LibreSSL"* ]]; then
if can_use_homebrew; then if can_use_homebrew; then

View file

@ -18,6 +18,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
VERSION='25.3.4.1' 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 "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 "Oracle GraalVM uses the GFTC license, which is free for development and production use, see https://medium.com/graalvm/161527df3d76" && echo
@ -46,4 +47,4 @@ case "$graalpy_arch" in
;; ;;
esac esac
install_package "graalpy3.13-${VERSION}" "https://github.com/oracle/graalpython/releases/download/graal-${VERSION}/graalpy3.13-${VERSION}-${graalpy_arch}.tar.gz#${checksum}" "copy" ensurepip 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

@ -18,6 +18,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
VERSION='25.3.4.1' VERSION='25.3.4.1'
RELEASE_TAG='graal-25.3.4'
graalpy_arch="$(graalpy_architecture 2>/dev/null || true)" graalpy_arch="$(graalpy_architecture 2>/dev/null || true)"
@ -41,4 +42,4 @@ case "$graalpy_arch" in
;; ;;
esac esac
install_package "graalpy3.13-community-${VERSION}" "https://github.com/oracle/graalpython/releases/download/graal-${VERSION}/graalpy3.13-community-${VERSION}-${graalpy_arch}.tar.gz#${checksum}" "copy" ensurepip 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

@ -219,8 +219,10 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..5}; do stub brew false; done for i in {1..5}; do stub brew false; done
stub brew "--prefix : echo '$BREW_PREFIX'" stub brew "--prefix : echo '$BREW_PREFIX'"
stub port '-q installed openssl3 : false' '-q installed openssl : false'
for i in {1..3}; do stub port false; done for i in {1..3}; do stub port false; done
stub_make_install stub_make_install
@ -253,6 +255,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..5}; do stub brew false; done for i in {1..5}; do stub brew false; done
stub brew "--prefix : echo '$BREW_PREFIX'" stub brew "--prefix : echo '$BREW_PREFIX'"
stub_make_install stub_make_install
@ -282,6 +285,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub port '-q installed openssl3 : false' '-q installed openssl : false'
for i in {1..3}; do stub port false; done for i in {1..3}; do stub port false; done
stub_make_install stub_make_install
export PYTHON_BUILD_SKIP_HOMEBREW=1 export PYTHON_BUILD_SKIP_HOMEBREW=1
@ -315,6 +319,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew "--prefix libyaml : echo '$brew_libdir'" stub brew "--prefix libyaml : echo '$brew_libdir'"
stub brew '--prefix openssl : false'
for i in {1..6}; do stub brew false; done for i in {1..6}; do stub brew false; done
stub_make_install stub_make_install
@ -341,6 +346,7 @@ OUT
mkdir -p "$readline_libdir" mkdir -p "$readline_libdir"
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..2}; do stub brew false; done for i in {1..2}; do stub brew false; done
stub brew "--prefix readline : echo '$readline_libdir'" stub brew "--prefix readline : echo '$readline_libdir'"
for i in {1..3}; do stub brew false; done for i in {1..3}; do stub brew false; done
@ -371,6 +377,7 @@ OUT
mkdir -p "$ncurses_libdir" mkdir -p "$ncurses_libdir"
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..3}; do stub brew false; done for i in {1..3}; do stub brew false; done
stub brew "--prefix ncurses : echo '$ncurses_libdir'" stub brew "--prefix ncurses : echo '$ncurses_libdir'"
for i in {1..2}; do stub brew false; done for i in {1..2}; do stub brew false; done
@ -400,6 +407,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub port "-q installed libyaml : echo ' libyaml @0.2.5_0 (active)'" stub port "-q installed libyaml : echo ' libyaml @0.2.5_0 (active)'"
stub port '-q installed openssl3 : false' '-q installed openssl : false'
for i in {1..3}; do stub port false; done for i in {1..3}; do stub port false; done
stub_make_install stub_make_install
export PYTHON_BUILD_SKIP_HOMEBREW=1 export PYTHON_BUILD_SKIP_HOMEBREW=1
@ -427,6 +435,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub port '-q installed openssl3 : false' '-q installed openssl : false'
stub port "-q installed readline : echo ' readline @8.2.013_0 (active)'" stub port "-q installed readline : echo ' readline @8.2.013_0 (active)'"
for i in {1..2}; do stub port false; done for i in {1..2}; do stub port false; done
stub_make_install stub_make_install
@ -457,6 +466,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub port '-q installed openssl3 : false' '-q installed openssl : false'
stub port false stub port false
stub port "-q installed ncurses : echo '$ncurses_libdir'" stub port "-q installed ncurses : echo '$ncurses_libdir'"
stub port false stub port false
@ -634,6 +644,7 @@ OUT
stub uname '-s : echo Linux' stub uname '-s : echo Linux'
stub brew false stub brew false
stub port '-q installed openssl3 : false' '-q installed openssl : false'
for i in {1..3}; do stub port false; done for i in {1..3}; do stub port false; done
PORT_PREFIX="$(which port)" PORT_PREFIX="$(which port)"
PORT_PREFIX="${PORT_PREFIX%/bin/port}" PORT_PREFIX="${PORT_PREFIX%/bin/port}"
@ -664,6 +675,7 @@ OUT
mkdir -p "$BREW_PREFIX" mkdir -p "$BREW_PREFIX"
stub uname '-s : echo Linux' stub uname '-s : echo Linux'
stub brew '--prefix openssl : false'
for i in {1..5}; do stub brew false; done for i in {1..5}; do stub brew false; done
stub brew "--prefix : echo '$BREW_PREFIX'" stub brew "--prefix : echo '$BREW_PREFIX'"
stub_make_install stub_make_install
@ -695,6 +707,7 @@ OUT
stub uname '-s : echo Linux' stub uname '-s : echo Linux'
stub brew "--prefix : echo '$BREW_PREFIX'" stub brew "--prefix : echo '$BREW_PREFIX'"
stub brew '--prefix openssl : false'
for i in {1..5}; do stub brew false; done for i in {1..5}; do stub brew false; done
stub brew "--prefix : echo '$BREW_PREFIX'" stub brew "--prefix : echo '$BREW_PREFIX'"
stub_make_install stub_make_install
@ -743,6 +756,218 @@ make install
OUT OUT
} }
assert_explicit_openssl() {
local configure_opts="$1"
local definition_opts="$2"
cached_tarball "Python-3.6.2"
local openssl_libdir="$BATS_TEST_TMPDIR/homebrew-openssl"
mkdir -p "$openssl_libdir"
executable "$BATS_TEST_TMPDIR/bin/brew" <<OUT
#!$BASH
if [ "\$*" = '--prefix openssl' ]; then
echo '$openssl_libdir'
else
exit 1
fi
OUT
stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010'
stub_make_install
export PYTHON_BUILD_SKIP_MACPORTS=1
run_inline_definition <<DEF
function /usr/bin/openssl() { echo "LibreSSL 3.3.6"; }
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL_RPATH=1
$definition_opts
install_package "openssl-1.1.1" "https://example.com/openssl-1.1.1.tar.gz" mac_openssl --if has_broken_mac_openssl
install_package "Python-3.6.2" "http://python.org/ftp/python/3.6.2/Python-3.6.2.tar.gz"
DEF
assert_success
[[ "$output" != *"use openssl from homebrew"* ]]
unstub uname
unstub sw_vers
unstub make
assert_build_log <<OUT
Python-3.6.2: CFLAGS="" CPPFLAGS="-I${BATS_TEST_TMPDIR}/install/include" LDFLAGS="-L${BATS_TEST_TMPDIR}/install/lib -Wl,-rpath,${BATS_TEST_TMPDIR}/install/lib" PKG_CONFIG_PATH=""
Python-3.6.2: --prefix=$INSTALL_ROOT --enable-shared --libdir=$INSTALL_ROOT/lib $configure_opts
make -j 2
make install
OUT
}
@test "explicit OpenSSL in CONFIGURE_OPTS bypasses automatic selection" {
export CONFIGURE_OPTS="--with-openssl=$BATS_TEST_TMPDIR/custom-openssl"
assert_explicit_openssl "$CONFIGURE_OPTS"
}
@test "explicit OpenSSL in PYTHON_CONFIGURE_OPTS bypasses automatic selection" {
export PYTHON_CONFIGURE_OPTS="--with-openssl=$BATS_TEST_TMPDIR/custom-openssl"
assert_explicit_openssl "$PYTHON_CONFIGURE_OPTS"
}
@test "explicit OpenSSL with a separate argument bypasses automatic selection" {
export PYTHON_CONFIGURE_OPTS="--with-openssl $BATS_TEST_TMPDIR/custom-openssl"
assert_explicit_openssl "$PYTHON_CONFIGURE_OPTS"
}
@test "explicit OpenSSL in package options bypasses automatic selection" {
local openssl_libdir="$BATS_TEST_TMPDIR/custom openssl"
assert_explicit_openssl "--with-openssl=$openssl_libdir" \
"package_option python configure '--with-openssl=$openssl_libdir'"
}
assert_standard_build_openssl_selection() {
local manager="$1"
local expected_opts="$2"
local definition_opts="$3"
local preceding_check="$4"
local expected_searches="${5:-0}"
local openssl_libdir="$BATS_TEST_TMPDIR/automatic-openssl"
cached_tarball "Python-3.6.2"
mkdir -p "$openssl_libdir"
executable "$BATS_TEST_TMPDIR/bin/brew" <<OUT
#!$BASH
if [ "\$*" = '--prefix openssl' ]; then
echo called >> '$BATS_TEST_TMPDIR/openssl-search'
echo '$openssl_libdir'
else
exit 1
fi
OUT
executable "$BATS_TEST_TMPDIR/bin/port" <<OUT
#!$BASH
if [ "\$*" = '-q installed openssl3' ]; then
echo called >> '$BATS_TEST_TMPDIR/openssl-search'
echo 'openssl3 @3.0.0 (active)'
else
exit 1
fi
OUT
if [ "$manager" = homebrew ]; then
export PYTHON_BUILD_USE_HOMEBREW=1
export PYTHON_BUILD_SKIP_MACPORTS=1
else
export PYTHON_BUILD_SKIP_HOMEBREW=1
export PYTHON_BUILD_USE_MACPORTS=1
fi
stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010'
stub_make_install
run_inline_definition <<DEF
function /usr/bin/openssl() { echo "LibreSSL 3.3.6"; }
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
$definition_opts
$preceding_check
install_package "Python-3.6.2" "http://python.org/ftp/python/3.6.2/Python-3.6.2.tar.gz"
DEF
assert_success
unstub uname
unstub sw_vers
unstub make
run cat "$INSTALL_ROOT/build.log"
assert_output_contains "Python-3.6.2: --prefix=$INSTALL_ROOT --enable-shared --libdir=$INSTALL_ROOT/lib $expected_opts"
if [ "$expected_searches" -eq 0 ]; then
refute test -e "$BATS_TEST_TMPDIR/openssl-search"
else
run cat "$BATS_TEST_TMPDIR/openssl-search"
assert_success "called"
fi
}
@test "explicit OpenSSL bypasses Homebrew selection in a standard build" {
export CONFIGURE_OPTS="--with-openssl=$BATS_TEST_TMPDIR/custom-openssl"
assert_standard_build_openssl_selection homebrew "$CONFIGURE_OPTS"
}
@test "explicit OpenSSL bypasses MacPorts selection in a standard build" {
export PYTHON_CONFIGURE_OPTS="--with-openssl $BATS_TEST_TMPDIR/custom-openssl"
assert_standard_build_openssl_selection macports "$PYTHON_CONFIGURE_OPTS"
}
@test "explicit package OpenSSL bypasses repeated Homebrew selection" {
local configure_opts="--with-openssl=$BATS_TEST_TMPDIR/custom openssl"
assert_standard_build_openssl_selection homebrew "$configure_opts" \
"package_option python configure '$configure_opts'" \
'has_broken_mac_openssl || true'
}
@test "explicit package OpenSSL bypasses repeated MacPorts selection" {
local configure_opts="--with-openssl=$BATS_TEST_TMPDIR/custom openssl"
assert_standard_build_openssl_selection macports "$configure_opts" \
"package_option python configure '$configure_opts'" \
'has_broken_mac_openssl || true'
}
@test "standard build selects Homebrew OpenSSL without a broken-system check" {
assert_standard_build_openssl_selection homebrew \
"--with-openssl=$BATS_TEST_TMPDIR/automatic-openssl" '' '' 1
}
@test "standard build selects MacPorts OpenSSL without a broken-system check" {
assert_standard_build_openssl_selection macports \
"--with-openssl=$BATS_TEST_TMPDIR" '' '' 1
}
@test "standard build does not probe Homebrew OpenSSL again after selection" {
assert_standard_build_openssl_selection homebrew \
"--with-openssl=$BATS_TEST_TMPDIR/automatic-openssl" '' \
'has_broken_mac_openssl || true' 1
}
@test "standard build does not probe MacPorts OpenSSL again after selection" {
assert_standard_build_openssl_selection macports \
"--with-openssl=$BATS_TEST_TMPDIR" '' \
'has_broken_mac_openssl || true' 1
}
@test "OpenSSL rpath alone does not bypass Homebrew selection" {
local openssl_libdir="$BATS_TEST_TMPDIR/homebrew-openssl"
mkdir -p "$openssl_libdir"
stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010'
stub brew "--prefix openssl : echo '$openssl_libdir'"
export PYTHON_CONFIGURE_OPTS="--with-openssl-rpath=auto"
run_inline_definition <<'DEF'
function /usr/bin/openssl() { echo "LibreSSL 3.3.6"; }
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
has_broken_mac_openssl || true
printf '%s\n' "${PYTHON_CONFIGURE_OPTS_ARRAY[@]}"
DEF
assert_success
assert_output <<OUT
python-build: use openssl from homebrew
--enable-shared
--libdir=$INSTALL_ROOT/lib
--with-openssl=$openssl_libdir
OUT
unstub uname
unstub sw_vers
unstub brew
}
@test "bundled OpenSSL is still needed without an explicit or package-manager installation" {
stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
export PYTHON_BUILD_SKIP_MACPORTS=1
run_inline_definition <<'DEF'
function /usr/bin/openssl() { echo "LibreSSL 3.3.6"; }
has_broken_mac_openssl && echo "bundled OpenSSL needed"
DEF
assert_success "bundled OpenSSL needed"
unstub uname
unstub sw_vers
unstub brew
}
@test "readline is not linked from Homebrew when explicitly defined" { @test "readline is not linked from Homebrew when explicitly defined" {
cached_tarball "Python-3.6.2" cached_tarball "Python-3.6.2"
@ -753,6 +978,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..5}; do stub brew false; done for i in {1..5}; do stub brew false; done
stub_make_install stub_make_install
@ -782,6 +1008,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'" stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'"
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
@ -815,6 +1042,7 @@ TCL_DEFS='-DSMTH -DTCL_WITH_EXTERNAL_TOMMATH=1 -DSMTH_ELSE'
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'" stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'"
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
@ -845,6 +1073,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
stub brew "--prefix tcl-tk-custom : echo '$tcl_tk_libdir'" stub brew "--prefix tcl-tk-custom : echo '$tcl_tk_libdir'"
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
@ -876,6 +1105,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'" stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'"
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
@ -911,6 +1141,7 @@ TCL_DEFS='-DSMTH -DTCL_WITH_EXTERNAL_TOMMATH=1 -DSMTH_ELSE'
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'" stub brew "--prefix tcl-tk@8 : echo '$tcl_tk_libdir'"
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
@ -946,6 +1177,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
stub_make_install stub_make_install
@ -977,6 +1209,7 @@ OUT
tcl_tk_libdir="$BATS_TEST_TMPDIR/homebrew-tcl-tk" tcl_tk_libdir="$BATS_TEST_TMPDIR/homebrew-tcl-tk"
mkdir -p "$tcl_tk_libdir/lib" mkdir -p "$tcl_tk_libdir/lib"
stub brew '--prefix openssl : false'
stub brew "--prefix tcl-tk@8 : echo '${tcl_tk_libdir}'" stub brew "--prefix tcl-tk@8 : echo '${tcl_tk_libdir}'"
for i in {1..4}; do stub brew false; done for i in {1..4}; do stub brew false; done
@ -1006,6 +1239,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 10.10' stub sw_vers '-productVersion : echo 10.10'
stub brew '--prefix openssl : false'
for i in {1..6}; do stub brew false; done for i in {1..6}; do stub brew false; done
stub sysctl false stub sysctl false
@ -1035,6 +1269,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 10.10' stub sw_vers '-productVersion : echo 10.10'
stub brew '--prefix openssl : false'
for i in {1..6}; do stub brew false; done for i in {1..6}; do stub brew false; done
stub sysctl '-n hw.ncpu : echo 4' stub sysctl '-n hw.ncpu : echo 4'
@ -1141,6 +1376,7 @@ OUT
stub uname '-s : echo Darwin' stub uname '-s : echo Darwin'
stub sw_vers '-productVersion : echo 1010' stub sw_vers '-productVersion : echo 1010'
stub brew '--prefix openssl : false'
for i in {1..6}; do stub brew false; done for i in {1..6}; do stub brew false; done
stub_make_install stub_make_install

View file

@ -0,0 +1,83 @@
#!/usr/bin/env bats
load test_helper
_setup() {
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"
}
@test "completion does not install packages" {
stub apt-get
PATH="${BATS_TEST_DIRNAME}/../../../libexec:$PATH" \
run pyenv completions install-prerequisites
assert_success "--help"
unstub apt-get
}
@test "supports help" {
stub pyenv-help 'install-prerequisites : echo "Usage: pyenv install-prerequisites"'
run pyenv-install-prerequisites --help
assert_success "Usage: pyenv install-prerequisites"
unstub pyenv-help
}
@test "rejects arguments" {
stub pyenv-help 'install-prerequisites : echo "Usage: pyenv install-prerequisites"'
run pyenv-install-prerequisites unexpected
assert_failure "Usage: pyenv install-prerequisites"
unstub pyenv-help
}
@test "installs build prerequisites with apt-get as root" {
stub id '-u : echo 0'
stub apt-get \
'update -q : true' \
"install -yq ${prerequisites} : true"
run pyenv-install-prerequisites
assert_success
unstub apt-get
unstub id
}
@test "uses sudo when not running as root" {
stub id '-u : echo 1000'
stub apt-get
stub sudo \
'apt-get update -q : true' \
"apt-get install -yq ${prerequisites} : true"
run pyenv-install-prerequisites
assert_success
unstub sudo
unstub apt-get
unstub id
}
@test "fails when apt-get is unavailable" {
PATH="$(path_without apt-get)" run pyenv-install-prerequisites
assert_failure "pyenv: installing build prerequisites is not supported on this system"
}
@test "fails when sudo is unavailable for an unprivileged user" {
stub id '-u : echo 1000'
stub apt-get
PATH="$(path_without sudo)" run pyenv-install-prerequisites
assert_failure "pyenv: sudo is required to install build prerequisites"
unstub apt-get
unstub id
}

View file

@ -2,6 +2,7 @@ setup() {
export PYTHON_BUILD_CURL_OPTS= export PYTHON_BUILD_CURL_OPTS=
export PYTHON_BUILD_HTTP_CLIENT="curl" export PYTHON_BUILD_HTTP_CLIENT="curl"
export PYENV_TEST_DIR="${BATS_TEST_TMPDIR}/pyenv"
export FIXTURE_ROOT="${BATS_TEST_DIRNAME}/fixtures" export FIXTURE_ROOT="${BATS_TEST_DIRNAME}/fixtures"
export INSTALL_ROOT="${BATS_TEST_TMPDIR}/install" export INSTALL_ROOT="${BATS_TEST_TMPDIR}/install"
PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
@ -148,7 +149,7 @@ path_without() {
if [ "$found" != "${PYENV_ROOT}/shims" ]; then if [ "$found" != "${PYENV_ROOT}/shims" ]; then
alt="${PYENV_TEST_DIR}/$(echo "${found#/}" | tr '/' '-')" alt="${PYENV_TEST_DIR}/$(echo "${found#/}" | tr '/' '-')"
mkdir -p "$alt" mkdir -p "$alt"
for util in bash head cut readlink greadlink; do for util in bash head cut readlink greadlink tr; do
if [ -x "${found}/$util" ]; then if [ -x "${found}/$util" ]; then
ln -s "${found}/$util" "${alt}/$util" ln -s "${found}/$util" "${alt}/$util"
fi fi

View file

@ -12,7 +12,7 @@ FROM bash:$BASH
apk add sed coreutils findutils \ apk add sed coreutils findutils \
;fi ;fi
# Bats # Bats
RUN apk add --update parallel ncurses git binutils \ RUN apk add --update parallel ncurses git binutils xz \
&& mkdir -p ~/.parallel \ && mkdir -p ~/.parallel \
&& touch ~/.parallel/will-cite && touch ~/.parallel/will-cite
COPY --from=bats /root/bats-core /root/bats-core COPY --from=bats /root/bats-core /root/bats-core

View file

@ -2,8 +2,14 @@ unset PYENV_VERSION
unset PYENV_DIR unset PYENV_DIR
setup() { setup() {
export _PYENV_INSTALL_PREFIX="${BATS_TEST_DIRNAME%/*}"
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
export _PYENV_INSTALL_PREFIX="${BATS_TEST_DIRNAME%/*}"
local PLUGIN_PREFIX
if [[ $_PYENV_INSTALL_PREFIX =~ /plugins/[^/]+$ ]]; then
PLUGIN_PREFIX="$_PYENV_INSTALL_PREFIX"
_PYENV_INSTALL_PREFIX="${_PYENV_INSTALL_PREFIX::${#_PYENV_INSTALL_PREFIX}-${#BASH_REMATCH[0]}}"
fi
if ! enable -f "${_PYENV_INSTALL_PREFIX}"/libexec/pyenv-realpath.dylib realpath 2>/dev/null; then if ! enable -f "${_PYENV_INSTALL_PREFIX}"/libexec/pyenv-realpath.dylib realpath 2>/dev/null; then
if [ -n "$PYENV_NATIVE_EXT" ]; then if [ -n "$PYENV_NATIVE_EXT" ]; then
echo "pyenv: failed to load \`realpath' builtin" >&2 echo "pyenv: failed to load \`realpath' builtin" >&2
@ -27,6 +33,9 @@ setup() {
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
PATH="${PYENV_TEST_DIR}/bin:$PATH" PATH="${PYENV_TEST_DIR}/bin:$PATH"
PATH="${_PYENV_INSTALL_PREFIX}/libexec:$PATH" PATH="${_PYENV_INSTALL_PREFIX}/libexec:$PATH"
if [[ -n $PLUGIN_PREFIX ]]; then
PATH="${PLUGIN_PREFIX}/libexec:${PLUGIN_PREFIX}/bin:$PATH"
fi
PATH="${BATS_TEST_DIRNAME}/libexec:$PATH" PATH="${BATS_TEST_DIRNAME}/libexec:$PATH"
PATH="${PYENV_ROOT}/shims:$PATH" PATH="${PYENV_ROOT}/shims:$PATH"
PATH="${BATS_TEST_TMPDIR}/stubs:$PATH" PATH="${BATS_TEST_TMPDIR}/stubs:$PATH"
@ -40,6 +49,7 @@ setup() {
# even if its output is redirected, breaking the comparison logic # even if its output is redirected, breaking the comparison logic
export NO_COLOR=1 export NO_COLOR=1
# If test specific setup exist, run it # If test specific setup exist, run it
if [[ $(type -t _setup) == function ]];then if [[ $(type -t _setup) == function ]];then
_setup _setup