You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.3 KiB

  1. #!/usr/bin/env bash
  2. # Summary: List all Python versions available to pyenv
  3. # Usage: pyenv versions [--bare] [--skip-aliases]
  4. #
  5. # Lists all Python versions found in `$PYENV_ROOT/versions/*'.
  6. set -e
  7. [ -n "$PYENV_DEBUG" ] && set -x
  8. unset bare
  9. unset skip_aliases
  10. # Provide pyenv completions
  11. for arg; do
  12. case "$arg" in
  13. --complete )
  14. echo --bare
  15. echo --skip-aliases
  16. exit ;;
  17. --bare ) bare=1 ;;
  18. --skip-aliases ) skip_aliases=1 ;;
  19. * )
  20. pyenv-help --usage versions >&2
  21. exit 1
  22. ;;
  23. esac
  24. done
  25. versions_dir="${PYENV_ROOT}/versions"
  26. if ! enable -f "${BASH_SOURCE%/*}"/pyenv-realpath.dylib realpath 2>/dev/null; then
  27. if [ -n "$PYENV_NATIVE_EXT" ]; then
  28. echo "pyenv: failed to load \`realpath' builtin" >&2
  29. exit 1
  30. fi
  31. READLINK=$(type -P greadlink readlink | head -1)
  32. if [ -z "$READLINK" ]; then
  33. echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2
  34. exit 1
  35. fi
  36. resolve_link() {
  37. $READLINK "$1"
  38. }
  39. realpath() {
  40. local path="$1"
  41. local name
  42. # Use a subshell to avoid changing the current path
  43. (
  44. while [ -n "$path" ]; do
  45. name="${path##*/}"
  46. [ "$name" = "$path" ] || cd "${path%/*}"
  47. path="$(resolve_link "$name" || true)"
  48. done
  49. echo "${PWD}/$name"
  50. )
  51. }
  52. fi
  53. if [ -d "$versions_dir" ]; then
  54. versions_dir="$(realpath "$versions_dir")"
  55. fi
  56. if ((${BASH_VERSINFO[0]} > 3)); then
  57. declare -A current_versions
  58. else
  59. current_versions=()
  60. fi
  61. if [ -n "$bare" ]; then
  62. hit_prefix=""
  63. miss_prefix=""
  64. include_system=""
  65. else
  66. hit_prefix="* "
  67. miss_prefix=" "
  68. OLDIFS="$IFS"
  69. IFS=:
  70. if ((${BASH_VERSINFO[0]} > 3)); then
  71. for i in $(pyenv-version-name || true); do
  72. current_versions["$i"]="1"
  73. done
  74. else
  75. current_versions=($(pyenv-version-name || true))
  76. fi
  77. IFS="$OLDIFS"
  78. include_system="1"
  79. fi
  80. num_versions=0
  81. exists() {
  82. local car="$1"
  83. local cdar
  84. shift
  85. for cdar in "$@"; do
  86. if [ "${car}" == "${cdar}" ]; then
  87. return 0
  88. fi
  89. done
  90. return 1
  91. }
  92. print_version() {
  93. if [[ ${BASH_VERSINFO[0]} -ge 4 && ${current_versions["$1"]} ]]; then
  94. echo "${hit_prefix}$1 (set by $(pyenv-version-origin))"
  95. elif (( ${BASH_VERSINFO[0]} <= 3 )) && exists "$1" "${current_versions[@]}"; then
  96. echo "${hit_prefix}$1 (set by $(pyenv-version-origin))"
  97. else
  98. echo "${miss_prefix}$1"
  99. fi
  100. num_versions=$((num_versions + 1))
  101. }
  102. # Include "system" in the non-bare output, if it exists
  103. if [ -n "$include_system" ] && \
  104. (PYENV_VERSION=system pyenv-which python >/dev/null 2>&1 || \
  105. PYENV_VERSION=system pyenv-which python3 >/dev/null 2>&1 || \
  106. PYENV_VERSION=system pyenv-which python2 >/dev/null 2>&1) ; then
  107. print_version system
  108. fi
  109. shopt -s dotglob nullglob
  110. for path in "$versions_dir"/*; do
  111. if [ -d "$path" ]; then
  112. if [ -n "$skip_aliases" ] && [ -L "$path" ]; then
  113. target="$(realpath "$path")"
  114. [ "${target%/*}" != "$versions_dir" ] || continue
  115. [ "${target%/*/envs/*}" != "$versions_dir" ] || continue
  116. fi
  117. print_version "${path##*/}"
  118. # virtual environments created by anaconda/miniconda
  119. for env_path in "${path}/envs/"*; do
  120. if [ -d "${env_path}" ]; then
  121. print_version "${env_path#${PYENV_ROOT}/versions/}"
  122. fi
  123. done
  124. fi
  125. done
  126. shopt -u dotglob nullglob
  127. if [ "$num_versions" -eq 0 ] && [ -n "$include_system" ]; then
  128. echo "Warning: no Python detected on the system" >&2
  129. exit 1
  130. fi