Support missing versions being present and set in a local .python-version (#3134)
Requested in https://github.com/pyenv/pyenv/issues/2680 for deployments with a stock `.pyenv-version` that can use any of a number of Python versions and for compatibility with `uv`. * Support `pyenv local --force` * Support `pyenv-version-file-write --force` * Support `pyenv version-name --force` * Ignore missing versions when searching for executables * Display "commmand not found" even when there are nonexistent versions * exec.bats: replace `python` and `rspec` with something that doesn't exist globally, either in Ubuntu Github CI, `python` exists globally
This commit is contained in:
parent
aef6a2a6d0
commit
dc873cf568
@ -91,6 +91,10 @@ or, if you prefer 3.3.3 over 2.7.6,
|
||||
Python 3.3.3
|
||||
|
||||
|
||||
You can use the `-f/--force` flag to force setting versions even if some aren't installed.
|
||||
This is mainly useful in special cases like provisioning scripts.
|
||||
|
||||
|
||||
## `pyenv global`
|
||||
|
||||
Sets the global version of Python to be used in all shells by writing
|
||||
|
@ -21,7 +21,7 @@ if [ "$1" = "--complete" ]; then
|
||||
exec pyenv-shims --short
|
||||
fi
|
||||
|
||||
PYENV_VERSION="$(pyenv-version-name)"
|
||||
PYENV_VERSION="$(pyenv-version-name -f)"
|
||||
PYENV_COMMAND="$1"
|
||||
|
||||
if [ -z "$PYENV_COMMAND" ]; then
|
||||
@ -29,9 +29,9 @@ if [ -z "$PYENV_COMMAND" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PYENV_VERSION
|
||||
PYENV_COMMAND_PATH="$(pyenv-which "$PYENV_COMMAND")"
|
||||
PYENV_BIN_PATH="${PYENV_COMMAND_PATH%/*}"
|
||||
export PYENV_VERSION
|
||||
|
||||
OLDIFS="$IFS"
|
||||
IFS=$'\n' scripts=(`pyenv-hooks exec`)
|
||||
|
@ -2,9 +2,11 @@
|
||||
#
|
||||
# Summary: Set or show the local application-specific Python version(s)
|
||||
#
|
||||
# Usage: pyenv local <version> <version2> <..>
|
||||
# Usage: pyenv local [-f|--force] [<version> [...]]
|
||||
# pyenv local --unset
|
||||
#
|
||||
# -f/--force Do not verify that the versions being set exist
|
||||
#
|
||||
# Sets the local application-specific Python version(s) by writing the
|
||||
# version name to a file named `.python-version'.
|
||||
#
|
||||
@ -36,12 +38,25 @@ if [ "$1" = "--complete" ]; then
|
||||
exec pyenv-versions --bare
|
||||
fi
|
||||
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
versions=("$@")
|
||||
|
||||
if [ "$versions" = "--unset" ]; then
|
||||
rm -f .python-version
|
||||
elif [ -n "$versions" ]; then
|
||||
pyenv-version-file-write .python-version "${versions[@]}"
|
||||
pyenv-version-file-write ${FORCE:+-f }.python-version "${versions[@]}"
|
||||
else
|
||||
if version_file="$(pyenv-version-file "$PWD")"; then
|
||||
IFS=: versions=($(pyenv-version-file-read "$version_file"))
|
||||
|
@ -1,9 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Usage: pyenv version-file-write <file> <version>
|
||||
# Usage: pyenv version-file-write [-f|--force] <file> <version> [...]
|
||||
#
|
||||
# -f/--force Don't verify that the versions exist
|
||||
|
||||
set -e
|
||||
[ -n "$PYENV_DEBUG" ] && set -x
|
||||
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
PYENV_VERSION_FILE="$1"
|
||||
shift || true
|
||||
versions=("$@")
|
||||
@ -14,7 +30,7 @@ if [ -z "$versions" ] || [ -z "$PYENV_VERSION_FILE" ]; then
|
||||
fi
|
||||
|
||||
# Make sure the specified version is installed.
|
||||
pyenv-prefix "${versions[@]}" >/dev/null
|
||||
[[ -z $FORCE ]] && pyenv-prefix "${versions[@]}" >/dev/null
|
||||
|
||||
# Write the version out to disk.
|
||||
# Create an empty file. Using "rm" might cause a permission error.
|
||||
|
@ -1,8 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Summary: Show the current Python version
|
||||
#
|
||||
# -f/--force (Internal) If a version doesn't exist, print it as is rather than produce an error
|
||||
|
||||
set -e
|
||||
[ -n "$PYENV_DEBUG" ] && set -x
|
||||
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
if [ -z "$PYENV_VERSION" ]; then
|
||||
PYENV_VERSION_FILE="$(pyenv-version-file)"
|
||||
PYENV_VERSION="$(pyenv-version-file-read "$PYENV_VERSION_FILE" || true)"
|
||||
@ -33,16 +50,20 @@ OLDIFS="$IFS"
|
||||
# Remove the explicit 'python-' prefix from versions like 'python-3.12'.
|
||||
normalised_version="${version#python-}"
|
||||
if version_exists "${version}" || [ "$version" = "system" ]; then
|
||||
versions=("${versions[@]}" "${version}")
|
||||
versions+=("${version}")
|
||||
elif version_exists "${normalised_version}"; then
|
||||
versions=("${versions[@]}" "${normalised_version}")
|
||||
versions+=("${normalised_version}")
|
||||
elif resolved_version="$(pyenv-latest -b "${version}")"; then
|
||||
versions=("${versions[@]}" "${resolved_version}")
|
||||
versions+=("${resolved_version}")
|
||||
elif resolved_version="$(pyenv-latest -b "${normalised_version}")"; then
|
||||
versions=("${versions[@]}" "${resolved_version}")
|
||||
versions+=("${resolved_version}")
|
||||
else
|
||||
echo "pyenv: version \`$version' is not installed (set by $(pyenv-version-origin))" >&2
|
||||
any_not_installed=1
|
||||
if [[ -n $FORCE ]]; then
|
||||
versions+=("${normalised_version}")
|
||||
else
|
||||
echo "pyenv: version \`$version' is not installed (set by $(pyenv-version-origin))" >&2
|
||||
any_not_installed=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ else
|
||||
for version in "${nonexistent_versions[@]}"; do
|
||||
echo "pyenv: version \`$version' is not installed (set by $(pyenv-version-origin))" >&2
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "pyenv: $PYENV_COMMAND: command not found" >&2
|
||||
|
@ -16,16 +16,22 @@ create_executable() {
|
||||
|
||||
@test "fails with invalid version" {
|
||||
export PYENV_VERSION="3.4"
|
||||
run pyenv-exec python -V
|
||||
assert_failure "pyenv: version \`3.4' is not installed (set by PYENV_VERSION environment variable)"
|
||||
run pyenv-exec nonexistent
|
||||
assert_failure <<EOF
|
||||
pyenv: version \`3.4' is not installed (set by PYENV_VERSION environment variable)
|
||||
pyenv: nonexistent: command not found
|
||||
EOF
|
||||
}
|
||||
|
||||
@test "fails with invalid version set from file" {
|
||||
mkdir -p "$PYENV_TEST_DIR"
|
||||
cd "$PYENV_TEST_DIR"
|
||||
echo 2.7 > .python-version
|
||||
run pyenv-exec rspec
|
||||
assert_failure "pyenv: version \`2.7' is not installed (set by $PWD/.python-version)"
|
||||
run pyenv-exec nonexistent
|
||||
assert_failure <<EOF
|
||||
pyenv: version \`2.7' is not installed (set by $PWD/.python-version)
|
||||
pyenv: nonexistent: command not found
|
||||
EOF
|
||||
}
|
||||
|
||||
@test "completes with names of executables" {
|
||||
|
@ -41,6 +41,18 @@ setup() {
|
||||
assert [ "$(cat .python-version)" = "1.2.3" ]
|
||||
}
|
||||
|
||||
@test "fails to set a nonexistent local version" {
|
||||
run pyenv-local 1.2.3
|
||||
assert_failure "pyenv: version \`1.2.3' not installed"
|
||||
assert [ ! -e .python-version ]
|
||||
}
|
||||
|
||||
@test "sets a nonexistent local version with --force" {
|
||||
run pyenv-local -f 1.2.3
|
||||
assert_success ""
|
||||
assert [ "$(cat .python-version)" = "1.2.3" ]
|
||||
}
|
||||
|
||||
@test "changes local version" {
|
||||
echo "1.0-pre" > .python-version
|
||||
mkdir -p "${PYENV_ROOT}/versions/1.2.3"
|
||||
|
@ -9,7 +9,7 @@ setup() {
|
||||
|
||||
@test "invocation without 2 arguments prints usage" {
|
||||
run pyenv-version-file-write
|
||||
assert_failure "Usage: pyenv version-file-write <file> <version>"
|
||||
assert_failure "Usage: pyenv version-file-write [-f|--force] <file> <version> [...]"
|
||||
run pyenv-version-file-write "one" ""
|
||||
assert_failure
|
||||
}
|
||||
@ -21,6 +21,13 @@ setup() {
|
||||
assert [ ! -e ".python-version" ]
|
||||
}
|
||||
|
||||
@test "setting nonexistent version succeeds with force" {
|
||||
assert [ ! -e ".python-version" ]
|
||||
run pyenv-version-file-write --force ".python-version" "2.7.6"
|
||||
assert_success
|
||||
assert [ -e ".python-version" ]
|
||||
}
|
||||
|
||||
@test "writes value to arbitrary file" {
|
||||
mkdir -p "${PYENV_ROOT}/versions/2.7.6"
|
||||
assert [ ! -e "my-version" ]
|
||||
|
@ -73,6 +73,11 @@ SH
|
||||
assert_failure "pyenv: version \`1.2' is not installed (set by PYENV_VERSION environment variable)"
|
||||
}
|
||||
|
||||
@test "missing version with --force" {
|
||||
PYENV_VERSION=1.2 run pyenv-version-name -f
|
||||
assert_success "1.2"
|
||||
}
|
||||
|
||||
@test "one missing version (second missing)" {
|
||||
create_version "3.5.1"
|
||||
PYENV_VERSION="3.5.1:1.2" run pyenv-version-name
|
||||
|
@ -71,7 +71,16 @@ create_executable() {
|
||||
@test "version not installed" {
|
||||
create_executable "3.4" "py.test"
|
||||
PYENV_VERSION=3.3 run pyenv-which py.test
|
||||
assert_failure "pyenv: version \`3.3' is not installed (set by PYENV_VERSION environment variable)"
|
||||
assert_failure <<OUT
|
||||
pyenv: version \`3.3' is not installed (set by PYENV_VERSION environment variable)
|
||||
pyenv: py.test: command not found
|
||||
|
||||
The \`py.test' command exists in these Python versions:
|
||||
3.4
|
||||
|
||||
Note: See 'pyenv help global' for tips on allowing both
|
||||
python2 and python3 to be found.
|
||||
OUT
|
||||
}
|
||||
|
||||
@test "versions not installed" {
|
||||
@ -80,6 +89,13 @@ create_executable() {
|
||||
assert_failure <<OUT
|
||||
pyenv: version \`2.7' is not installed (set by PYENV_VERSION environment variable)
|
||||
pyenv: version \`3.3' is not installed (set by PYENV_VERSION environment variable)
|
||||
pyenv: py.test: command not found
|
||||
|
||||
The \`py.test' command exists in these Python versions:
|
||||
3.4
|
||||
|
||||
Note: See 'pyenv help global' for tips on allowing both
|
||||
python2 and python3 to be found.
|
||||
OUT
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user