Updates all pyenv virtual environments to the latest micro version of Python
#!/usr/bin/env bash | |
# | |
# update_envs_micro_python.sh | |
# | |
# Updates all pyenv virtual environments to the latest micro version of Python | |
# | |
# Author: Joao Moreira (jagmoreira) | |
# | |
# First update pyenv to get any new python versions | |
if type pyenv >/dev/null 2>&1; then | |
# Homebrew pyenv | |
if type brew >/dev/null 2>&1 && [[ -n "$(brew ls | grep pyenv)" ]]; then | |
brew upgrade pyenv | |
# Linux pyenv | |
else | |
pyenv update | |
fi | |
else | |
echo "Pyenv does not appear to be installed in your system..." | |
echo | |
exit 1 | |
fi | |
# Exit script if any errors occur (commands return non-zero status) | |
set -e | |
# If any command in a pipe returns an error, fail the whole pipe | |
set -o pipefail | |
# Get currently installed main pythons with derived virtualenvs | |
MAIN_PYTHONS="$(pyenv versions --skip-aliases --bare | grep / | cut -f 1 -d / | uniq)" | |
for VERSION in $MAIN_PYTHONS; do | |
echo | |
echo "Checking for micro version updates for python $VERSION." | |
echo | |
# Get the latest micro version for each A.B python | |
MAJOR_MINOR="$(echo $VERSION | cut -f 1,2 -d .)" | |
LATEST_MICRO=$(pyenv install -l | grep -E "(^| )$MAJOR_MINOR" | sort -b -V | tail -n 1 | sed -e 's/^[ \t]*//') | |
# If there are no new micro versions we move on to the next main Python | |
if [[ "$VERSION" = "$LATEST_MICRO" ]]; then | |
echo | |
echo -n "Version $VERSION is already the latest version in the" | |
echo " $MAJOR_MINOR.x series." | |
echo | |
continue | |
fi | |
echo | |
echo "Found a new micro version for python $VERSION!" | |
echo "$VERSION -> $LATEST_MICRO" | |
echo | |
# Install the latest micro and upgrade pip | |
pyenv install -s "$LATEST_MICRO" | |
pyenv rehash | |
export PYENV_VERSION="$LATEST_MICRO" | |
pip install --upgrade pip | |
# Get all virtual environments for this minor version | |
VENVS="$(pyenv versions --skip-aliases --bare | grep $VERSION/ | cut -f 3 -d /)" | |
N_VENVS=$(echo $VENVS| wc -w) | |
echo | |
echo "Found $N_VENVS virtual environments built with python $VERSION." | |
echo | |
for ENV in $VENVS; do | |
echo | |
echo "Upgrading micro python version of '$ENV' virtualenv: $VERSION-> $LATEST_MICRO" | |
echo | |
ENV_PIP_REQS="__tmp_${ENV}_requirements.pip" | |
export PYENV_VERSION="$ENV" # "Activate" the virtualenv | |
pip freeze > $ENV_PIP_REQS | |
pyenv uninstall -f "$ENV" | |
pyenv virtualenv "$LATEST_MICRO" "$ENV" | |
pyenv rehash | |
echo | |
echo "Re-installing $ENV with all its packages." | |
echo | |
# PYENV_VERSION is still set. No need to update it since it's just a | |
# string with the virtualenv name, which did not change. | |
pip install --upgrade pip | |
# If numpy is present install it manually, otherwise some package | |
# installations might fail due to mall-formed installation requirements | |
set +e # Temporarily disabling error checking to catch empty grep result | |
NUMPY="$(grep numpy= $ENV_PIP_REQS)" | |
set -e | |
if [[ -n $NUMPY ]]; then | |
pip install $NUMPY | |
fi | |
# Installation of old versions of statsmodels may fail due to mall-formed | |
# installation requirements. To prevent this, we install all other | |
# packages first then try the full requirements file again | |
if [[ -n "$(grep statsmodels $ENV_PIP_REQS)" ]]; then | |
sed -e '/statsmodels/d' $ENV_PIP_REQS | pip install -r /dev/stdin | |
fi | |
pip install -r $ENV_PIP_REQS | |
done | |
# Check for any existing environments for the old minor version | |
if [[ -z "$(pyenv versions --skip-aliases --bare | grep $VERSION/)" ]]; then | |
echo | |
echo -n "No more virtualenvs for python $VERSION." | |
echo " Deleting this minor version..." | |
echo | |
pyenv uninstall -f "$VERSION" | |
fi | |
done | |
# Final cleanup | |
unset PYENV_VERSION | |
rm -f __tmp_*_requirements.pip |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Thanks!