Compare commits

..

No commits in common. "master" and "v1.3.0" have entirely different histories.

10 changed files with 207 additions and 320 deletions

View file

@ -6,12 +6,11 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: os:
- ubuntu-22.04
- ubuntu-24.04 - ubuntu-24.04
- macos-14 - ubuntu-22.04
- macos-15
- macos-15-intel - macos-15-intel
- macos-26 - macos-15
- macos-14
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

View file

@ -1,9 +1,5 @@
## Version History ## Version History
## v1.4.0
* Fix POSIX sh (dash) compatibility in pyenv-virtualenv-init by @chrisolof in https://github.com/pyenv/pyenv-virtualenv/pull/526
* Improve performance and output of `pyenv virtualenvs` by @samdoran in https://github.com/pyenv/pyenv-virtualenv/pull/502
## v1.3.0 ## v1.3.0
* CI: cleanup by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/521 * CI: cleanup by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/521
* CI: tests: use Bats 1.10; support concurrent, out-of-order and multiple-times execution of stub commands; fix race condition between concurrent stubs by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/520 * CI: tests: use Bats 1.10; support concurrent, out-of-order and multiple-times execution of stub commands; fix race condition between concurrent stubs by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/520

View file

@ -13,7 +13,7 @@
# -u/--upgrade Imply --force # -u/--upgrade Imply --force
# #
PYENV_VIRTUALENV_VERSION="1.4.0" PYENV_VIRTUALENV_VERSION="1.3.0"
set -e set -e
[ -n "$PYENV_DEBUG" ] && set -x [ -n "$PYENV_DEBUG" ] && set -x
@ -24,7 +24,7 @@ fi
# Provide pyenv completions # Provide pyenv completions
if [ "$1" = "--complete" ]; then if [ "$1" = "--complete" ]; then
exec pyenv-versions --bare --skip-envs exec pyenv-versions --bare
fi fi
unset PIP_REQUIRE_VENV unset PIP_REQUIRE_VENV

View file

@ -120,13 +120,22 @@ esac
case "$shell" in case "$shell" in
fish ) fish )
cat <<EOS if [ -n "$_has_version_hooks" ]; then
cat <<EOS
function _pyenv_virtualenv_hook --on-event fish_prompt; function _pyenv_virtualenv_hook --on-event fish_prompt;
set -l ret \$status set -l ret \$status
if [ -n "\$VIRTUAL_ENV" ]
pyenv activate --quiet; or pyenv deactivate --quiet; or true
else
pyenv activate --quiet; or true
end
return \$ret
end
EOS EOS
else
if [ -z "$_has_version_hooks" ]; then
cat <<EOS cat <<EOS
function _pyenv_virtualenv_hook --on-event fish_prompt;
set -l ret \$status
if test "\$PYENV_VERSION" = "\$_PYENV_VH_VERSION" \\ if test "\$PYENV_VERSION" = "\$_PYENV_VH_VERSION" \\
-a "\$VIRTUAL_ENV" = "\$_PYENV_VH_VENV" -a "\$VIRTUAL_ENV" = "\$_PYENV_VH_VENV"
if test -n "\$PYENV_VERSION" if test -n "\$PYENV_VERSION"
@ -137,19 +146,11 @@ EOS
return \$ret return \$ret
end end
end end
EOS
fi
cat <<EOS
if [ -n "\$VIRTUAL_ENV" ] if [ -n "\$VIRTUAL_ENV" ]
pyenv activate --quiet; or pyenv deactivate --quiet; or true pyenv activate --quiet; or pyenv deactivate --quiet; or true
else else
pyenv activate --quiet; or true pyenv activate --quiet; or true
end end
EOS
if [ -z "$_has_version_hooks" ]; then
cat <<EOS
set -g _PYENV_VH_PWD "\$PWD" set -g _PYENV_VH_PWD "\$PWD"
set -g _PYENV_VH_VERSION "\$PYENV_VERSION" set -g _PYENV_VH_VERSION "\$PYENV_VERSION"
set -g _PYENV_VH_VENV "\$VIRTUAL_ENV" set -g _PYENV_VH_VENV "\$VIRTUAL_ENV"
@ -174,23 +175,39 @@ EOS
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$PYENV_ROOT/version" set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$PYENV_ROOT/version"
end end
set -g _PYENV_VH_MTIMES (stat ${_stat_fmt} \$_PYENV_VH_PATHS 2>/dev/null) set -g _PYENV_VH_MTIMES (stat ${_stat_fmt} \$_PYENV_VH_PATHS 2>/dev/null)
EOS
fi
cat <<EOS
return \$ret return \$ret
end end
EOS
fi
;;
ksh )
cat <<EOS
function _pyenv_virtualenv_hook() {
EOS EOS
;; ;;
* )
bash|zsh )
cat <<EOS cat <<EOS
_pyenv_virtualenv_hook() { _pyenv_virtualenv_hook() {
local ret=\$?
EOS EOS
;;
esac
if [ -z "$_has_version_hooks" ]; then if [[ "$shell" != "fish" ]]; then
if [ -n "$_has_version_hooks" ]; then
cat <<EOS cat <<EOS
local ret=\$?
if [ -n "\${VIRTUAL_ENV-}" ]; then
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
else
eval "\$(pyenv sh-activate --quiet || true)" || true
fi
return \$ret
};
EOS
else
cat <<EOS
local ret=\$?
# Cache: env vars checked once, path list and stat rebuilt on miss only
if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\ if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then && [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
if [ -n "\${PYENV_VERSION-}" ]; then if [ -n "\${PYENV_VERSION-}" ]; then
@ -201,19 +218,11 @@ EOS
return \$ret return \$ret
fi fi
fi fi
EOS
fi
cat <<EOS
if [ -n "\${VIRTUAL_ENV-}" ]; then if [ -n "\${VIRTUAL_ENV-}" ]; then
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
else else
eval "\$(pyenv sh-activate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || true)" || true
fi fi
EOS
if [ -z "$_has_version_hooks" ]; then
cat <<EOS
_PYENV_VH_PWD="\${PWD}" _PYENV_VH_PWD="\${PWD}"
_PYENV_VH_VERSION="\${PYENV_VERSION-}" _PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}" _PYENV_VH_VENV="\${VIRTUAL_ENV-}"
@ -237,33 +246,29 @@ EOS
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version") _PYENV_VH_PATHS+=("\${PYENV_ROOT}/version")
fi fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" _PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)"
EOS
fi
cat <<EOS
return \$ret return \$ret
}; };
EOS EOS
;; fi
esac
case "$shell" in case "$shell" in
bash ) bash )
cat <<EOS cat <<EOS
if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then
PROMPT_COMMAND="_pyenv_virtualenv_hook;\${PROMPT_COMMAND-}" PROMPT_COMMAND="_pyenv_virtualenv_hook;\${PROMPT_COMMAND-}"
fi fi
EOS EOS
;; ;;
zsh ) zsh )
cat <<EOS cat <<EOS
typeset -g -a precmd_functions typeset -g -a precmd_functions
if [[ -z \$precmd_functions[(r)_pyenv_virtualenv_hook] ]]; then if [[ -z \$precmd_functions[(r)_pyenv_virtualenv_hook] ]]; then
precmd_functions=(_pyenv_virtualenv_hook \$precmd_functions); precmd_functions=(_pyenv_virtualenv_hook \$precmd_functions);
fi fi
EOS EOS
;; ;;
* ) * )
# No prompt command support or it's installed elsewhere # FIXME: what should i do here??
;; ;;
esac esac
fi

View file

@ -26,17 +26,13 @@ if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv" PYENV_ROOT="${HOME}/.pyenv"
fi fi
OLDIFS="$IFS"
IFS=:
if [ -n "$1" ]; then if [ -n "$1" ]; then
# $@ is not affected by IFS versions=($@)
versions=("$@") IFS=: PYENV_VERSION="${versions[*]}"
PYENV_VERSION="${versions[*]}"
export PYENV_VERSION export PYENV_VERSION
else else
versions=($(pyenv-version-name)) IFS=: versions=($(pyenv-version-name))
fi fi
IFS="$OLDIFS"
append_virtualenv_prefix() { append_virtualenv_prefix() {
if [ -d "${VIRTUALENV_PREFIX_PATH}" ]; then if [ -d "${VIRTUALENV_PREFIX_PATH}" ]; then
@ -53,18 +49,7 @@ for version in "${versions[@]}"; do
echo "pyenv-virtualenv: version \`${version}' is not a virtualenv" 1>&2 echo "pyenv-virtualenv: version \`${version}' is not a virtualenv" 1>&2
exit 1 exit 1
fi fi
PYENV_PREFIX_PATH="$(pyenv-prefix "${version}")"
# In the vast majority of cases, there's a direct match and
# not spawning `pyenv-prefix' saves about half the invocation time
# with a signle argument which accumulates when called repeatedly
# (e.g. from `pyenv-virtualenvs').
# `pyenv-prefix' also does not have hooks to worry about.
# XXX: refactor the test into a shared module?
PYENV_PREFIX_PATH="${PYENV_ROOT}/versions/${version}"
if [[ ! -d "$PYENV_PREFIX_PATH" ]]; then
PYENV_PREFIX_PATH="$(pyenv-prefix "${version}")"
fi
if [ -x "${PYENV_PREFIX_PATH}/bin/python" ]; then if [ -x "${PYENV_PREFIX_PATH}/bin/python" ]; then
if [ -f "${PYENV_PREFIX_PATH}/bin/activate" ]; then if [ -f "${PYENV_PREFIX_PATH}/bin/activate" ]; then
if [ -f "${PYENV_PREFIX_PATH}/bin/conda" ]; then if [ -f "${PYENV_PREFIX_PATH}/bin/conda" ]; then
@ -109,7 +94,4 @@ for version in "${versions[@]}"; do
fi fi
done done
OLDIFS="$IFS" IFS=: echo "${VIRTUALENV_PREFIX_PATHS[*]}"
IFS=:
echo "${VIRTUALENV_PREFIX_PATHS[*]}"
IFS="$OLDIFS"

View file

@ -6,9 +6,24 @@
# List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'. # List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'.
set -e set -e
[[ -n $PYENV_DEBUG ]] && set -x [ -n "$PYENV_DEBUG" ] && set -x
if [ -L "${BASH_SOURCE}" ]; then
READLINK=$(type -p greadlink readlink | head -1)
if [ -z "$READLINK" ]; then
echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2
exit 1
fi
resolve_link() {
$READLINK -f "$1"
}
script_path=$(resolve_link ${BASH_SOURCE})
else
script_path=${BASH_SOURCE}
fi
if [[ -z $PYENV_ROOT ]]; then . ${script_path%/*}/../libexec/pyenv-virtualenv-realpath
if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv" PYENV_ROOT="${HOME}/.pyenv"
fi fi
@ -32,26 +47,28 @@ done
versions_dir="${PYENV_ROOT}/versions" versions_dir="${PYENV_ROOT}/versions"
if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then if [ -d "$versions_dir" ]; then
declare -A current_versions versions_dir="$(realpath "$versions_dir")"
else
current_versions=()
fi fi
if [[ -z $bare ]]; then
if [ -n "$bare" ]; then
hit_prefix=""
miss_prefix=""
current_versions=()
unset print_origin
include_system=""
else
hit_prefix="* " hit_prefix="* "
miss_prefix=" " miss_prefix=" "
OLDIFS="$IFS" OLDIFS="$IFS"
IFS=: IFS=: current_versions=($(pyenv-version-name || true))
if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then
for i in $(pyenv-version-name || true); do
current_versions["$i"]="1"
done
else
read -r -a current_versions <<< "$(pyenv-version-name || true)"
fi
IFS="$OLDIFS" IFS="$OLDIFS"
print_origin="1"
include_system=""
fi fi
num_versions=0
exists() { exists() {
local car="$1" local car="$1"
local cdar local cdar
@ -65,67 +82,39 @@ exists() {
} }
print_version() { print_version() {
local version="${1:?}" if exists "$1" "${current_versions[@]}"; then
if [[ -n $bare ]]; then echo "${hit_prefix}${1}${print_origin+$2}"
echo "$version"
return
fi
local path="${2:?}"
if [[ -L "$path" ]]; then
version_repr="$version --> $(readlink "$path")"
else else
version_repr="$version (created from $(pyenv-virtualenv-prefix "$version" 2>/dev/null))" echo "${miss_prefix}${1}${print_origin+$2}"
fi
if [[ ${BASH_VERSINFO[0]} -gt 3 && ${current_versions["$1"]} ]] || \
{ [[ ${BASH_VERSINFO[0]} -le 3 ]] && exists "$1" "${current_versions[@]}"; }; then
echo "${hit_prefix}${version_repr} (set by $(pyenv-version-origin))"
else
echo "${miss_prefix}${version_repr}"
fi fi
num_versions=$((num_versions + 1))
} }
shopt -s dotglob shopt -s dotglob
shopt -s nullglob shopt -s nullglob
version_dir_entries=("$versions_dir"/*) for path in "$versions_dir"/*; do
venv_dir_entries=("$versions_dir"/*/envs/*) if [ -d "$path" ]; then
if [ -n "$skip_aliases" ] && [ -L "$path" ]; then
if sort --version-sort </dev/null >/dev/null 2>&1; then target="$(realpath "$path")"
# system sort supports version sorting [ "${target%/*/envs/*}" != "$versions_dir" ] || continue
OLDIFS="$IFS"
IFS='||'
read -r -a version_dir_entries <<< "$(
printf "%s||" "${version_dir_entries[@]}" |
sort --version-sort
)"
read -r -a venv_dir_entries <<< "$(
printf "%s||" "${venv_dir_entries[@]}" |
sort --version-sort
)"
IFS="$OLDIFS"
fi
for env_path in "${venv_dir_entries[@]}"; do
if [[ -d ${env_path} ]]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi
done
for env_path in "${version_dir_entries[@]}"; do
if [[ -d ${env_path} ]]; then
if [[ -L ${env_path} ]]; then
if [[ -z $skip_aliases ]]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi
# Mimics the test from pyenv-virtualenv-prefix
# XXX: refactor itto a shared module ?
elif [[ -f "${env_path}/bin/activate" ]]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi fi
virtualenv_prefix="$(pyenv-virtualenv-prefix "${path##*/}" 2>/dev/null || true)"
if [ -d "${virtualenv_prefix}" ]; then
print_version "${path##*/}" " (created from ${virtualenv_prefix})"
fi
for venv_path in "${path}/envs/"*; do
venv="${path##*/}/envs/${venv_path##*/}"
virtualenv_prefix="$(pyenv-virtualenv-prefix "${venv}" 2>/dev/null || true)"
if [ -d "${virtualenv_prefix}" ]; then
print_version "${venv}" " (created from ${virtualenv_prefix})"
fi
done
fi fi
done done
shopt -u dotglob shopt -u dotglob
shopt -u nullglob shopt -u nullglob
if [ "$num_versions" -eq 0 ] && [ -n "$include_system" ]; then
echo "Warning: no Python virtualenv detected on the system" >&2
exit 1
fi

View file

@ -9,6 +9,7 @@ setup() {
@test "display conda root" { @test "display conda root" {
setup_conda "anaconda-2.3.0" setup_conda "anaconda-2.3.0"
stub pyenv-version-name "echo anaconda-2.3.0" stub pyenv-version-name "echo anaconda-2.3.0"
stub pyenv-prefix "anaconda-2.3.0 : echo \"${PYENV_ROOT}/versions/anaconda-2.3.0\""
PYENV_VERSION="anaconda-2.3.0" run pyenv-virtualenv-prefix PYENV_VERSION="anaconda-2.3.0" run pyenv-virtualenv-prefix
@ -18,12 +19,14 @@ ${PYENV_ROOT}/versions/anaconda-2.3.0
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
teardown_conda "anaconda-2.3.0" teardown_conda "anaconda-2.3.0"
} }
@test "display conda env" { @test "display conda env" {
setup_conda "anaconda-2.3.0" "foo" setup_conda "anaconda-2.3.0" "foo"
stub pyenv-version-name "echo anaconda-2.3.0/envs/foo" stub pyenv-version-name "echo anaconda-2.3.0/envs/foo"
stub pyenv-prefix "anaconda-2.3.0/envs/foo : echo \"${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo\""
PYENV_VERSION="anaconda-2.3.0/envs/foo" run pyenv-virtualenv-prefix PYENV_VERSION="anaconda-2.3.0/envs/foo" run pyenv-virtualenv-prefix
@ -33,5 +36,6 @@ ${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
teardown_conda "anaconda-2.3.0" "foo" teardown_conda "anaconda-2.3.0" "foo"
} }

View file

@ -29,18 +29,22 @@ load test_helper
rm -f "${TMP}/script.sh" rm -f "${TMP}/script.sh"
} }
@test "sh-compatible instructions" {
run pyenv-virtualenv-init bash
assert [ "$status" -eq 1 ]
assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
run pyenv-virtualenv-init zsh
assert [ "$status" -eq 1 ]
assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
}
@test "fish instructions" { @test "fish instructions" {
run pyenv-virtualenv-init fish run pyenv-virtualenv-init fish
assert [ "$status" -eq 1 ] assert [ "$status" -eq 1 ]
assert_output_contains 'status --is-interactive; and source (pyenv virtualenv-init -|psub)' assert_output_contains 'status --is-interactive; and source (pyenv virtualenv-init -|psub)'
} }
@test "other shells instructions" {
run pyenv-virtualenv-init some_other_sh
assert [ "$status" -eq 1 ]
assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
}
@test "outputs bash-specific syntax" { @test "outputs bash-specific syntax" {
export PYENV_VIRTUALENV_ROOT="${TMP}/pyenv/plugins/pyenv-virtualenv" export PYENV_VIRTUALENV_ROOT="${TMP}/pyenv/plugins/pyenv-virtualenv"
run pyenv-virtualenv-init - bash run pyenv-virtualenv-init - bash
@ -50,6 +54,7 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
export PYENV_VIRTUALENV_INIT=1; export PYENV_VIRTUALENV_INIT=1;
_pyenv_virtualenv_hook() { _pyenv_virtualenv_hook() {
local ret=\$? local ret=\$?
# Cache: env vars checked once, path list and stat rebuilt on miss only
if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\ if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then && [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
if [ -n "\${PYENV_VERSION-}" ]; then if [ -n "\${PYENV_VERSION-}" ]; then
@ -160,6 +165,7 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
export PYENV_VIRTUALENV_INIT=1; export PYENV_VIRTUALENV_INIT=1;
_pyenv_virtualenv_hook() { _pyenv_virtualenv_hook() {
local ret=\$? local ret=\$?
# Cache: env vars checked once, path list and stat rebuilt on miss only
if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\ if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then && [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
if [ -n "\${PYENV_VERSION-}" ]; then if [ -n "\${PYENV_VERSION-}" ]; then
@ -206,13 +212,3 @@ if [[ -z \$precmd_functions[(r)_pyenv_virtualenv_hook] ]]; then
fi fi
EOS EOS
} }
@test "outputs other shells syntax" {
export PYENV_VIRTUALENV_ROOT="${TMP}/pyenv/plugins/pyenv-virtualenv"
run pyenv-virtualenv-init - some_other_sh
assert_success
assert_output <<EOS
export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
export PYENV_VIRTUALENV_INIT=1;
EOS
}

View file

@ -12,6 +12,10 @@ create_version() {
chmod +x "${PYENV_ROOT}/versions/$1/bin/python" chmod +x "${PYENV_ROOT}/versions/$1/bin/python"
} }
remove_version() {
rm -fr "${PYENV_ROOT}/versions/$1"
}
create_virtualenv() { create_virtualenv() {
create_version "$1" create_version "$1"
create_version "${2:-$1}" create_version "${2:-$1}"
@ -36,6 +40,11 @@ create_virtualenv_pypy() {
touch "${PYENV_ROOT}/versions/$1/bin/activate" touch "${PYENV_ROOT}/versions/$1/bin/activate"
} }
remove_virtualenv() {
remove_version "$1"
remove_version "${2:-$1}"
}
create_m_venv() { create_m_venv() {
create_version "$1" create_version "$1"
create_version "${2:-$1}" create_version "${2:-$1}"
@ -43,6 +52,10 @@ create_m_venv() {
touch "${PYENV_ROOT}/versions/$1/bin/activate" touch "${PYENV_ROOT}/versions/$1/bin/activate"
} }
remove_m_venv() {
remove_version "${2:-$1}"
}
create_conda() { create_conda() {
create_version "$1" create_version "$1"
create_version "${2:-$1}" create_version "${2:-$1}"
@ -53,8 +66,13 @@ create_conda() {
touch "${PYENV_ROOT}/versions/${2:-$1}/bin/activate" touch "${PYENV_ROOT}/versions/${2:-$1}/bin/activate"
} }
remove_conda() {
remove_version "${2:-$1}"
}
@test "display prefix of virtualenv created by virtualenv" { @test "display prefix of virtualenv created by virtualenv" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_virtualenv "foo" "2.7.11" create_virtualenv "foo" "2.7.11"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -65,10 +83,13 @@ ${PYENV_ROOT}/versions/2.7.11
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "2.7.11"
} }
@test "display prefix of virtualenv created by virtualenv (pypy)" { @test "display prefix of virtualenv created by virtualenv (pypy)" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_virtualenv_pypy "foo" "pypy-4.0.1" create_virtualenv_pypy "foo" "pypy-4.0.1"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -79,10 +100,13 @@ ${PYENV_ROOT}/versions/pypy-4.0.1
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "pypy-4.0.1"
} }
@test "display prefix of virtualenv created by virtualenv (jython)" { @test "display prefix of virtualenv created by virtualenv (jython)" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_virtualenv_jython "foo" "jython-2.7.0" create_virtualenv_jython "foo" "jython-2.7.0"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -93,10 +117,14 @@ ${PYENV_ROOT}/versions/jython-2.7.0
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "jython-2.7.0"
} }
@test "display prefixes of virtualenv created by virtualenv" { @test "display prefixes of virtualenv created by virtualenv" {
stub pyenv-version-name "echo foo:bar" stub pyenv-version-name "echo foo:bar"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\"" \
"bar : echo \"${PYENV_ROOT}/versions/bar\""
create_virtualenv "foo" "2.7.11" create_virtualenv "foo" "2.7.11"
create_virtualenv "bar" "3.5.1" create_virtualenv "bar" "3.5.1"
@ -108,10 +136,14 @@ ${PYENV_ROOT}/versions/2.7.11:${PYENV_ROOT}/versions/3.5.1
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "2.7.11"
remove_virtualenv "bar" "3.5.1"
} }
@test "display prefix of virtualenv created by venv" { @test "display prefix of virtualenv created by venv" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_m_venv "foo" "3.3.6" create_m_venv "foo" "3.3.6"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -122,10 +154,14 @@ ${PYENV_ROOT}/versions/3.3.6
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_m_venv "foo" "3.3.6"
} }
@test "display prefixes of virtualenv created by venv" { @test "display prefixes of virtualenv created by venv" {
stub pyenv-version-name "echo foo:bar" stub pyenv-version-name "echo foo:bar"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\"" \
"bar : echo \"${PYENV_ROOT}/versions/bar\""
create_m_venv "foo" "3.3.6" create_m_venv "foo" "3.3.6"
create_m_venv "bar" "3.4.4" create_m_venv "bar" "3.4.4"
@ -137,10 +173,14 @@ ${PYENV_ROOT}/versions/3.3.6:${PYENV_ROOT}/versions/3.4.4
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_m_venv "foo" "3.3.6"
remove_m_venv "bar" "3.4.4"
} }
@test "display prefix of virtualenv created by conda" { @test "display prefix of virtualenv created by conda" {
stub pyenv-version-name "echo miniconda3-3.16.0/envs/foo" stub pyenv-version-name "echo miniconda3-3.16.0/envs/foo"
stub pyenv-prefix "miniconda3-3.16.0/envs/foo : echo \"${PYENV_ROOT}/versions/miniconda3-3.16.0/envs/foo\""
create_conda "miniconda3-3.16.0/envs/foo" "miniconda3-3.16.0" create_conda "miniconda3-3.16.0/envs/foo" "miniconda3-3.16.0"
PYENV_VERSION="miniconda3-3.16.0/envs/foo" run pyenv-virtualenv-prefix PYENV_VERSION="miniconda3-3.16.0/envs/foo" run pyenv-virtualenv-prefix
@ -151,6 +191,8 @@ ${PYENV_ROOT}/versions/miniconda3-3.16.0/envs/foo
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_conda "miniconda3-3.16.0/envs/foo" "miniconda3-3.16.0"
} }
@test "should fail if the version is the system" { @test "should fail if the version is the system" {
@ -168,6 +210,7 @@ OUT
@test "should fail if the version is not a virtualenv" { @test "should fail if the version is not a virtualenv" {
stub pyenv-version-name "echo 3.4.4" stub pyenv-version-name "echo 3.4.4"
stub pyenv-prefix "3.4.4 : echo \"${PYENV_ROOT}/versions/3.4.4\""
create_version "3.4.4" create_version "3.4.4"
PYENV_VERSION="3.4.4" run pyenv-virtualenv-prefix PYENV_VERSION="3.4.4" run pyenv-virtualenv-prefix
@ -178,10 +221,14 @@ pyenv-virtualenv: version \`3.4.4' is not a virtualenv
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_version "3.4.4"
} }
@test "should fail if one of the versions is not a virtualenv" { @test "should fail if one of the versions is not a virtualenv" {
stub pyenv-version-name "echo venv33:3.4.4" stub pyenv-version-name "echo venv33:3.4.4"
stub pyenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/venv33\"" \
"3.4.4 : echo \"${PYENV_ROOT}/versions/3.4.4\""
create_virtualenv "venv33" "3.3.6" create_virtualenv "venv33" "3.3.6"
create_version "3.4.4" create_version "3.4.4"
@ -190,25 +237,10 @@ OUT
assert_failure assert_failure
assert_output <<OUT assert_output <<OUT
pyenv-virtualenv: version \`3.4.4' is not a virtualenv pyenv-virtualenv: version \`3.4.4' is not a virtualenv
OUT
unstub pyenv-version-name
}
@test "resolves a version that is not an exact match" {
stub pyenv-version-name "echo 3"
create_version "3.4.4"
stub pyenv-prefix "3 : echo \"$PYENV_ROOT/versions/3.4.4\""
run pyenv-virtualenv-prefix
assert_failure
assert_output <<OUT
pyenv-virtualenv: version \`3' is not a virtualenv
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix unstub pyenv-prefix
remove_virtualenv "venv33" "3.3.6"
remove_version "3.4.4"
} }

View file

@ -2,79 +2,27 @@
load test_helper load test_helper
create_m_system_venv() {
# Create a mock virtual environment in the same way a venv created from
# the system Python version looks.
#
# The venv is in ${PYENV_ROOT}/versions, is not a symlink, and
# home is /usr/bin in the pyenv.cfg.
create_executable "$2" "python"
create_executable "$2" "activate"
local version="$1"
local venv="$2"
local venv_dir="${PYENV_ROOT}/versions/${venv}"
echo "home = /usr/bin" > "${venv_dir}/pyvenv.cfg"
}
create_m_venv() {
# Create a mock virtual environment from an installed (not system) Python version.
#
# The venv name is a symlink inside ${PYENV_ROOT}/versions that points to
# the real venv directory inside the Python version used to created and
# home points to the bin directory inside the venv dir.
setup_m_venv "$1/envs/$2"
local version="$1"
local venv="$2"
local venv_dir="${PYENV_ROOT}/versions/${version}/envs/${venv}"
echo "home = ${PYENV_ROOT}/versions/${version}/bin" > "${venv_dir}/pyvenv.cfg"
ln -sf "${venv_dir}" "${PYENV_ROOT}/versions/${venv}"
}
setup() { setup() {
export PYENV_ROOT="${TMP}/pyenv" export PYENV_ROOT="${TMP}/pyenv"
mkdir -p "${PYENV_ROOT}/versions/2.7.6"
mkdir -p "${PYENV_ROOT}/versions/3.3.3"
mkdir -p "${PYENV_ROOT}/versions/venv27"
mkdir -p "${PYENV_ROOT}/versions/venv33"
} }
@test "system venv" { @test "list virtual environments only" {
stub pyenv-version-name ": echo venv314"
stub pyenv-version-origin ": echo PYENV_VERSION"
create_m_venv "3.14.3" "venv314"
create_m_system_venv "3.9.11" "system_venv"
run pyenv-virtualenvs
assert_success
assert_output <<OUT
3.14.3/envs/venv314 (created from ${PYENV_ROOT}/versions/3.14.3)
system_venv (created from /usr)
* venv314 --> ${PYENV_ROOT}/versions/3.14.3/envs/venv314 (set by PYENV_VERSION)
OUT
unstub pyenv-version-name
unstub pyenv-version-origin
}
@test "list virtual environments" {
stub pyenv-version-name ": echo system" stub pyenv-version-name ": echo system"
stub pyenv-virtualenv-prefix "2.7.6/envs/venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\"" stub pyenv-virtualenv-prefix "2.7.6 : false"
stub pyenv-virtualenv-prefix "3.3.3/envs/venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\"" stub pyenv-virtualenv-prefix "3.3.3 : false"
stub pyenv-virtualenv-prefix "venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\""
create_m_venv "2.7.6" "venv27" stub pyenv-virtualenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\""
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs run pyenv-virtualenvs
assert_success assert_success
assert_output <<OUT assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6) venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3) venv33 (created from ${PYENV_ROOT}/versions/3.3.3)
venv27 --> ${PYENV_ROOT}/versions/2.7.6/envs/venv27
venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
@ -82,101 +30,37 @@ OUT
} }
@test "list virtual environments with hit prefix" { @test "list virtual environments with hit prefix" {
stub pyenv-version-name ": echo 3.3.3/envs/venv33" stub pyenv-version-name ": echo venv33"
stub pyenv-version-origin ": echo PYENV_VERSION" stub pyenv-virtualenv-prefix "2.7.6 : false"
stub pyenv-virtualenv-prefix "3.3.3 : false"
create_m_venv "2.7.6" "venv27" stub pyenv-virtualenv-prefix "venv27 : echo \"/usr\""
create_m_venv "3.3.3" "venv33" stub pyenv-virtualenv-prefix "venv33 : echo \"/usr\""
run pyenv-virtualenvs run pyenv-virtualenvs
assert_success assert_success
assert_output <<OUT assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6) venv27 (created from /usr)
* 3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3) (set by PYENV_VERSION) * venv33 (created from /usr)
venv27 --> ${PYENV_ROOT}/versions/2.7.6/envs/venv27
venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-version-origin unstub pyenv-virtualenv-prefix
} }
@test "list bare virtual environments" { @test "list virtual environments with --bare" {
create_m_venv "2.7.6" "venv27" stub pyenv-virtualenv-prefix "2.7.6 : false"
create_m_venv "3.3.3" "venv33" stub pyenv-virtualenv-prefix "3.3.3 : false"
stub pyenv-virtualenv-prefix "venv27 : echo \"/usr\""
stub pyenv-virtualenv-prefix "venv33 : echo \"/usr\""
run pyenv-virtualenvs --bare run pyenv-virtualenvs --bare
assert_success assert_success
assert_output <<OUT assert_output <<OUT
2.7.6/envs/venv27
3.3.3/envs/venv33
venv27 venv27
venv33 venv33
OUT OUT
}
unstub pyenv-virtualenv-prefix
@test "list bare virtual environments without aliases" {
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs --bare --skip-aliases
assert_success
assert_output <<OUT
2.7.6/envs/venv27
3.3.3/envs/venv33
OUT
}
@test "list virtual environments without aliases" {
stub pyenv-version-name ": echo system"
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs --skip-aliases
assert_success
assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3)
OUT
unstub pyenv-version-name
}
@test "hit prefix matches alias version name" {
stub pyenv-version-name ": echo venv27"
stub pyenv-version-origin ": echo PYENV_VERSION"
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs
assert_success
assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3)
* venv27 --> ${PYENV_ROOT}/versions/2.7.6/envs/venv27 (set by PYENV_VERSION)
venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33
OUT
unstub pyenv-version-name
unstub pyenv-version-origin
}
@test "completions output" {
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs --complete
assert_success
assert_output <<OUT
--bare
--skip-aliases
OUT
} }