pyenv.pyenv-virtualenv/bin/pyenv-virtualenvs
Sam Doran 13b0d850d8
Add skip-aliases to complete output
This was removed by accident.
2026-04-23 17:29:17 -04:00

193 lines
4.3 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Summary: List all Python virtualenvs found in `$PYENV_ROOT/versions/*'.
# Usage: pyenv virtualenvs [--bare] [--skip-aliases] [--only-aliases]
#
# List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'.
set -e
[ -n "$PYENV_DEBUG" ] && set -x
if [ -L "${BASH_SOURCE[0]}" ]; 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[0]}")
else
script_path="${BASH_SOURCE[0]}"
fi
. "${script_path%/*}"/../libexec/pyenv-virtualenv-realpath
if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv"
fi
unset bare
unset skip_aliases
# Provide pyenv completions
for arg; do
case "$arg" in
--complete )
echo --bare
echo --skip-aliases
echo --only-aliases
exit ;;
--bare ) bare=1 ;;
--skip-aliases ) skip_aliases=1 ;;
--only-aliases ) only_aliases=1 ;;
* )
pyenv-help --usage virtualenvs >&2
exit 1
;;
esac
done
versions_dir="${PYENV_ROOT}/versions"
if ! enable -f "${BASH_SOURCE%/*}"/pyenv-realpath.dylib realpath 2>/dev/null; then
if [ -n "$PYENV_NATIVE_EXT" ]; then
echo "pyenv: failed to load \`realpath' builtin" >&2
exit 1
fi
READLINK=$(type -P readlink)
if [ -z "$READLINK" ]; then
echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2
exit 1
fi
resolve_link() {
$READLINK "$1"
}
realpath() {
local path="$1"
local name
# Use a subshell to avoid changing the current path
(
while [ -n "$path" ]; do
name="${path##*/}"
[ "$name" = "$path" ] || cd "${path%/*}"
path="$(resolve_link "$name" || true)"
done
echo "${PWD}/$name"
)
}
fi
if ((BASH_VERSINFO[0] > 3)); then
declare -A current_versions
else
current_versions=()
fi
if [ -n "$bare" ]; then
include_system=""
else
hit_prefix="* "
miss_prefix=" "
OLDIFS="$IFS"
IFS=:
if ((BASH_VERSINFO[0] > 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"
include_system="1"
fi
num_versions=0
exists() {
local car="$1"
local cdar
shift
for cdar in "$@"; do
if [ "${car}" == "${cdar}" ]; then
return 0
fi
done
return 1
}
print_version() {
local version="${1:?}"
if [[ -n $bare ]]; then
echo "$version"
return
fi
local path="${2:?}"
if [[ -L "$path" ]]; then
# Only resolve the link itself for printing, do not resolve further.
# Doing otherwise would misinform the user of what the link contains.
version_repr="$version --> $(readlink "$path")"
else
version_repr="$version"
fi
if [[ ${BASH_VERSINFO[0]} -ge 4 && ${current_versions["$1"]} ]]; then
echo "${hit_prefix}${version_repr} (set by $(pyenv-version-origin))"
elif (( BASH_VERSINFO[0] <= 3 )) && exists "$1" "${current_versions[@]}"; then
echo "${hit_prefix}${version_repr} (set by $(pyenv-version-origin))"
else
echo "${miss_prefix}${version_repr}"
fi
num_versions=$((num_versions + 1))
}
shopt -s dotglob
shopt -s nullglob
version_dir_entries=("$versions_dir"/*)
venv_dir_entries=("$versions_dir"/*/envs/*)
if sort --version-sort </dev/null >/dev/null 2>&1; then
# system sort supports version sorting
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
if [ -z "$only_aliases" ]; then
for env_path in "${venv_dir_entries[@]}"; do
if [ -d "${env_path}" ]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi
done
fi
if [ -z "$skip_aliases" ]; then
for env_path in "${version_dir_entries[@]}"; do
if [ -d "${env_path}" ] && [ -L "${env_path}" ]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi
done
fi
shopt -u dotglob
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