From 338a2af217e38fbc4319edf4e2a9e4a2403edd40 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 13 Feb 2025 11:50:18 -0500 Subject: [PATCH 01/13] Improve performance of pyenv-virtualenvs Use the code from pyenv-versions for efficiency and consistent output. The main performance problem was in the call to pyenv-virtualenv-prefix, which called pyenv-prefix, which then enumerated every virtual environment. This was done inside a loop, compounding the problem. Simply the virtual environment listing so that it does not have to call pyenv-virtualenv-prefix anymore. --- bin/pyenv-virtualenvs | 127 ++++++++++++++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 29 deletions(-) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index fec12868..eae9b672 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -47,24 +47,60 @@ done versions_dir="${PYENV_ROOT}/versions" -if [ -d "$versions_dir" ]; then - versions_dir="$(realpath "$versions_dir")" +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 [ -n "$bare" ]; then - hit_prefix="" - miss_prefix="" +if ((BASH_VERSINFO[0] > 3)); then + declare -A current_versions +else current_versions=() - unset print_origin +fi +if [ -n "$bare" ]; then include_system="" else hit_prefix="* " miss_prefix=" " OLDIFS="$IFS" - IFS=: current_versions=($(pyenv-version-name || true)) + 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" - print_origin="1" - include_system="" + include_system="1" fi num_versions=0 @@ -82,35 +118,68 @@ exists() { } print_version() { - if exists "$1" "${current_versions[@]}"; then - echo "${hit_prefix}${1}${print_origin+$2}" + 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}${1}${print_origin+$2}" + echo "${miss_prefix}${version_repr}" fi num_versions=$((num_versions + 1)) } shopt -s dotglob shopt -s nullglob -for path in "$versions_dir"/*; do - if [ -d "$path" ]; then - if [ -n "$skip_aliases" ] && [ -L "$path" ]; then - target="$(realpath "$path")" - [ "${target%/*/envs/*}" != "$versions_dir" ] || continue +version_dir_entries=("$versions_dir"/*) +venv_dir_entries=("$versions_dir"/*/envs/*) + +if sort --version-sort /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 - virtualenv_prefix="$(pyenv-virtualenv-prefix "${path##*/}" 2>/dev/null || true)" - if [ -d "${virtualenv_prefix}" ]; then - print_version "${path##*/}" " (created from ${virtualenv_prefix})" + 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 - 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 -done + done +fi + shopt -u dotglob shopt -u nullglob From a0931435fe74ffa569343ab0e97b4c62e87e6054 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 13 Feb 2025 11:51:24 -0500 Subject: [PATCH 02/13] Shellcheck fixes, mostly quoting to avoid word splitting --- bin/pyenv-virtualenvs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index eae9b672..a43ece2c 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -7,7 +7,7 @@ set -e [ -n "$PYENV_DEBUG" ] && set -x -if [ -L "${BASH_SOURCE}" ]; then +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 @@ -16,12 +16,12 @@ if [ -L "${BASH_SOURCE}" ]; then resolve_link() { $READLINK -f "$1" } - script_path=$(resolve_link ${BASH_SOURCE}) + script_path=$(resolve_link "${BASH_SOURCE[0]}") else - script_path=${BASH_SOURCE} + script_path="${BASH_SOURCE[0]}" fi -. ${script_path%/*}/../libexec/pyenv-virtualenv-realpath +. "${script_path%/*}"/../libexec/pyenv-virtualenv-realpath if [ -z "$PYENV_ROOT" ]; then PYENV_ROOT="${HOME}/.pyenv" @@ -187,3 +187,4 @@ if [ "$num_versions" -eq 0 ] && [ -n "$include_system" ]; then echo "Warning: no Python virtualenv detected on the system" >&2 exit 1 fi + From ce388ef55f725017b4dff98401f17b75276ae9db Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 13 Feb 2025 11:57:26 -0500 Subject: [PATCH 03/13] Add --only-aliases argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful for listing the “frinedly” virtualenv names instead of the short path which includes the Python version. --- bin/pyenv-virtualenvs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index a43ece2c..d4b7ba00 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # Summary: List all Python virtualenvs found in `$PYENV_ROOT/versions/*'. -# Usage: pyenv virtualenvs [--bare] [--skip-aliases] +# Usage: pyenv virtualenvs [--bare] [--skip-aliases] [--only-aliases] # # List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'. @@ -34,10 +34,11 @@ 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 From 29b5e3e4eae54939707c262458666fe28267a172 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 13 Feb 2025 11:59:59 -0500 Subject: [PATCH 04/13] Only show Python versions for completion when creating new virtual environments Having the current virtual environments listed as options in the competion is noisy since only bare Python versions, such as 3.11.1, make sense as suggested completions for `pyenv virtualenv [version]`. --- bin/pyenv-virtualenv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pyenv-virtualenv b/bin/pyenv-virtualenv index f1cbe3dc..69c61d17 100755 --- a/bin/pyenv-virtualenv +++ b/bin/pyenv-virtualenv @@ -24,7 +24,7 @@ fi # Provide pyenv completions if [ "$1" = "--complete" ]; then - exec pyenv-versions --bare + exec pyenv-versions --bare --skip-envs --skip-aliases fi unset PIP_REQUIRE_VENV From 725ba24b5f469d19cab45aefca314be035a7ce9f Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 13 Feb 2025 12:03:24 -0500 Subject: [PATCH 05/13] Only show aliases as completions for `pyenv activate` This makes the suggested completetions cleaner. --- bin/pyenv-activate | 2 +- bin/pyenv-sh-activate | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/pyenv-activate b/bin/pyenv-activate index 0f5d324b..c46eb6dd 100755 --- a/bin/pyenv-activate +++ b/bin/pyenv-activate @@ -17,7 +17,7 @@ set -e # Provide pyenv completions if [ "$1" = "--complete" ]; then echo --unset - exec pyenv-virtualenvs --bare + exec pyenv-virtualenvs --bare --only-aliases fi { printf "\x1B[31;1m" diff --git a/bin/pyenv-sh-activate b/bin/pyenv-sh-activate index 5c53b500..868bc5d7 100755 --- a/bin/pyenv-sh-activate +++ b/bin/pyenv-sh-activate @@ -51,7 +51,7 @@ while [ $# -gt 0 ]; do "--complete" ) # Provide pyenv completions echo --unset - exec pyenv-virtualenvs --bare + exec pyenv-virtualenvs --bare --only-aliases ;; "-f" | "--force" ) FORCE=1 From 4b4fc3f2b9b8c8c3e71752f9cfb433d87f2728c4 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 13 Feb 2025 12:10:39 -0500 Subject: [PATCH 06/13] Update tests --- test/virtualenvs.bats | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/test/virtualenvs.bats b/test/virtualenvs.bats index 9079efb1..51bc44d4 100644 --- a/test/virtualenvs.bats +++ b/test/virtualenvs.bats @@ -4,10 +4,15 @@ load test_helper setup() { 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" + mkdir -p "${PYENV_ROOT}/versions/2.7.6/envs/venv27" + mkdir -p "${PYENV_ROOT}/versions/3.3.3/envs/venv33" + ln -s "venv27" "${PYENV_ROOT}/versions/venv27" + ln -s "venv33" "${PYENV_ROOT}/versions/venv33" +} + +create_alias() { + mkdir -p "${PYENV_ROOT}/versions" + ln -s "$2" "${PYENV_ROOT}/versions/$1" } @test "list virtual environments only" { @@ -21,40 +26,40 @@ setup() { assert_success assert_output < Date: Tue, 11 Mar 2025 22:57:10 -0400 Subject: [PATCH 07/13] Add skip-aliases to complete output This was removed by accident. --- bin/pyenv-virtualenvs | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index d4b7ba00..7081d325 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -34,6 +34,7 @@ for arg; do case "$arg" in --complete ) echo --bare + echo --skip-aliases echo --only-aliases exit ;; --bare ) bare=1 ;; From 54391b67663f099f9a34101ca13ea40d43aba0f7 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Tue, 11 Mar 2025 23:24:28 -0400 Subject: [PATCH 08/13] Use conditional expressions For consistency, use conditional expressions instead of arithmetic evaluation when comparing bash versions. --- bin/pyenv-virtualenvs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index 7081d325..46718107 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -82,7 +82,7 @@ if ! enable -f "${BASH_SOURCE%/*}"/pyenv-realpath.dylib realpath 2>/dev/null; th } fi -if ((BASH_VERSINFO[0] > 3)); then +if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then declare -A current_versions else current_versions=() @@ -94,7 +94,7 @@ else miss_prefix=" " OLDIFS="$IFS" IFS=: - if ((BASH_VERSINFO[0] > 3)); then + if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then for i in $(pyenv-version-name || true); do current_versions["$i"]="1" done @@ -135,7 +135,7 @@ print_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 + elif [[ ${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}" From e539efa1c9d564c267e877b602bdaade51610a90 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Tue, 11 Mar 2025 23:55:12 -0400 Subject: [PATCH 09/13] Remove unused code The new implementation is not using realpath. --- bin/pyenv-virtualenvs | 48 ------------------------------------------- 1 file changed, 48 deletions(-) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index 46718107..6898f730 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -7,21 +7,6 @@ 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" @@ -49,39 +34,6 @@ 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]} -gt 3 ]]; then declare -A current_versions else From 26ffe02a8b1a15cf0328052b9e4dc3cff1782270 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Tue, 11 Mar 2025 23:58:38 -0400 Subject: [PATCH 10/13] Use the newer [[ command https://mywiki.wooledge.org/BashFAQ/031 --- bin/pyenv-virtualenvs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index 6898f730..8da8986e 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -6,9 +6,9 @@ # List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'. set -e -[ -n "$PYENV_DEBUG" ] && set -x +[[ -n $PYENV_DEBUG ]] && set -x -if [ -z "$PYENV_ROOT" ]; then +if [[ -z $PYENV_ROOT ]]; then PYENV_ROOT="${HOME}/.pyenv" fi @@ -39,7 +39,7 @@ if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then else current_versions=() fi -if [ -n "$bare" ]; then +if [[ -n $bare ]]; then include_system="" else hit_prefix="* " @@ -118,17 +118,17 @@ if sort --version-sort /dev/null 2>&1; then IFS="$OLDIFS" fi -if [ -z "$only_aliases" ]; then +if [[ -z $only_aliases ]]; then for env_path in "${venv_dir_entries[@]}"; do - if [ -d "${env_path}" ]; then + if [[ -d ${env_path} ]]; then print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}" fi done fi -if [ -z "$skip_aliases" ]; then +if [[ -z "$skip_aliases" ]]; then for env_path in "${version_dir_entries[@]}"; do - if [ -d "${env_path}" ] && [ -L "${env_path}" ]; then + if [[ -d ${env_path} ]] && [[ -L ${env_path} ]]; then print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}" fi done @@ -137,7 +137,7 @@ fi shopt -u dotglob shopt -u nullglob -if [ "$num_versions" -eq 0 ] && [ -n "$include_system" ]; then +if [[ $num_versions -eq 0 ]] && [[ -n $include_system ]]; then echo "Warning: no Python virtualenv detected on the system" >&2 exit 1 fi From d82cd8f63e9e481c070d97b2ced78dd2d30d7f99 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Wed, 12 Mar 2025 00:43:18 -0400 Subject: [PATCH 11/13] Remove --only-aliases option for later discussion --- bin/pyenv-sh-activate | 2 +- bin/pyenv-virtualenvs | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/bin/pyenv-sh-activate b/bin/pyenv-sh-activate index 868bc5d7..5c53b500 100755 --- a/bin/pyenv-sh-activate +++ b/bin/pyenv-sh-activate @@ -51,7 +51,7 @@ while [ $# -gt 0 ]; do "--complete" ) # Provide pyenv completions echo --unset - exec pyenv-virtualenvs --bare --only-aliases + exec pyenv-virtualenvs --bare ;; "-f" | "--force" ) FORCE=1 diff --git a/bin/pyenv-virtualenvs b/bin/pyenv-virtualenvs index 8da8986e..71440301 100755 --- a/bin/pyenv-virtualenvs +++ b/bin/pyenv-virtualenvs @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # Summary: List all Python virtualenvs found in `$PYENV_ROOT/versions/*'. -# Usage: pyenv virtualenvs [--bare] [--skip-aliases] [--only-aliases] +# Usage: pyenv virtualenvs [--bare] [--skip-aliases] # # List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'. @@ -20,11 +20,9 @@ for arg; do --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 @@ -118,13 +116,11 @@ if sort --version-sort /dev/null 2>&1; then 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 +for env_path in "${venv_dir_entries[@]}"; do + if [[ -d ${env_path} ]]; then + print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}" + fi +done if [[ -z "$skip_aliases" ]]; then for env_path in "${version_dir_entries[@]}"; do From b93aa471ff0287440ac85f3c5a38fd41d6a53eeb Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Wed, 15 Apr 2026 11:04:15 -0400 Subject: [PATCH 12/13] Correct test setup so aliases are properly symlinked --- test/virtualenvs.bats | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/virtualenvs.bats b/test/virtualenvs.bats index 51bc44d4..e4dd10a2 100644 --- a/test/virtualenvs.bats +++ b/test/virtualenvs.bats @@ -6,13 +6,8 @@ setup() { export PYENV_ROOT="${TMP}/pyenv" mkdir -p "${PYENV_ROOT}/versions/2.7.6/envs/venv27" mkdir -p "${PYENV_ROOT}/versions/3.3.3/envs/venv33" - ln -s "venv27" "${PYENV_ROOT}/versions/venv27" - ln -s "venv33" "${PYENV_ROOT}/versions/venv33" -} - -create_alias() { - mkdir -p "${PYENV_ROOT}/versions" - ln -s "$2" "${PYENV_ROOT}/versions/$1" + ln -s "${PYENV_ROOT}/versions/2.7.6/envs/venv27" "${PYENV_ROOT}/versions/venv27" + ln -s "${PYENV_ROOT}/versions/3.3.3/envs/venv33" "${PYENV_ROOT}/versions/venv33" } @test "list virtual environments only" { From cbaa29a4c21e3318027f12a0b4bdd80a0e93b8d3 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Wed, 15 Apr 2026 12:25:18 -0400 Subject: [PATCH 13/13] Update tests and add more test cases Update the existing tests based on new behavior/output format. Add additional tests to cover scenarios that were not previously tested. --- test/virtualenvs.bats | 112 +++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 23 deletions(-) diff --git a/test/virtualenvs.bats b/test/virtualenvs.bats index e4dd10a2..8863c94a 100644 --- a/test/virtualenvs.bats +++ b/test/virtualenvs.bats @@ -10,12 +10,8 @@ setup() { ln -s "${PYENV_ROOT}/versions/3.3.3/envs/venv33" "${PYENV_ROOT}/versions/venv33" } -@test "list virtual environments only" { +@test "list virtual environments" { stub pyenv-version-name ": echo system" - stub pyenv-virtualenv-prefix "2.7.6 : false" - stub pyenv-virtualenv-prefix "3.3.3 : false" - stub pyenv-virtualenv-prefix "venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\"" - stub pyenv-virtualenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\"" run pyenv-virtualenvs @@ -23,44 +19,114 @@ setup() { assert_output < ${PYENV_ROOT}/versions/2.7.6/envs/venv27 + venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33 OUT - # unstub pyenv-version-name - # unstub pyenv-virtualenv-prefix + unstub pyenv-version-name } @test "list virtual environments with hit prefix" { - stub pyenv-version-name ": echo venv33" - stub pyenv-virtualenv-prefix "2.7.6 : false" - stub pyenv-virtualenv-prefix "3.3.3 : false" - stub pyenv-virtualenv-prefix "venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\"" - stub pyenv-virtualenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\"" + stub pyenv-version-name ": echo 3.3.3/envs/venv33" + stub pyenv-version-origin ": echo PYENV_VERSION" run pyenv-virtualenvs assert_success assert_output < ${PYENV_ROOT}/versions/2.7.6/envs/venv27 + venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33 OUT - # unstub pyenv-version-name - # unstub pyenv-virtualenv-prefix + unstub pyenv-version-name + unstub pyenv-version-origin } -@test "list virtual environments with --bare" { - stub pyenv-virtualenv-prefix "2.7.6 : false" - stub pyenv-virtualenv-prefix "3.3.3 : false" - stub pyenv-virtualenv-prefix "venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\"" - stub pyenv-virtualenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\"" - - run pyenv-virtualenvs --bare --only-aliases +@test "list bare virtual environments" { + run pyenv-virtualenvs --bare assert_success assert_output < ${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 "no virtualenvs warning" { + rm -rf "${PYENV_ROOT}/versions" + mkdir -p "${PYENV_ROOT}/versions" + stub pyenv-version-name ": echo system" + + run pyenv-virtualenvs + + assert_failure + assert_output "Warning: no Python virtualenv detected on the system" - unstub pyenv-virtualenv-prefix + unstub pyenv-version-name +} + +@test "no warning with --bare and no virtualenvs" { + rm -rf "${PYENV_ROOT}/versions" + mkdir -p "${PYENV_ROOT}/versions" + + run pyenv-virtualenvs --bare + + assert_success + assert_output "" +} + +@test "completions output" { + run pyenv-virtualenvs --complete + + assert_success + assert_output <