From 1edff311d535db844e7c9ce145b0f22b06346604 Mon Sep 17 00:00:00 2001 From: "Yamashita, Yuu" Date: Thu, 26 Nov 2015 10:30:13 +0000 Subject: [PATCH 1/3] exits as error if the virtual environment doesn't have `python` executable (#104) conda's environment might not have `python` executable. If the prefix doesn't contain `python` in it, `pyenv-which` might be ran into infinite loop if some of `which` hooks invoke `pyenv-virtualenv-prefix`. --- bin/pyenv-virtualenv-prefix | 13 +++++++++---- test/prefix.bats | 22 ++++++++++++++++------ test/test_helper.bash | 4 ++++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/bin/pyenv-virtualenv-prefix b/bin/pyenv-virtualenv-prefix index d097670..901f2da 100755 --- a/bin/pyenv-virtualenv-prefix +++ b/bin/pyenv-virtualenv-prefix @@ -37,11 +37,16 @@ for version in "${versions[@]}"; do exit 1 fi PYENV_PREFIX_PATH="$(pyenv-prefix "${version}")" - if [ -f "${PYENV_PREFIX_PATH}/bin/activate" ]; then - VIRTUALENV_PREFIX_PATH="$(real_prefix "${version}" || base_prefix "${version}" || true)" - VIRTUALENV_PREFIX_PATHS=("${VIRTUALENV_PREFIX_PATHS[@]}" "${VIRTUALENV_PREFIX_PATH:-${PYENV_PREFIX_PATH}}") + if [ -x "${PYENV_PREFIX_PATH}/bin/python" ]; then + if [ -f "${PYENV_PREFIX_PATH}/bin/activate" ]; then + VIRTUALENV_PREFIX_PATH="$(real_prefix "${version}" || base_prefix "${version}" || true)" + VIRTUALENV_PREFIX_PATHS=("${VIRTUALENV_PREFIX_PATHS[@]}" "${VIRTUALENV_PREFIX_PATH:-${PYENV_PREFIX_PATH}}") + else + echo "pyenv-virtualenv: version \`${version}' is not a virtualenv" 1>&2 + exit 1 + fi else - echo "pyenv-virtualenv: version \`${version}' is not a virtualenv" 1>&2 + echo "pyenv-virtualenv: \`python' not found in version \`${version}'" 1>&2 exit 1 fi done diff --git a/test/prefix.bats b/test/prefix.bats index ea03736..95a9cae 100644 --- a/test/prefix.bats +++ b/test/prefix.bats @@ -6,13 +6,23 @@ setup() { export PYENV_ROOT="${TMP}/pyenv" } -create_virtualenv() { +create_version() { mkdir -p "${PYENV_ROOT}/versions/$1/bin" + touch "${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_version "$@" touch "${PYENV_ROOT}/versions/$1/bin/activate" } remove_virtualenv() { - rm -fr "${PYENV_ROOT}/versions/$1" + remove_version "$@" } @test "display prefix with using sys.real_prefix" { @@ -118,13 +128,13 @@ OUT @test "should fail if the version is not a virtualenv" { stub pyenv-version-name "echo 3.4.0" stub pyenv-prefix "3.4.0 : echo \"${PYENV_ROOT}/versions/3.4.0\"" - mkdir -p "${PYENV_ROOT}/versions/3.4.0" + create_version "3.4.0" PYENV_VERSION="3.4.0" run pyenv-virtualenv-prefix unstub pyenv-version-name unstub pyenv-prefix - rmdir "${PYENV_ROOT}/versions/3.4.0" + remove_version "3.4.0" assert_failure assert_output < Date: Thu, 26 Nov 2015 11:06:43 +0000 Subject: [PATCH 2/3] Should not try to find system-site-packages if virtualenv is a conda's environment (#104) --- etc/pyenv.d/which/system-site-packages.bash | 40 +++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/etc/pyenv.d/which/system-site-packages.bash b/etc/pyenv.d/which/system-site-packages.bash index 4838725..8b49790 100644 --- a/etc/pyenv.d/which/system-site-packages.bash +++ b/etc/pyenv.d/which/system-site-packages.bash @@ -5,27 +5,31 @@ if [ ! -x "${PYENV_COMMAND_PATH}" ]; then virtualenv_prefix="$(pyenv-virtualenv-prefix 2>/dev/null || true)" - if [ -d "${virtualenv_prefix}" ]; then + if [ -d "$(pyenv-prefix)" ] && [ -d "${virtualenv_prefix}" ]; then unset include_system_site_packages - if [ -f "$(pyenv-prefix)/pyvenv.cfg" ]; then - # pyvenv - if grep -q -i "include-system-site-packages *= *true" "$(pyenv-prefix)/pyvenv.cfg" 1>/dev/null 2>&1; then - include_system_site_packages=1 - fi + if [ -f "$(pyenv-prefix)/bin/conda" ]; then + : # do nothing for conda's environments else - # virtualenv - shopt -s nullglob - no_global_site_packages="$(echo "$(pyenv-prefix)/lib/"*"/no-global-site-packages.txt")" - shopt -u nullglob - if [ ! -f "${no_global_site_packages}" ]; then - include_system_site_packages=1 + if [ -f "$(pyenv-prefix)/pyvenv.cfg" ]; then + # pyvenv + if grep -q -i "include-system-site-packages *= *true" "$(pyenv-prefix)/pyvenv.cfg" 1>/dev/null 2>&1; then + include_system_site_packages=1 + fi + else + # virtualenv + shopt -s nullglob + no_global_site_packages="$(echo "$(pyenv-prefix)/lib/"*"/no-global-site-packages.txt")" + shopt -u nullglob + if [ ! -f "${no_global_site_packages}" ]; then + include_system_site_packages=1 + fi fi - fi - if [ -n "${include_system_site_packages}" ]; then - # virtualenv is created with `--system-site-packages` - virtualenv_command_path="${virtualenv_prefix}/bin/${PYENV_COMMAND_PATH##*/}" - if [ -x "${virtualenv_command_path}" ]; then - PYENV_COMMAND_PATH="${virtualenv_command_path}" + if [ -n "${include_system_site_packages}" ]; then + # virtualenv is created with `--system-site-packages` + virtualenv_command_path="${virtualenv_prefix}/bin/${PYENV_COMMAND_PATH##*/}" + if [ -x "${virtualenv_command_path}" ]; then + PYENV_COMMAND_PATH="${virtualenv_command_path}" + fi fi fi fi From c3d044d70a8d36188dd88f04f0be655475967871 Mon Sep 17 00:00:00 2001 From: "Yamashita, Yuu" Date: Thu, 26 Nov 2015 12:39:15 +0000 Subject: [PATCH 3/3] Only use premitives in which hooks to avoid infinite loop (#104) --- etc/pyenv.d/which/python-config.bash | 27 +++++++++++++++++---- etc/pyenv.d/which/system-site-packages.bash | 18 +++++++++----- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/etc/pyenv.d/which/python-config.bash b/etc/pyenv.d/which/python-config.bash index ed31eee..7d2b3eb 100644 --- a/etc/pyenv.d/which/python-config.bash +++ b/etc/pyenv.d/which/python-config.bash @@ -4,11 +4,28 @@ # https://github.com/yyuu/pyenv/issues/397 if [ ! -x "${PYENV_COMMAND_PATH}" ] && [[ "${PYENV_COMMAND_PATH##*/}" == "python"*"-config" ]]; then - virtualenv_prefix="$(pyenv-virtualenv-prefix 2>/dev/null || true)" - if [ -d "${virtualenv_prefix}" ]; then - virtualenv_command_path="${virtualenv_prefix}/bin/${PYENV_COMMAND_PATH##*/}" - if [ -x "${virtualenv_command_path}" ]; then - PYENV_COMMAND_PATH="${virtualenv_command_path}" + OLDIFS="${IFS}" + IFS=: + version="$(pyenv-version-name)" + IFS="${OLDIFS}" + if [ -f "${PYENV_ROOT}/versions/${version}/bin/activate" ]; then + if [ -f "${PYENV_ROOT}/versions/${version}/bin/conda" ]; then + : # do nothing for conda's environments + else + if [ -f "${PYENV_ROOT}/versions/${version}/bin/pyvenv.cfg" ]; then + # pyvenv + virtualenv_binpath="$(cut -b 1-1024 "${PYENV_ROOT}/versions/${version}/pyvenv.cfg" | sed -n '/^ *home *= */s///p' || true)" + virtualenv_prefix="${virtualenv_binpath%/bin}" + else + # virtualenv + shopt -s nullglob + virtualenv_prefix="$(cat "${PYENV_ROOT}/versions/${version}/lib/"*"/orig-prefix.txt" &1 || true)" + shopt -u nullglob + fi + virtualenv_command_path="${virtualenv_prefix}/bin/${PYENV_COMMAND_PATH##*/}" + if [ -x "${virtualenv_command_path}" ]; then + PYENV_COMMAND_PATH="${virtualenv_command_path}" + fi fi fi fi diff --git a/etc/pyenv.d/which/system-site-packages.bash b/etc/pyenv.d/which/system-site-packages.bash index 8b49790..ee7dc91 100644 --- a/etc/pyenv.d/which/system-site-packages.bash +++ b/etc/pyenv.d/which/system-site-packages.bash @@ -4,21 +4,27 @@ # https://github.com/yyuu/pyenv-virtualenv/issues/62 if [ ! -x "${PYENV_COMMAND_PATH}" ]; then - virtualenv_prefix="$(pyenv-virtualenv-prefix 2>/dev/null || true)" - if [ -d "$(pyenv-prefix)" ] && [ -d "${virtualenv_prefix}" ]; then + OLDIFS="${IFS}" + IFS=: + version="$(pyenv-version-name)" + IFS="${OLDIFS}" + if [ -f "${PYENV_ROOT}/versions/${version}/bin/activate" ]; then unset include_system_site_packages - if [ -f "$(pyenv-prefix)/bin/conda" ]; then + if [ -f "${PYENV_ROOT}/versions/${version}/bin/conda" ]; then : # do nothing for conda's environments else - if [ -f "$(pyenv-prefix)/pyvenv.cfg" ]; then + if [ -f "${PYENV_ROOT}/versions/${version}/pyvenv.cfg" ]; then # pyvenv - if grep -q -i "include-system-site-packages *= *true" "$(pyenv-prefix)/pyvenv.cfg" 1>/dev/null 2>&1; then + virtualenv_binpath="$(cut -b 1-1024 "${PYENV_ROOT}/versions/${version}/pyvenv.cfg" | sed -n '/^ *home *= */s///p' || true)" + virtualenv_prefix="${virtualenv_binpath%/bin}" + if grep -q -i "include-system-site-packages *= *true" "${PYENV_ROOT}/versions/${version}/pyvenv.cfg" 1>/dev/null 2>&1; then include_system_site_packages=1 fi else # virtualenv shopt -s nullglob - no_global_site_packages="$(echo "$(pyenv-prefix)/lib/"*"/no-global-site-packages.txt")" + virtualenv_prefix="$(cat "${PYENV_ROOT}/versions/${version}/lib/"*"/orig-prefix.txt" &1 || true)" + no_global_site_packages="$(echo "${PYENV_ROOT}/versions/${version}/lib/"*"/no-global-site-packages.txt")" shopt -u nullglob if [ ! -f "${no_global_site_packages}" ]; then include_system_site_packages=1