Skip to content

Instantly share code, notes, and snippets.

@nolar
Created July 27, 2012 18:22
Show Gist options
  • Save nolar/3189569 to your computer and use it in GitHub Desktop.
Save nolar/3189569 to your computer and use it in GitHub Desktop.
Virtualenv automatic activation
#
# Finds the closest virtualenv root directory, starting from $1, and going up to the root.
# If the target directory is not specified as an argument, current directory is used.
# Prints the virtualenv path found, or nothing otherwise.
#
function venv_find () {
# The cycle is just for the case with broken root folder detection - never do more than N iterations.
venv_root=${1:-"."}
venv_found=""
for (( i=100; i > 0; i-- )); do
venv_real=$(cd $venv_root && pwd -P)
if [ -f "$venv_real/bin/activate" ]; then
echo $venv_real
return
fi
if [ "$venv_real" = "/" ]; then
return
fi
venv_root=$venv_root/".."
done
}
#
# Find current virtualenv, and prints its path.
# NB: The virtualenv must be activated in the current shell, or it will be ignored as if there is
# NB: no active virtualenv at all. This is needed because current virtualenv is usually determined
# NB: to be deactivated, and if it is not in the current shell, there is no "deactivate" function.
#
function venv_curr () {
if [ -n "$VIRTUAL_ENV" -a "$(type -t deactivate)" = 'function' ]; then
echo $VIRTUAL_ENV
fi
}
#
# Activates a virtualenv which we are in (or in any of its subfolders), according to our cwd.
# Deactivates any virtualenv when we leave it (cd to a directory with no venv at all).
#
function venv_auto () {
venv_new=$(venv_find)
venv_old=$(venv_curr)
bash_cmd=`basename $(expr "$BASH_COMMAND" : "\([^ ]*\)")`
# Special case for subshells - they will reactivate their own venv inside. This is needed
# to properly keep "deactivate" function inside subshells, and avoid recursive venvs.
if [ "$bash_cmd" == "mc" -o "$bash_cmd" == "bash" -o "$bash_cmd" == "sh" ]; then
# echo "DEACTIVATE $venv_old FOR $bash_cmd"
deactivate
elif [ -z "$venv_new" -a -n "$venv_old" ]; then
# echo "DEACTIVATE $venv_old"
deactivate
elif [ -n "$venv_new" -a "$venv_new" != "$venv_old" ]; then
# echo "ACTIVATE $venv_new"
source $venv_new/bin/activate
fi
}
#
# Attach automatic virtualenv detection for any command or action in the shell.
# Works well even if you change dirs in mc.
#
trap venv_auto DEBUG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment