mirror of
https://github.com/pyenv/pyenv.git
synced 2026-10-02 23:41:06 +09:00
Compare commits
No commits in common. "master" and "v2.8.7" have entirely different histories.
15
COMMANDS.md
15
COMMANDS.md
@ -315,7 +315,7 @@ Lists all Python versions with the given command installed.
|
|||||||
|
|
||||||
## `pyenv exec`
|
## `pyenv exec`
|
||||||
|
|
||||||
Usage: pyenv exec [-N|--environment] <command> [arg1 arg2...]
|
Usage: pyenv exec <command> [arg1 arg2...]
|
||||||
|
|
||||||
Runs an executable by first preparing PATH so that the selected Python
|
Runs an executable by first preparing PATH so that the selected Python
|
||||||
version's `bin` directory is at the front.
|
version's `bin` directory is at the front.
|
||||||
@ -326,18 +326,7 @@ For example, if the currently selected Python version is 3.9.7:
|
|||||||
|
|
||||||
is equivalent to:
|
is equivalent to:
|
||||||
|
|
||||||
PYENV_VERSION="3.9.7" PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
|
PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
|
||||||
|
|
||||||
The `--environment` option sets `PYTHONHOME` and `LD_LIBRARY_PATH` (`DYLD_LIBRARY_PATH` in macOS) in the program's environment.
|
|
||||||
This is needed to run programs that embed Python by loading `libpython` without specifying rpath or an explicit path.
|
|
||||||
This breaks linking for programs that expect to link to a different `libpython` with the same name as one
|
|
||||||
in selected Python -- thus it's not done by default.
|
|
||||||
|
|
||||||
In macOS, System Integrity Protection (SIP) removes `DYLD_LIBRARY_PATH` from a process' environment
|
|
||||||
upon `exec` (not `fork`) if the executable being run is protected. The protection covers preinstalled system software
|
|
||||||
(including preinstalled shells) and does not cover user-installed apps and 3rd-party software. See
|
|
||||||
[About System Integrity Protection on your Mac - Apple Support](https://support.apple.com/en-us/102149)
|
|
||||||
for details.
|
|
||||||
|
|
||||||
## `pyenv root`
|
## `pyenv root`
|
||||||
|
|
||||||
|
|||||||
@ -2,17 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Summary: Run an executable with the selected Python version
|
# Summary: Run an executable with the selected Python version
|
||||||
#
|
#
|
||||||
# Usage: pyenv exec [-N|--environment] <command> [arg1 arg2...]
|
# Usage: pyenv exec <command> [arg1 arg2...]
|
||||||
#
|
|
||||||
# -N/--environment Set PYTHONHOME and LD_LIBRARY_PATH (DYLD_LIBRARY_PATH in macOS)
|
|
||||||
# envvars for the running command.
|
|
||||||
# This allows to run programs that embed Python without using rpath or
|
|
||||||
# exact library path to libpython.
|
|
||||||
# WARNING: For the running command and its child processes, this will
|
|
||||||
# break linkage for programs that expect to be linked to a different
|
|
||||||
# libpython instance with the same name!
|
|
||||||
# WARNING: In macOS, DYLD_LIBRARY_PATH will be unset by the system for
|
|
||||||
# processes covered by System Integrity Protection.
|
|
||||||
#
|
#
|
||||||
# Runs an executable by first preparing PATH so that the selected Python
|
# Runs an executable by first preparing PATH so that the selected Python
|
||||||
# version's `bin' directory is at the front.
|
# version's `bin' directory is at the front.
|
||||||
@ -28,16 +18,9 @@ set -e
|
|||||||
|
|
||||||
# Provide pyenv completions
|
# Provide pyenv completions
|
||||||
if [ "$1" = "--complete" ]; then
|
if [ "$1" = "--complete" ]; then
|
||||||
echo --environment
|
|
||||||
exec pyenv-shims --short
|
exec pyenv-shims --short
|
||||||
fi
|
fi
|
||||||
|
|
||||||
unset MODIFY_ENV
|
|
||||||
if [ "$1" = "-N" ] || [ "$1" = "--environment" ]; then
|
|
||||||
MODIFY_ENV=true
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
PYENV_VERSION="$(pyenv-version-name -f)"
|
PYENV_VERSION="$(pyenv-version-name -f)"
|
||||||
PYENV_COMMAND="$1"
|
PYENV_COMMAND="$1"
|
||||||
|
|
||||||
@ -71,27 +54,4 @@ if [ "${PYENV_BIN_PATH#${PYENV_ROOT}}" != "${PYENV_BIN_PATH}" ]; then
|
|||||||
# Only add to $PATH for non-system version.
|
# Only add to $PATH for non-system version.
|
||||||
export PATH="${PYENV_BIN_PATH}:${PATH}"
|
export PATH="${PYENV_BIN_PATH}:${PATH}"
|
||||||
fi
|
fi
|
||||||
if [ -n "$MODIFY_ENV" ]; then
|
|
||||||
|
|
||||||
# Check if multiple Python versions are selected
|
|
||||||
VERSIONS=$(pyenv-prefix)
|
|
||||||
if [[ "$VERSIONS" == *:* ]]; then
|
|
||||||
VERSION="${VERSIONS%%:*}"
|
|
||||||
echo "pyenv: Warning: multiple Python versions are selected." \
|
|
||||||
"Setting environment variables for the first one, (${VERSION#$PYENV_ROOT})" >&2
|
|
||||||
else
|
|
||||||
VERSION="$VERSIONS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Assign the correct version of PYTHONHOME
|
|
||||||
export PYTHONHOME="$VERSION"
|
|
||||||
case "$(uname -s)" in
|
|
||||||
Darwin)
|
|
||||||
export DYLD_LIBRARY_PATH="${PYTHONHOME}/lib${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export LD_LIBRARY_PATH="${PYTHONHOME}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
exec "$PYENV_COMMAND_PATH" "$@"
|
exec "$PYENV_COMMAND_PATH" "$@"
|
||||||
|
|||||||
@ -33,11 +33,6 @@ proceeds.
|
|||||||
pyenv binary install 3.14.7
|
pyenv binary install 3.14.7
|
||||||
```
|
```
|
||||||
|
|
||||||
A definition with the selected package entry's name in a plugin's
|
|
||||||
`share/python-build` directory overrides the published definition. The normal
|
|
||||||
Python-Build search order applies, including `PYTHON_BUILD_DEFINITIONS`.
|
|
||||||
Local definitions are installed without downloading the stock definition.
|
|
||||||
|
|
||||||
### `pyenv binary package [-v|--verbose] <version>[:<entry>] --archive-base-url <url>`
|
### `pyenv binary package [-v|--verbose] <version>[:<entry>] --archive-base-url <url>`
|
||||||
|
|
||||||
Installs `<version>` from source under a separate name, packages that install
|
Installs `<version>` from source under a separate name, packages that install
|
||||||
|
|||||||
@ -100,12 +100,6 @@ if [ -z "$entry" ]; then
|
|||||||
echo "pyenv-binary: no binary available for $requested on $os/$arch" >&2
|
echo "pyenv-binary: no binary available for $requested on $os/$arch" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
definitions="$(pyenv-install --list --bare)" || definitions=""
|
|
||||||
if printf '%s\n' "$definitions" | grep -qxF -- "$entry"; then
|
|
||||||
pyenv-install "$entry:$version"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [[ "$expected_sha" =~ ^[0-9a-fA-F]{64}$ ]]; then
|
if ! [[ "$expected_sha" =~ ^[0-9a-fA-F]{64}$ ]]; then
|
||||||
echo "pyenv-binary: invalid checksum for $entry" >&2
|
echo "pyenv-binary: invalid checksum for $entry" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@ -44,7 +44,7 @@ STUB
|
|||||||
"$(host_distro)" 0 >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
"$(host_distro)" 0 >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
||||||
stub_downloads
|
stub_downloads
|
||||||
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
||||||
create_stub pyenv-install '[ "$1" = --list ] && exit; echo installed'
|
create_stub pyenv-install 'echo installed'
|
||||||
|
|
||||||
run pyenv-binary-install 3.14.7
|
run pyenv-binary-install 3.14.7
|
||||||
assert_failure
|
assert_failure
|
||||||
@ -58,64 +58,6 @@ STUB
|
|||||||
assert_success ""
|
assert_success ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "a plugin definition overrides a published binary without its checksum" {
|
|
||||||
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
|
|
||||||
use_manifest
|
|
||||||
export TMPDIR="$BATS_TEST_TMPDIR/temp"
|
|
||||||
mkdir -p "$TMPDIR"
|
|
||||||
local entry="3.14.7-ubuntu-24.04-x86_64"
|
|
||||||
printf '3.14.7\t%s\tLinux\tx86_64\t%s\t%s\n' "$entry" \
|
|
||||||
"$(host_distro)" "" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
|
||||||
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
|
||||||
create_stub curl 'touch "$BATS_TEST_TMPDIR/downloaded"; exit 1'
|
|
||||||
PATH="${BATS_TEST_DIRNAME}/../../python-build/bin:$PATH"
|
|
||||||
mkdir -p "$PYENV_ROOT/plugins/first/share/python-build" "$PYENV_ROOT/plugins/second/share/python-build"
|
|
||||||
printf '%s\n' 'mkdir -p "$PREFIX_PATH"; echo first > "$PREFIX_PATH/marker"' \
|
|
||||||
> "$PYENV_ROOT/plugins/first/share/python-build/$entry"
|
|
||||||
echo 'exit 1' > "$PYENV_ROOT/plugins/second/share/python-build/$entry"
|
|
||||||
|
|
||||||
run pyenv-binary-install 3.14
|
|
||||||
assert_success ""
|
|
||||||
assert_equal first "$(cat "$PYENV_ROOT/versions/3.14.7/marker")"
|
|
||||||
[ ! -e "$BATS_TEST_TMPDIR/downloaded" ]
|
|
||||||
assert_equal "" "$(find "$TMPDIR" -mindepth 1 -maxdepth 1 -type d)"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "an explicit definition path takes precedence over a plugin definition" {
|
|
||||||
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
|
|
||||||
use_manifest
|
|
||||||
local entry="3.14.7-ubuntu-24.04-x86_64"
|
|
||||||
printf '3.14.7\t%s\tLinux\tx86_64\t%s\t%s\n' "$entry" \
|
|
||||||
"$(host_distro)" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
|
||||||
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
|
||||||
create_stub curl 'touch "$BATS_TEST_TMPDIR/downloaded"; exit 1'
|
|
||||||
PATH="${BATS_TEST_DIRNAME}/../../python-build/bin:$PATH"
|
|
||||||
export PYTHON_BUILD_DEFINITIONS="$BATS_TEST_TMPDIR/custom definitions"
|
|
||||||
mkdir -p "$PYTHON_BUILD_DEFINITIONS" "$PYENV_ROOT/plugins/custom/share/python-build"
|
|
||||||
printf '%s\n' 'mkdir -p "$PREFIX_PATH"; echo custom > "$PREFIX_PATH/marker"' \
|
|
||||||
> "$PYTHON_BUILD_DEFINITIONS/$entry"
|
|
||||||
echo 'exit 1' > "$PYENV_ROOT/plugins/custom/share/python-build/$entry"
|
|
||||||
|
|
||||||
run pyenv-binary-install 3.14.7
|
|
||||||
assert_success ""
|
|
||||||
assert_equal custom "$(cat "$PYENV_ROOT/versions/3.14.7/marker")"
|
|
||||||
[ ! -e "$BATS_TEST_TMPDIR/downloaded" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "rejects an invalid published checksum when definition lookup fails" {
|
|
||||||
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
|
|
||||||
use_manifest
|
|
||||||
printf '3.14.7\t3.14.7-ubuntu-24.04-x86_64\tLinux\tx86_64\t%s\tinvalid\n' \
|
|
||||||
"$(host_distro)" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
|
||||||
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
|
||||||
create_stub pyenv-install 'exit 1'
|
|
||||||
create_stub curl 'touch "$BATS_TEST_TMPDIR/downloaded"; exit 1'
|
|
||||||
|
|
||||||
run pyenv-binary-install 3.14.7
|
|
||||||
assert_failure "pyenv-binary: invalid checksum for 3.14.7-ubuntu-24.04-x86_64"
|
|
||||||
[ ! -e "$BATS_TEST_TMPDIR/downloaded" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "installs a matching published binary with an uppercase checksum" {
|
@test "installs a matching published binary with an uppercase checksum" {
|
||||||
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
|
create_stub lsb_release 'case "$1" in -si) echo Ubuntu;; -sr) echo 24.04;; esac'
|
||||||
use_manifest
|
use_manifest
|
||||||
@ -128,7 +70,6 @@ STUB
|
|||||||
stub_downloads
|
stub_downloads
|
||||||
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
||||||
create_stub pyenv-install <<'STUB'
|
create_stub pyenv-install <<'STUB'
|
||||||
[ "$1" = --list ] && exit
|
|
||||||
definition="${1%:*}"
|
definition="${1%:*}"
|
||||||
printf '%s:%s\n' "${definition##*/}" "${1##*:}"
|
printf '%s:%s\n' "${definition##*/}" "${1##*:}"
|
||||||
cat "$definition"
|
cat "$definition"
|
||||||
@ -148,7 +89,7 @@ definition"
|
|||||||
"$(host_distro)" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
"$(host_distro)" "$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
||||||
stub_downloads
|
stub_downloads
|
||||||
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
create_stub uname 'case "$1" in -s) echo Linux;; -m) echo x86_64;; esac'
|
||||||
create_stub pyenv-install '[ "$1" = --list ] && exit; echo "${1##*:}"'
|
create_stub pyenv-install 'echo "${1##*:}"'
|
||||||
|
|
||||||
run pyenv-binary-install 3.14
|
run pyenv-binary-install 3.14
|
||||||
assert_success "3.14.10"
|
assert_success "3.14.10"
|
||||||
@ -184,7 +125,7 @@ definition"
|
|||||||
stub_downloads
|
stub_downloads
|
||||||
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
|
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
|
||||||
create_stub sw_vers 'echo 26.6.2'
|
create_stub sw_vers 'echo 26.6.2'
|
||||||
create_stub pyenv-install '[ "$1" = --list ] && exit; echo "${1##*:}"'
|
create_stub pyenv-install 'echo "${1##*:}"'
|
||||||
|
|
||||||
run pyenv-binary-install 3.14.7
|
run pyenv-binary-install 3.14.7
|
||||||
assert_success "3.14.7"
|
assert_success "3.14.7"
|
||||||
@ -196,7 +137,7 @@ definition"
|
|||||||
"$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
"$definition_sha" >> "$BATS_TEST_TMPDIR/plugin/share/pyenv-binary/versions/3.14"
|
||||||
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
|
create_stub uname 'case "$1" in -s) echo Darwin;; -m) echo arm64;; esac'
|
||||||
create_stub sw_vers 'echo 15.7.8'
|
create_stub sw_vers 'echo 15.7.8'
|
||||||
create_stub pyenv-install '[ "$1" = --list ] && exit; echo installed'
|
create_stub pyenv-install 'echo installed'
|
||||||
|
|
||||||
run pyenv-binary-install 3.14.7
|
run pyenv-binary-install 3.14.7
|
||||||
assert_failure "pyenv-binary: no binary available for 3.14.7 on Darwin/arm64"
|
assert_failure "pyenv-binary: no binary available for 3.14.7 on Darwin/arm64"
|
||||||
|
|||||||
@ -34,7 +34,6 @@ EOF
|
|||||||
assert_success
|
assert_success
|
||||||
assert_output <<OUT
|
assert_output <<OUT
|
||||||
--help
|
--help
|
||||||
--environment
|
|
||||||
fab
|
fab
|
||||||
python
|
python
|
||||||
OUT
|
OUT
|
||||||
@ -140,53 +139,3 @@ $envvarname=/unusual/shim/location:/another/shim/location
|
|||||||
_PYENV_SHIM_PATH=
|
_PYENV_SHIM_PATH=
|
||||||
!
|
!
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "--environment sets envvars in Linux" {
|
|
||||||
export PYENV_VERSION="test"
|
|
||||||
create_alt_executable print_env <<!
|
|
||||||
#!$BASH
|
|
||||||
echo PYTHONHOME="\$PYTHONHOME"
|
|
||||||
echo LD_LIBRARY_PATH="\$LD_LIBRARY_PATH"
|
|
||||||
!
|
|
||||||
create_path_executable uname "echo Linux"
|
|
||||||
|
|
||||||
LD_LIBRARY_PATH= run pyenv-exec -N print_env
|
|
||||||
assert_output_glob <<!
|
|
||||||
PYTHONHOME=*/test
|
|
||||||
LD_LIBRARY_PATH=*/test/lib
|
|
||||||
!
|
|
||||||
|
|
||||||
LD_LIBRARY_PATH=/foo/bar run pyenv-exec -N print_env
|
|
||||||
assert_output_glob <<!
|
|
||||||
PYTHONHOME=*/test
|
|
||||||
LD_LIBRARY_PATH=*/test/lib:/foo/bar
|
|
||||||
!
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "--environment sets envvars in macOS" {
|
|
||||||
if [[ $(uname -s) == "Darwin" && $BASH == "/bin/bash" \
|
|
||||||
&& $(LC_ALL=C csrutil status) == *"enabled." ]]; then
|
|
||||||
skip "macOS with Bash covered by SIP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export PYENV_VERSION="test"
|
|
||||||
create_alt_executable print_env <<!
|
|
||||||
#!$BASH
|
|
||||||
echo PYTHONHOME="\$PYTHONHOME"
|
|
||||||
echo DYLD_LIBRARY_PATH="\$DYLD_LIBRARY_PATH"
|
|
||||||
!
|
|
||||||
create_path_executable uname "echo Darwin"
|
|
||||||
|
|
||||||
DYLD_LIBRARY_PATH= run pyenv-exec -N print_env
|
|
||||||
assert_output_glob <<!
|
|
||||||
PYTHONHOME=*/test
|
|
||||||
DYLD_LIBRARY_PATH=*/test/lib
|
|
||||||
!
|
|
||||||
|
|
||||||
|
|
||||||
DYLD_LIBRARY_PATH=/foo/bar run pyenv-exec -N print_env
|
|
||||||
assert_output_glob <<!
|
|
||||||
PYTHONHOME=*/test
|
|
||||||
DYLD_LIBRARY_PATH=*/test/lib:/foo/bar
|
|
||||||
!
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user