Compare commits

...

9 Commits

Author SHA1 Message Date
Anup Das
cf6f3c3200
fix(rehash): prevent terminal hang caused by stale or sandbox-blocked lock file (#3469)
* reduce stale lock TTL to 2 min, check for stale lock before acquiring and each time -- to hold up new shell sessions for as little as possible

---------

Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-06-04 22:36:11 +03:00
Ivan Pozdeev
45180928d3
2.7.1 2026-06-03 09:09:54 +03:00
native-api
c12fd3ae6b
realpath.c: fix obsolete syntax warning (#3468) 2026-06-03 08:42:53 +03:00
Ayush
455d1a31db
init: add --install for shell setup (#3454) 2026-06-03 01:13:07 +03:00
pyenv-bot[bot]
efc77132f7
Add CPython 3.15.0b2 (#3467)
Co-authored-by: native-api <2670332+native-api@users.noreply.github.com>
2026-06-03 00:55:40 +03:00
native-api
c425c9ec3a
Update URLs for PyPy nightly; Remove pypy3.5 and pypy3.7 nightly (#3466)
pypy3.5-c-jit-latest and pypy3.7-c-jit-latest are no longer available
2026-06-02 13:16:51 +03:00
native-api
95ddd7d479
Support 3.9 EOL Pip URL, consolidate tests (#3465) 2026-06-02 10:29:59 +03:00
Ivan Pozdeev
29057a6c69
2.6.32 2026-05-31 06:20:35 +03:00
native-api
23eb9a9ee3
Merge pull request #3463 from native-api/3.14_openssl_4_r2
3.14.0-5: Support building against OpenSSL 4
2026-05-31 05:59:43 +03:00
17 changed files with 430 additions and 246 deletions

View File

@ -1,5 +1,26 @@
# Version History # Version History
## Release v2.7.1
* Support 3.9 EOL Pip URL, consolidate tests by @native-api in https://github.com/pyenv/pyenv/pull/3465
* Update URLs for PyPy nightly; Remove pypy3.5 and pypy3.7 nightly by @native-api in https://github.com/pyenv/pyenv/pull/3466
* Add CPython 3.15.0b2 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3467
* init: add --install for shell setup by @macayu17 in https://github.com/pyenv/pyenv/pull/3454
* realpath.c: fix obsolete syntax warning by @native-api in https://github.com/pyenv/pyenv/pull/3468
## Release v2.6.32
* Add miniconda3 26.3.2-2, miniforge3 26.3.2-0, 26.3.2-1 by @native-api in https://github.com/pyenv/pyenv/pull/3445
* miniforge3 26.1, 26.3, add_miniforge: exclude .pkg installers by @native-api in https://github.com/pyenv/pyenv/pull/3446
* miniforge 26, CI: switch check to 3.13 by @native-api in https://github.com/pyenv/pyenv/pull/3447
* 2.7, 3.4: force C99 standard; 2.7.14-18: force OpenSSL 1 formula by @native-api in https://github.com/pyenv/pyenv/pull/3448
* rehash: detect and remove a stale lockfile by @native-api in https://github.com/pyenv/pyenv/pull/3450
* Add GraalPy 25.0.3 by @msimacek in https://github.com/pyenv/pyenv/pull/3452
* 3.11.0+: Use the `--with-openssl-rpath' Configure option when possible by @native-api in https://github.com/pyenv/pyenv/pull/3458
* python_build: Make `verify_python` verify `pythonX.Y' suffix by @native-api in https://github.com/pyenv/pyenv/pull/3459
* Add micropython 1.22.0 to 1.28.0; add downstream patches to fix compilation errors by @native-api in https://github.com/pyenv/pyenv/pull/3460
* Fix linking against a keg_only Homebrew OpenSSL when a a non-keg_only one is also installed by @native-api in https://github.com/pyenv/pyenv/pull/3462
* Add missing CPython 3.14.2t by @native-api in https://github.com/pyenv/pyenv/pull/3464
* 3.14.0-5: Support building against OpenSSL 4 by @native-api in https://github.com/pyenv/pyenv/pull/3463
## Release v2.6.31 ## Release v2.6.31
* CI: add_cpython: Support prereleases for non-initial CPython releases by @native-api in https://github.com/pyenv/pyenv/pull/3443 * CI: add_cpython: Support prereleases for non-initial CPython releases by @native-api in https://github.com/pyenv/pyenv/pull/3443
* Add CPython 3.14.5 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3444 * Add CPython 3.14.5 by @pyenv-bot[bot] in https://github.com/pyenv/pyenv/pull/3444

View File

@ -393,11 +393,15 @@ List existing pyenv shims.
Configure the shell environment for pyenv Configure the shell environment for pyenv
Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--no-rehash] [<shell>])" Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--no-rehash] [<shell>])"
pyenv init --install [<shell>]
pyenv init --detect-shell [<shell>]
- Initialize shims directory, print PYENV_SHELL variable, completions path - Initialize shims directory, print PYENV_SHELL variable, completions path
and shell function and shell function
--path Print shims path --path Print shims path
--install Configure detected shell startup files
--no-push-path Do not push shim to the start of PATH if they're already there --no-push-path Do not push shim to the start of PATH if they're already there
--detect-shell Print shell startup files detected for the current shell
--no-rehash Add no rehash command to output --no-rehash Add no rehash command to output
## `pyenv completions` ## `pyenv completions`

View File

@ -179,6 +179,24 @@ which does install native Windows Python versions.
The below setup should work for the vast majority of users for common use cases. The below setup should work for the vast majority of users for common use cases.
See [Advanced configuration](#advanced-configuration) for details and more configuration options. See [Advanced configuration](#advanced-configuration) for details and more configuration options.
If `pyenv` is already on `PATH`, you can configure the relevant shell startup
files automatically:
```sh
pyenv init --install
```
If `pyenv` is not on `PATH` yet, run the same command through the `pyenv`
executable in your chosen installation directory.
This uses the same shell detection as `pyenv init`. If a startup file already
contains Pyenv-related configuration, the command refuses to edit it; review the
file manually and run `pyenv init <shell>` to see the suggested setup.
For Bash, avoid the automatic `--install` path if your `BASH_ENV` points to
`.bashrc`; use the manual Bash instructions below so the `eval "$(pyenv init - bash)"`
line only goes in your login startup file.
#### Bash #### Bash
<details> <details>

View File

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

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Summary: Configure the shell environment for pyenv # Summary: Configure the shell environment for pyenv
# Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--detect-shell] [--no-rehash] [<shell>])" # Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--no-rehash] [<shell>])"
# pyenv init --install [<shell>]
# pyenv init --detect-shell [<shell>]
set -e set -e
[ -n "$PYENV_DEBUG" ] && set -x [ -n "$PYENV_DEBUG" ] && set -x
@ -9,6 +11,7 @@ set -e
if [ "$1" = "--complete" ]; then if [ "$1" = "--complete" ]; then
echo - echo -
echo --path echo --path
echo --install
echo --no-push-path echo --no-push-path
echo --no-rehash echo --no-rehash
echo --detect-shell echo --detect-shell
@ -30,6 +33,9 @@ while [ "$#" -gt 0 ]; do
--path) --path)
mode="path" mode="path"
;; ;;
--install)
mode="install"
;;
--detect-shell) --detect-shell)
mode="detect-shell" mode="detect-shell"
;; ;;
@ -81,21 +87,23 @@ function main() {
exit 0 exit 0
;; ;;
"detect-shell") "detect-shell")
detect_profile 1 detect_profile
print_detect_shell print_detect_shell
exit 0 exit 0
;; ;;
"install")
install_shell_startup_files
exit 0
;;
esac esac
# should never get here # should never get here
exit 2 exit 2
} }
function detect_profile() { function detect_profile() {
local detect_for_detect_shell="$1"
case "$shell" in case "$shell" in
bash ) bash )
if [ -e '~/.bash_profile' ]; then if [ -e "${HOME}/.bash_profile" ]; then
profile='~/.bash_profile' profile='~/.bash_profile'
else else
profile='~/.profile' profile='~/.profile'
@ -103,6 +111,10 @@ function detect_profile() {
profile_explain="~/.bash_profile if it exists, otherwise ~/.profile" profile_explain="~/.bash_profile if it exists, otherwise ~/.profile"
rc='~/.bashrc' rc='~/.bashrc'
;; ;;
fish )
profile='~/.config/fish/config.fish'
rc='~/.config/fish/config.fish'
;;
pwsh ) pwsh )
profile='~/.config/powershell/profile.ps1' profile='~/.config/powershell/profile.ps1'
rc='~/.config/powershell/profile.ps1' rc='~/.config/powershell/profile.ps1'
@ -121,13 +133,10 @@ function detect_profile() {
rc='~/.profile' rc='~/.profile'
;; ;;
* ) * )
if [ -n "$detect_for_detect_shell" ]; then
profile= profile=
rc= rc=
else profile_explain='your shell'\''s login startup file'
profile='your shell'\''s login startup file' rc_explain='your shell'\''s interactive startup file'
rc='your shell'\''s interactive startup file'
fi
;; ;;
esac esac
} }
@ -146,38 +155,32 @@ function help_() {
echo "# Add pyenv executable to PATH by running" echo "# Add pyenv executable to PATH by running"
echo "# the following interactively:" echo "# the following interactively:"
echo echo
echo 'set -Ux PYENV_ROOT $HOME/.pyenv' print_fish_user_path_setup
echo 'set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths'
echo echo
echo "# Load pyenv automatically by appending" echo "# Load pyenv automatically by appending"
echo "# the following to ~/.config/fish/config.fish:" echo "# the following to ~/.config/fish/config.fish:"
echo echo
echo 'pyenv init - fish | source' print_fish_shell_setup
echo echo
;; ;;
pwsh ) pwsh )
echo '# Load pyenv automatically by appending' echo '# Load pyenv automatically by appending'
echo "# the following to $profile :" echo "# the following to $profile :"
echo echo
echo '$Env:PYENV_ROOT="$Env:HOME/.pyenv"' print_pwsh_shell_setup
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")'
;; ;;
* ) * )
echo '# Load pyenv automatically by appending' echo '# Load pyenv automatically by appending'
echo -n "# the following to " echo -n "# the following to "
if [ "$profile" == "$rc" ]; then if [[ "$profile" == "$rc" && -z $rc_explain ]]; then
echo "$profile :" echo "${profile_explain:-$profile} :"
else else
echo echo
echo "# ${profile_explain:-$profile} (for login shells)" echo "# ${profile_explain:-$profile} (for login shells)"
echo "# and $rc (for interactive shells) :" echo "# and ${rc_explain:-$rc} (for interactive shells) :"
fi fi
echo echo
echo 'export PYENV_ROOT="$HOME/.pyenv"' print_posix_shell_setup
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"'
echo 'eval "$(pyenv init - '$shell')"'
;; ;;
esac esac
echo echo
@ -186,6 +189,154 @@ function help_() {
} >&2 } >&2
} }
function print_posix_shell_setup() {
echo 'export PYENV_ROOT="$HOME/.pyenv"'
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"'
echo 'eval "$(pyenv init - '$shell')"'
}
function print_fish_shell_setup() {
echo 'pyenv init - fish | source'
}
function print_fish_user_path_setup() {
echo 'set -Ux PYENV_ROOT $HOME/.pyenv'
echo 'if functions -q fish_add_path'
echo ' test -d $PYENV_ROOT/bin; and fish_add_path $PYENV_ROOT/bin'
echo 'else'
echo ' test -d $PYENV_ROOT/bin; and set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths'
echo 'end'
}
function print_pwsh_shell_setup() {
echo '$Env:PYENV_ROOT="$Env:HOME/.pyenv"'
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")'
}
function expand_home_path() {
local path="$1"
printf '%s\n' "${path/#\~/$HOME}"
}
function install_shell_startup_files() {
if [[ -z $HOME ]]; then
echo "pyenv: HOME must be set to configure shell startup files" >&2
return 1
fi
detect_profile
local files=()
local lines=()
local profile_path rc_path setup
case "$shell" in
bash | zsh | ksh | ksh93 | mksh )
rc_path="$(expand_home_path "$rc")"
profile_path="$(expand_home_path "$profile")"
setup="$(print_posix_shell_setup)"
files=("$rc_path")
lines=("$setup")
if [[ $profile_path != "$rc_path" ]]; then
files+=("$profile_path")
lines+=("$setup")
fi
;;
fish )
rc_path="$(expand_home_path "$rc")"
files=("$rc_path")
lines=("$(print_fish_shell_setup)")
;;
pwsh )
rc_path="$(expand_home_path "$rc")"
files=("$rc_path")
lines=("$(print_pwsh_shell_setup)")
;;
* )
echo "pyenv: cannot automatically configure startup files for $shell" >&2
return 1
;;
esac
local index
for ((index = 0; index < ${#files[@]}; index++)); do
check_startup_file "${files[$index]}" || return 1
done
if [[ $shell == fish ]]; then
install_fish_user_paths || return 1
fi
for ((index = 0; index < ${#files[@]}; index++)); do
append_lines "${files[$index]}" "${lines[$index]}"
done
}
function check_startup_file() {
local file="$1"
local grep_status
if [[ ! -e $file ]]; then
return 0
fi
if [[ ! -f $file || ! -r $file ]]; then
echo "pyenv: failed to inspect $file" >&2
return 1
fi
if grep -Fi pyenv "$file" >/dev/null; then
echo "pyenv: cannot automatically apply changes to $file: it appears to already contain Pyenv-related code." >&2
echo "pyenv: review the file's contents and apply changes manually if necessary." >&2
echo "pyenv: run \`pyenv init $shell\` to see the suggested setup." >&2
return 1
else
grep_status=$?
if [[ $grep_status == 1 ]]; then
return 0
fi
echo "pyenv: failed to inspect $file" >&2
return "$grep_status"
fi
}
function install_fish_user_paths() {
local fish_setup
if ! command -v fish >/dev/null; then
echo "pyenv: fish is not available to configure fish universal variables" >&2
return 1
fi
fish_setup="$(print_fish_user_path_setup)"
if ! fish -c "$fish_setup"; then
echo "pyenv: failed to configure fish universal variables" >&2
return 1
fi
}
function append_lines() {
local file="$1"
local lines="$2"
local dir last_char
dir="${file%/*}"
if [[ $dir != "$file" ]]; then
mkdir -p "$dir"
fi
if [[ -s $file ]]; then
last_char="$(tail -c 1 "$file")" || return 1
if [[ -n $last_char ]]; then
echo >> "$file"
fi
fi
printf '%s\n' "$lines" >> "$file"
}
function init_dirs() { function init_dirs() {
mkdir -p "${PYENV_ROOT}/"{shims,versions} mkdir -p "${PYENV_ROOT}/"{shims,versions}
} }

View File

@ -13,15 +13,29 @@ mkdir -p "$SHIM_PATH"
declare last_acquire_error declare last_acquire_error
acquire_lock() { acquire_lock() {
# Ensure only one instance of pyenv-rehash is running at a time by
# setting the shell's `noclobber` option and attempting to write to
# the prototype shim file.
local ret local ret
# An old lock file is presumed stale. We assume no healthy rehash takes this long.
# The time is picked very small so that a killed rehash holds up new shell sessions
# for as little as possible
find "$PROTOTYPE_SHIM_PATH" -mmin +2 -exec rm -f {} \; 2>/dev/null || true
set -o noclobber set -o noclobber
# Assuming an old lockfile is stale
# Unknown why this happens for some users but this at least unblocks them
last_acquire_error="$( { ( echo -n > "$PROTOTYPE_SHIM_PATH"; ) 2>&1 1>&3 3>&1-; } 3>&1)" \ last_acquire_error="$( { ( echo -n > "$PROTOTYPE_SHIM_PATH"; ) 2>&1 1>&3 3>&1-; } 3>&1)" \
|| { find "$PROTOTYPE_SHIM_PATH" -mmin +10 -exec rm -f {} \; ; ret=1; } && trap release_lock EXIT \
|| {
# Linux Landlock and MacOS Seatbelt sandbox subsystems return false information in access(),
# making -w "$SHIM_PATH" not catch the fact that the shims dir is not writable in this case.
# Bash doesn't provide access to errno to check for non-EEXIST error code in `echo >'.
# So check for writablity by trying to write to a different file,
# in a way that taxes the usual use case as little as possible.
if [[ -z $tested_for_other_write_errors ]]; then
( t="$(TMPDIR="$SHIM_PATH" mktemp)" && rm "$t" ) \
&& tested_for_other_write_errors=1 \
|| { echo "pyenv: cannot rehash: $SHIM_PATH isn't writable" >&2
set +o noclobber
exit 1; }
fi
ret=1
}
set +o noclobber set +o noclobber
[[ -z "${ret}" ]] [[ -z "${ret}" ]]
} }
@ -32,6 +46,7 @@ remove_prototype_shim() {
release_lock() { release_lock() {
remove_prototype_shim remove_prototype_shim
trap - EXIT
} }
if [ ! -w "$SHIM_PATH" ]; then if [ ! -w "$SHIM_PATH" ]; then
@ -45,22 +60,8 @@ PYENV_REHASH_TIMEOUT=${PYENV_REHASH_TIMEOUT:-60}
while (( SECONDS <= start + PYENV_REHASH_TIMEOUT )); do while (( SECONDS <= start + PYENV_REHASH_TIMEOUT )); do
if acquire_lock; then if acquire_lock; then
acquired=1 acquired=1
# If we were able to obtain a lock, register a trap to clean up the
# prototype shim when the process exits.
trap release_lock EXIT
break break
else else
#Landlock sandbox subsystem in the Linux kernel returns false information in access() as of 6.14.0,
# making -w "$SHIM_PATH" not catch the fact that the shims dir is not writable in this case.
#Bash doesn't provide access to errno to check for non-EEXIST error code in acquire_lock.
#So check for writablity by trying to write to a different file,
# in a way that taxes the usual use case as little as possible.
if [[ -z $tested_for_other_write_errors ]]; then
( t="$(TMPDIR="$SHIM_PATH" mktemp)" && rm "$t" ) && tested_for_other_write_errors=1 ||
{ echo "pyenv: cannot rehash: $SHIM_PATH isn't writable" >&2; break; }
fi
# POSIX sleep(1) doesn't provide subsecond precision, but many others do # POSIX sleep(1) doesn't provide subsecond precision, but many others do
sleep 0.1 2>/dev/null || sleep 1 sleep 0.1 2>/dev/null || sleep 1
fi fi

View File

@ -14,7 +14,7 @@
# -g/--debug Build a debug version # -g/--debug Build a debug version
# #
PYTHON_BUILD_VERSION="2.6.31" PYTHON_BUILD_VERSION="2.7.1"
OLDIFS="$IFS" OLDIFS="$IFS"
@ -2678,7 +2678,7 @@ if [ -z "${GET_PIP_URL}" ]; then
2.6 | 2.6.* ) 2.6 | 2.6.* )
GET_PIP_URL="https://bootstrap.pypa.io/pip/2.6/get-pip.py" GET_PIP_URL="https://bootstrap.pypa.io/pip/2.6/get-pip.py"
;; ;;
2.7 | 2.7.* | pypy2.7 | pypy2.7-* ) 2.7 | 2.7.* | pypy2.7 | pypy2.7-* | pypy-c-jit-* )
GET_PIP_URL="https://bootstrap.pypa.io/pip/2.7/get-pip.py" GET_PIP_URL="https://bootstrap.pypa.io/pip/2.7/get-pip.py"
;; ;;
3.2 | 3.2.* ) 3.2 | 3.2.* )
@ -2702,6 +2702,9 @@ if [ -z "${GET_PIP_URL}" ]; then
3.8 | 3.8.* | pypy3.8 | pypy3.8-* | pyston* ) 3.8 | 3.8.* | pypy3.8 | pypy3.8-* | pyston* )
GET_PIP_URL="https://bootstrap.pypa.io/pip/3.8/get-pip.py" GET_PIP_URL="https://bootstrap.pypa.io/pip/3.8/get-pip.py"
;; ;;
3.9 | 3.9.* | pypy3.9 | pypy3.9-* )
GET_PIP_URL="https://bootstrap.pypa.io/pip/3.9/get-pip.py"
;;
* ) * )
GET_PIP_URL="https://bootstrap.pypa.io/get-pip.py" GET_PIP_URL="https://bootstrap.pypa.io/get-pip.py"
;; ;;

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-3.6.2" "https://github.com/openssl/openssl/releases/download/openssl-3.6.2/openssl-3.6.2.tar.gz#aaf51a1fe064384f811daeaeb4ec4dce7340ec8bd893027eee676af31e83a04f" 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.0b1" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0b1.tar.xz#d4d52ccfa1d727ef5235fbb7d70fa1dbacf10b8b3760db622875da05acbe437c" standard verify_py315 copy_python_gdb ensurepip
else
install_package "Python-3.15.0b1" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0b1.tgz#9b41271890067875db7f0f5cb2fdcb944b90c473f272a18a13b93c059d84c68e" 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.0" "https://github.com/openssl/openssl/releases/download/openssl-4.0.0/openssl-4.0.0.tar.gz#c32cf49a959c4f345f9606982dd36e7d28f7c58b19c2e25d75624d2b3d2f79ac" 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.0b2" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0b2.tar.xz#d14f474ab679e90bc734b02ff58447b6ec99a821af61d6ff0c1da0f86e341a71" standard verify_py315 copy_python_gdb ensurepip
else
install_package "Python-3.15.0b2" "https://www.python.org/ftp/python/3.15.0/Python-3.15.0b2.tgz#781f4bcdef48d1d38b335fdc7a156b4e5fe9738b14456121f949257ff5cce77c" standard verify_py315 copy_python_gdb ensurepip
fi

View File

@ -1,30 +1,21 @@
case "$(pypy_architecture 2>/dev/null || true)" in case "$(pypy_architecture 2>/dev/null || true)" in
"linux" ) "linux" )
install_nightly_package "pypy-c-jit-latest-linux" "http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-linux.tar.bz2" "pypy-c-jit-*-linux" "pypy" verify_py27 ensurepip install_nightly_package "pypy-c-jit-latest-linux" "https://buildbot.pypy.org/nightly/main/pypy-c-jit-latest-linux.tar.bz2" "pypy-c-jit-*-linux" "pypy" verify_py27 ensurepip_lt21
;;
"linux-armel" )
install_nightly_package "pypy-c-jit-latest-linux-armel" "http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-linux-armel.tar.bz2" "pypy-c-jit-*-linux-armel" "pypy" verify_py27 ensurepip
;;
"linux-armhf" )
if [[ "$(cat /etc/issue 2>/dev/null || true)" == "Raspbian"* ]]; then
install_nightly_package "pypy-c-jit-latest-linux-armhf-raspbian" "http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-linux-armhf-raspbian.tar.bz2" "pypy-c-jit-*-linux-armhf-raspbian" "pypy" verify_py27 ensurepip
else
{ echo
colorize 1 "ERROR"
echo ": The binary distribution of PyPy is not available for $(pypy_architecture 2>/dev/null || true)."
echo
} >&2
exit 1
fi
;; ;;
"linux64" ) "linux64" )
install_nightly_package "pypy-c-jit-latest-linux64" "http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-linux64.tar.bz2" "pypy-c-jit-*-linux64" "pypy" verify_py27 ensurepip install_nightly_package "pypy-c-jit-latest-linux64" "https://buildbot.pypy.org/nightly/main/pypy-c-jit-latest-linux64.tar.bz2" "pypy-c-jit-*-linux64" "pypy" verify_py27 ensurepip_lt21
;;
"linux-aarch64" )
install_nightly_package "pypy-c-jit-latest-aarch64" "https://buildbot.pypy.org/nightly/main/pypy-c-jit-latest-aarch64.tar.bz2" "pypy-c-jit-*-aarch64" "pypy" verify_py27 ensurepip_lt21
;;
"osarm64" )
install_nightly_package "pypy-c-jit-latest-macos_arm64" "https://buildbot.pypy.org/nightly/main/pypy-c-jit-latest-macos_arm64.tar.bz2" "pypy-c-jit-*-macos_arm64" "pypy" verify_py27 ensurepip_lt21
;; ;;
"osx64" ) "osx64" )
install_nightly_package "pypy-c-jit-latest-osx64" "http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-osx64.tar.bz2" "pypy-c-jit-*-osx64" "pypy" verify_py27 ensurepip install_nightly_package "pypy-c-jit-latest-macos_x86_64" "https://buildbot.pypy.org/nightly/main/pypy-c-jit-latest-macos_x86_64.tar.bz2" "pypy-c-jit-*-macos_x86_64" "pypy" verify_py27 ensurepip_lt21
;; ;;
"win32" ) "win32" )
install_zip "pypy-c-jit-latest-win32" "http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-win32.zip" "pypy" verify_py27 ensurepip install_zip "pypy-c-jit-latest-win32" "https://buildbot.pypy.org/nightly/main/pypy-c-jit-latest-win32.zip" "pypy" verify_py27 ensurepip_lt21
;; ;;
* ) * )
{ echo { echo

View File

@ -1,49 +0,0 @@
echo
colorize 1 "WARNING"
echo ": This may eat your kittens/ affect timespace in alternate dimensions/"
echo "cause you to complain more. Nightly builds are meant for testing only."
echo
echo "To report bugs/regressions, please see:"
echo
echo "http://doc.pypy.org/en/latest/faq.html#how-should-i-report-a-bug"
echo
case "$(pypy_architecture 2>/dev/null || true)" in
"linux" )
install_nightly_package "pypy-c-jit-latest-linux" "http://buildbot.pypy.org/nightly/py3.5/pypy-c-jit-latest-linux.tar.bz2" "pypy-c-jit-*-linux" "pypy" verify_py27 ensurepip
;;
"linux-armel" )
install_nightly_package "pypy-c-jit-latest-linux-armel" "http://buildbot.pypy.org/nightly/py3.5/pypy-c-jit-latest-linux-armel.tar.bz2" "pypy-c-jit-*-linux-armel" "pypy" verify_py27 ensurepip
;;
"linux-armhf" )
if [[ "$(cat /etc/issue 2>/dev/null || true)" == "Raspbian"* ]]; then
install_nightly_package "pypy-c-jit-latest-linux-armhf-raspbian" "http://buildbot.pypy.org/nightly/py3.5/pypy-c-jit-latest-linux-armhf-raspbian.tar.bz2" "pypy-c-jit-*-linux-armhf-raspbian" "pypy" verify_py27 ensurepip
else
{ echo
colorize 1 "ERROR"
echo ": The latest nightly build of PyPy 3.5 is not available for $(pypy_architecture 2>/dev/null || true),"
echo "Please check http://buildbot.pypy.org/nightly/py3.5/ for previous builds."
echo
} >&2
exit 1
fi
;;
"linux64" )
install_nightly_package "pypy3.5-c-jit-latest-linux64" "http://buildbot.pypy.org/nightly/py3.5/pypy-c-jit-latest-linux64.tar.bz2" "pypy-c-jit-*-linux64" "pypy" verify_py35 ensurepip
;;
"osx64" )
install_nightly_package "pypy-c-jit-latest-osx64" "http://buildbot.pypy.org/nightly/py3.5/pypy-c-jit-latest-osx64.tar.bz2" "pypy-c-jit-*-osx64" "pypy" verify_py27 ensurepip
;;
"win32" )
install_zip "pypy-c-jit-latest-win32" "http://buildbot.pypy.org/nightly/py3.5/pypy-c-jit-latest-win32.zip" "pypy" verify_py27 ensurepip
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The latest nightly build of PyPy 3.5 is not available for $(pypy_architecture 2>/dev/null || true),"
echo "Please check http://buildbot.pypy.org/nightly/py3.5/ for previous builds."
echo
} >&2
exit 1
;;
esac

View File

@ -1,39 +0,0 @@
echo
colorize 1 "WARNING"
echo ": This may eat your kittens/ affect timespace in alternate dimensions/"
echo "cause you to complain more. Nightly builds are meant for testing only."
echo "Current pypy py3.7 development status:"
echo
echo "https://foss.heptapod.net/pypy/pypy/-/wikis/py3.7%20status"
echo
echo "for the latest status updates. To report bugs/regressions, please see:"
echo
echo "https://doc.pypy.org/en/latest/faq.html#how-should-i-report-a-bug"
echo
case "$(pypy_architecture 2>/dev/null || true)" in
"linux" )
install_nightly_package "pypy-c-jit-latest-linux" "https://buildbot.pypy.org/nightly/py3.7/pypy-c-jit-latest-linux.tar.bz2" "pypy-c-jit-*-linux" "pypy" verify_py27 ensurepip
;;
"linux64" )
install_nightly_package "pypy3.7-c-jit-latest-linux64" "https://buildbot.pypy.org/nightly/py3.7/pypy-c-jit-latest-linux64.tar.bz2" "pypy-c-jit-*-linux64" "pypy" verify_py35 ensurepip
;;
"linux-aarch64" )
install_nightly_package "pypy3.7-c-jit-latest-aarch64" "https://buildbot.pypy.org/nightly/py3.7/pypy-c-jit-latest-aarch64.tar.bz2" "pypy-c-jit-*-aarch64" "pypy" verify_py35 ensurepip
;;
"osx64" )
install_nightly_package "pypy-c-jit-latest-osx64" "https://buildbot.pypy.org/nightly/py3.7/pypy-c-jit-latest-osx64.tar.bz2" "pypy-c-jit-*-osx64" "pypy" verify_py27 ensurepip
;;
"win32" )
install_zip "pypy-c-jit-latest-win32" "https://buildbot.pypy.org/nightly/py3.7/pypy-c-jit-latest-win32.zip" "pypy" verify_py27 ensurepip
;;
* )
{ echo
colorize 1 "ERROR"
echo ": The latest nightly build of PyPy 3.7 is not available for $(pypy_architecture 2>/dev/null || true),"
echo "Please check https://buildbot.pypy.org/nightly/py3.7/ for previous builds."
echo
} >&2
exit 1
;;
esac

View File

@ -388,82 +388,39 @@ OUT
assert_success assert_success
} }
@test "use the custom GET_PIP_URL for 2.6 versions" { @test "use custom GET_PIP_URLs" {
run_inline_definition_with_name --name=2.6 <<OUT
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/2.6/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for 2.7 versions" { declare -a name_subdir=(\
run_inline_definition_with_name --name=2.7 <<OUT 2.6
echo "\${GET_PIP_URL}" 2.7
OUT 3.2
assert_output "https://bootstrap.pypa.io/pip/2.7/get-pip.py" 3.3
assert_success 3.4
} 3.5
3.6
3.7
3.8
3.9
@test "use the custom GET_PIP_URL for 3.2 versions" { "pypy2.7-7.3.12 2.7"
run_inline_definition_with_name --name=3.2 <<OUT "pypy-c-jit-latest-linux 2.7"
echo "\${GET_PIP_URL}" "pypy3.5-7.0.0 3.5"
OUT "pypy3.6-7.3.3 3.6"
assert_output "https://bootstrap.pypa.io/pip/3.2/get-pip.py" "pypy3.7-7.3.3 3.7"
assert_success "pypy3.8-7.3.8 3.8"
} "pypy3.9-7.3.16 3.9"
@test "use the custom GET_PIP_URL for 3.3 versions" { "pyston-2.3.5 3.8"
run_inline_definition_with_name --name=3.3 <<OUT )
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/3.3/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for 3.4 versions" { for item_s in "${name_subdir[@]}"; do
run_inline_definition_with_name --name=3.4 <<OUT item=($item_s)
echo "\${GET_PIP_URL}" name="${item[0]}"
subdir="${item[1]:-$name}"
run_inline_definition_with_name --name="$name" <<OUT
echo "\${DEFINITION_PATH##*/}:\${GET_PIP_URL}"
OUT OUT
assert_output "https://bootstrap.pypa.io/pip/3.4/get-pip.py" assert_output "$name:https://bootstrap.pypa.io/pip/$subdir/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for 3.5 versions" {
run_inline_definition_with_name --name=3.5 <<OUT
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/3.5/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for 3.6 versions" {
run_inline_definition_with_name --name=3.6 <<OUT
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/3.6/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for pypy2.7 versions" {
run_inline_definition_with_name --name=pypy2.7-7.3.12 <<OUT
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/2.7/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for pypy3.5 versions" {
run_inline_definition_with_name --name=pypy3.5-7.0.0 <<OUT
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/3.5/get-pip.py"
assert_success
}
@test "use the custom GET_PIP_URL for pypy3.6 versions" {
run_inline_definition_with_name --name=pypy3.6-7.3.3 <<OUT
echo "\${GET_PIP_URL}"
OUT
assert_output "https://bootstrap.pypa.io/pip/3.6/get-pip.py"
assert_success assert_success
done
} }

View File

@ -2,8 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int realpath_builtin(list) int realpath_builtin(WORD_LIST *list)
WORD_LIST *list;
{ {
int es; int es;
char *realbuf, *p; char *realbuf, *p;

View File

@ -79,6 +79,134 @@ OUT
assert_line "PYENV_SHELL_DETECT=bash" assert_line "PYENV_SHELL_DETECT=bash"
} }
@test "shell detection for fish startup file" {
run pyenv-init --detect-shell fish
assert_success
assert_line "PYENV_SHELL_DETECT=fish"
assert_line "PYENV_PROFILE_DETECT=~/.config/fish/config.fish"
assert_line "PYENV_RC_DETECT=~/.config/fish/config.fish"
}
@test "completion includes install option" {
run pyenv-init --complete
assert_success
assert_line "--install"
}
@test "install setup for detected shell startup files" {
mkdir -p "$HOME"
run pyenv-init --install
assert_success
expected_setup=$'export PYENV_ROOT="$HOME/.pyenv"\n[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"\neval "$(pyenv init - bash)"'
assert_equal "$expected_setup" "$(cat "$HOME/.bashrc")"
assert_equal "$expected_setup" "$(cat "$HOME/.profile")"
}
@test "install setup for bash uses existing bash_profile" {
mkdir -p "$HOME"
touch "$HOME/.bash_profile"
run pyenv-init --install bash
assert_success
expected_setup=$'export PYENV_ROOT="$HOME/.pyenv"\n[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"\neval "$(pyenv init - bash)"'
assert_equal "$expected_setup" "$(cat "$HOME/.bashrc")"
assert_equal "$expected_setup" "$(cat "$HOME/.bash_profile")"
assert [ ! -e "$HOME/.profile" ]
}
@test "install setup for zsh startup files" {
mkdir -p "$HOME"
run pyenv-init --install zsh
assert_success
expected_setup=$'export PYENV_ROOT="$HOME/.pyenv"\n[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"\neval "$(pyenv init - zsh)"'
assert_equal "$expected_setup" "$(cat "$HOME/.zshrc")"
assert_equal "$expected_setup" "$(cat "$HOME/.zprofile")"
}
@test "install setup for fish startup file" {
mkdir -p "$HOME"
create_stub fish <<OUT
printf '%s\n' "\$2" > "$PYENV_TEST_DIR/fish-script"
OUT
run pyenv-init --install fish
assert_success
expected_fish_script=$'set -Ux PYENV_ROOT $HOME/.pyenv\nif functions -q fish_add_path\n test -d $PYENV_ROOT/bin; and fish_add_path $PYENV_ROOT/bin\nelse\n test -d $PYENV_ROOT/bin; and set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths\nend'
expected_setup='pyenv init - fish | source'
assert_equal "$expected_fish_script" "$(cat "$PYENV_TEST_DIR/fish-script")"
assert_equal "$expected_setup" "$(cat "$HOME/.config/fish/config.fish")"
}
@test "install setup for pwsh startup file" {
mkdir -p "$HOME"
run pyenv-init --install pwsh
assert_success
expected_setup=$'$Env:PYENV_ROOT="$Env:HOME/.pyenv"\nif (Test-Path -LP "$Env:PYENV_ROOT/bin" -PathType Container) {\n $Env:PATH="$Env:PYENV_ROOT/bin:$Env:PATH" }\niex ((pyenv init -) -join "`n")'
assert_equal "$expected_setup" "$(cat "$HOME/.config/powershell/profile.ps1")"
}
@test "install refuses to modify files with pyenv-related code" {
mkdir -p "$HOME"
echo 'eval "$(pyenv init -)"' > "$HOME/.bashrc"
run pyenv-init --install bash
assert_failure
assert_line "pyenv: cannot automatically apply changes to $HOME/.bashrc: it appears to already contain Pyenv-related code."
assert_line "pyenv: review the file's contents and apply changes manually if necessary."
assert_line "pyenv: run \`pyenv init bash\` to see the suggested setup."
assert_equal 'eval "$(pyenv init -)"' "$(cat "$HOME/.bashrc")"
assert [ ! -e "$HOME/.profile" ]
}
@test "install treats PYENV_ROOT as pyenv-related code" {
mkdir -p "$HOME"
echo 'export PYENV_ROOT="$HOME/tools/python-env"' > "$HOME/.bashrc"
run pyenv-init --install bash
assert_failure
assert_line "pyenv: cannot automatically apply changes to $HOME/.bashrc: it appears to already contain Pyenv-related code."
}
@test "install refuses unreadable startup file without partial writes" {
mkdir -p "$HOME/.bashrc"
run pyenv-init --install bash
assert_failure
assert_line "pyenv: failed to inspect $HOME/.bashrc"
assert [ ! -e "$HOME/.profile" ]
}
@test "install setup keeps fish block intact when generic lines already exist" {
mkdir -p "$HOME/.config/fish"
create_stub fish <<OUT
exit 0
OUT
echo "end" > "$HOME/.config/fish/config.fish"
run pyenv-init --install fish
assert_success
expected_setup=$'end\npyenv init - fish | source'
assert_equal "$expected_setup" "$(cat "$HOME/.config/fish/config.fish")"
}
@test "install setup fails gracefully for unsupported shell" {
mkdir -p "$HOME"
run pyenv-init --install nu
assert_failure "pyenv: cannot automatically configure startup files for nu"
}
@test "option to skip rehash" { @test "option to skip rehash" {
run pyenv-init - --no-rehash run pyenv-init - --no-rehash
assert_success assert_success

View File

@ -38,18 +38,17 @@ pyenv: cannot rehash: couldn't acquire lock ${PYENV_ROOT}/shims/.pyenv-shim for
assert_success assert_success
} }
@test "stale lockfile is removed" { @test "removes stale lockfile" {
mkdir -p "${PYENV_ROOT}/shims" mkdir -p "${PYENV_ROOT}/shims"
#GNU and BSD `date` support generating relative dates via different syntax # A portable code to set mtime to "N minutes ago" is long and unwieldy,
# but BusyBox `date` used in Bash Docker images doesn't # see https://unix.stackexchange.com/questions/806015/portably-set-a-files-time-to-n-minutes-ago
# Using a fixed timestamp far in the past is infinitely simpler and good enough for the test
touch -t 200001010000.00 "${PYENV_ROOT}/shims/.pyenv-shim" touch -t 200001010000.00 "${PYENV_ROOT}/shims/.pyenv-shim"
run pyenv-rehash run pyenv-rehash
assert_success "" assert_success ""
assert [ ! -e "${PYENV_ROOT}/shims/.pyenv-shim" ] assert [ ! -e "${PYENV_ROOT}/shims/.pyenv-shim" ]
} }
@test "creates shims" { @test "creates shims" {
create_alt_executable_in_version "2.7" "python" create_alt_executable_in_version "2.7" "python"
create_alt_executable_in_version "2.7" "fab" create_alt_executable_in_version "2.7" "fab"