Last active
December 17, 2021 07:29
-
-
Save pujianto/7df2413d64480f7797e1f0c434841283 to your computer and use it in GitHub Desktop.
Lazy solution to reinstall your Python libraries inside your PEW virtualenv wrapper or plain virtualenv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# THIS SCRIPT IS INTENDED FOR ROLLING RELEASE DISTRO USERS. | |
# Sometimes my local libraries didn't work after upgrading my Python, so I decided to write this helper script. | |
# | |
# Usage: | |
# venv_upgrade [options] | |
# | |
# Options: | |
# -h, --help Show this help message. | |
# -p, --path Path to your virtualenv. | |
# -n, --name Name of your virtualenv (PEW ONLY). | |
# -l, --list List all virtual environments (PEW ONLY). | |
# --dry-run Run without actually upgrading your virtualenv. | |
# | |
# Some libraries may be not compatible to your new Python version. Be sure to add --dry-run to check it. | |
# This script can also be sourced from your favorite shell as long as it POSIX compatible (bash, zsh, etc.). | |
venv_upgrade() { | |
usage() { | |
printf "Usage: \n" | |
printf " venv_upgrade [options]\n\n\n" | |
printf "Options:\n" | |
printf " -h, --help\t\t Show this help message.\n" | |
printf " -p, --path\t\t Path to your virtualenv.\n" | |
printf " -n, --name\t\t Name of your virtualenv (PEW ONLY).\n" | |
printf " -l, --list\t\t List all virtual environments (PEW ONLY).\n" | |
printf " --dry-run\t Run without actually upgrading your virtualenv.\n\n\n" | |
} | |
if ! command -v pip >/dev/null 2>&1; then | |
printf "pip is not installed" | |
return 1 | |
fi | |
if ! command -v virtualenv >/dev/null 2>&1; then | |
printf "virtualenv is not installed" | |
return 1 | |
fi | |
VENV_DRY_RUN=0 | |
while [ $# -gt 0 ]; do | |
case "${1}" in | |
-h | --help) | |
usage | |
shift | |
return 0 | |
;; | |
-p | --path) | |
VENV_DIR_PATH="${2}" | |
VENV_ENV_NAME=$(basename "${VENV_DIR_PATH}") | |
if [ ! -d "${VENV_DIR_PATH}" ]; then | |
printf "Path does not exist" | |
return 1 | |
fi | |
shift | |
shift | |
;; | |
-n | --name) | |
VENV_ENV_NAME="${2}" | |
if ! command -V pew >/dev/null 2>&1; then | |
printf "pew is not installed" | |
return 1 | |
fi | |
VENV_DIR_PATH=$(python -m pew dir "${VENV_ENV_NAME}") | |
VENV_RETVAL=$? | |
if [ $VENV_RETVAL -ne 0 ]; then | |
return $VENV_RETVAL | |
fi | |
shift | |
shift | |
;; | |
-l | --list) | |
if ! command -V pew >/dev/null 2>&1; then | |
printf "pew is not installed" | |
return 1 | |
fi | |
python -m pew ls | |
return 0 | |
;; | |
--dry-run) | |
printf "\nDry run mode.\n" | |
VENV_DRY_RUN=1 | |
shift | |
;; | |
\ | |
*) | |
shift | |
;; | |
esac | |
done | |
if [ -z "${VENV_DIR_PATH}" ] || [ -z "${VENV_ENV_NAME}" ]; then | |
usage | |
return 1 | |
fi | |
VENV_LIB_PATH="${VENV_DIR_PATH}/lib" | |
VENV_PYTHON_VERSION=$(python -V | awk 'BEGIN{FS=OFS="."} NF--' | sed 's/\s//g' | tr '[:upper:]' '[:lower:]') | |
VENV_DETECTED_PYTHON_RUNTIMES=$(find "${VENV_LIB_PATH}" -maxdepth 1 ! -path "${VENV_LIB_PATH}" -type d -name "python*" -printf '%f\n' | sort -k1) | |
VENV_DETECTED_PYTHON_RUNTIMES_COUNT=$(echo "${VENV_DETECTED_PYTHON_RUNTIMES}" | wc -l) | |
if [ "${VENV_DETECTED_PYTHON_RUNTIMES_COUNT}" -gt 1 ]; then | |
printf "%d Python runtimes detected: \nPlease specify the one you want to upgrade to: (default 1) \n" "${VENV_DETECTED_PYTHON_RUNTIMES_COUNT}" | |
VENV_IDX=1 | |
for VENV_PY in ${VENV_DETECTED_PYTHON_RUNTIMES}; do | |
printf "\t%s. %s\n" "${VENV_IDX}" "${VENV_PY}" | |
VENV_IDX=$((VENV_IDX + 1)) | |
done | |
read -r "VENV_RESPONSE" | |
while true; do | |
case "${VENV_RESPONSE}" in | |
*[!0-9]* | '') ;; | |
*) | |
if [ "${VENV_RESPONSE}" -gt 0 ] && [ "${VENV_RESPONSE}" -le "${VENV_DETECTED_PYTHON_RUNTIMES_COUNT}" ]; then | |
VENV_PYTHONLIB_VERSION=$(echo "${VENV_DETECTED_PYTHON_RUNTIMES}" | awk "NR==${VENV_RESPONSE}") | |
break | |
fi | |
;; | |
esac | |
printf "Please enter a valid number between 1 and %d\n" "${VENV_DETECTED_PYTHON_RUNTIMES_COUNT}" | |
read -r "VENV_RESPONSE" | |
done | |
else | |
VENV_PYTHONLIB_VERSION="${VENV_DETECTED_PYTHON_RUNTIMES}" | |
fi | |
printf "Upgrading python runtime from %s to %s on %s\n" "${VENV_PYTHONLIB_VERSION}" "${VENV_PYTHON_VERSION}" "${VENV_ENV_NAME}" | |
if [ "${VENV_PYTHON_VERSION}" = "${VENV_PYTHONLIB_VERSION}" ]; then | |
printf "(%s) runtime is detected in your virtual environment. Do you want to recreate the virtual environment instead? [y/N]\n" "${VENV_PYTHONLIB_VERSION}" | |
read -r "VENV_RESPONSE" | |
case "$VENV_RESPONSE" in | |
y | Y) ;; | |
\ | |
*) | |
printf "Upgrade cancelled. \n" | |
return 0 | |
;; | |
esac | |
fi | |
VENV_SITE_PACKAGE_PATH="${VENV_LIB_PATH}/${VENV_PYTHONLIB_VERSION}/site-packages" | |
VENV_PACKAGES=$(python -m pip freeze --path "${VENV_SITE_PACKAGE_PATH}") | |
if [ -z "${VENV_PACKAGES}" ]; then | |
printf "No packages found in %s. Aborting.. \n" "${VENV_SITE_PACKAGE_PATH}" | |
return 1 | |
else | |
printf "Packages to be installed: \n\n\n%s \n\nContinue? [y/N]?\n" "${VENV_PACKAGES}" | |
read -r "VENV_RESPONSE" | |
case "$VENV_RESPONSE" in | |
y | Y) | |
printf "Installing..\n" | |
vENV_TMP_DIR=$(mktemp -d -t venv_upgrade.XXXXXXXXXX) | |
VENV_TMP_REQUIREMENTS=$(mktemp -t venv_upgrade.requirements.XXXXXXXXXX.txt) | |
printf "%s" "${VENV_PACKAGES}" >"${VENV_TMP_REQUIREMENTS}" | |
if [ "${VENV_DRY_RUN}" -eq 0 ]; then | |
mv "${VENV_DIR_PATH}" "${vENV_TMP_DIR}" | |
virtualenv "${VENV_DIR_PATH}" | |
VENV_CMD_INSTALL="${VENV_DIR_PATH}/bin/python -m pip install -r ${VENV_TMP_REQUIREMENTS}" | |
eval "${VENV_CMD_INSTALL}" | |
printf "\n\n\nYour packages were installed in %s. \n" "${VENV_DIR_PATH}" | |
printf "Your old virtual environment moved to %s temporary folder. \n" "${vENV_TMP_DIR}" | |
printf "If you want to restore the old virtual environment, run mv %s %s \n" "${vENV_TMP_DIR}" "${VENV_DIR_PATH}" | |
else | |
printf "Dry run enabled. Trying to install your packages in %s (temporary folder) then delete it.\n" "${vENV_TMP_DIR}" | |
virtualenv "${vENV_TMP_DIR}" | |
VENV_CMD_INSTALL="${vENV_TMP_DIR}/bin/python -m pip install -r ${VENV_TMP_REQUIREMENTS}" | |
eval "${VENV_CMD_INSTALL}" | |
printf "Cleanup: rm -rf %s \n" "${vENV_TMP_DIR}" | |
rm -rf "${vENV_TMP_DIR}" | |
fi | |
printf "Cleanup tmp requirements file. \n" | |
rm "${VENV_TMP_REQUIREMENTS}" | |
;; | |
*) | |
printf "Upgrade cancelled. \n" | |
return 0 | |
;; | |
esac | |
return 0 | |
fi | |
} | |
return 2>/dev/null || venv_upgrade "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment