-
-
Save courtc/f01ddfe6798f9e6a5ae3 to your computer and use it in GitHub Desktop.
Virtualenv for Python: Yuck
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/bash -e | |
# | |
# Stay off my lawn | |
# | |
# I refuse to source scripts, so this is my way of dealing with virtualenv. | |
# | |
# Basically the idea here is that I mess up my own personal environment so that | |
# this script runs in place of python. With that I load the proper environment | |
# based on the python script being run. Environment mapping is based on the | |
# canonical file path of each script. | |
# | |
# SETUP: | |
# cp $0 ~/bin/vpy | |
# (cd ~/bin; for k in {vpy,python}{2,2.7,3,3.7}; do | |
# ln -s vpy "$k" | |
# done) | |
# | |
# USE: | |
# vpy new myapp # or e.g. vpy2.7 if you want python2.7 specifically | |
# vpy add myapp myapp.py | |
# vpy pip myapp install mydep # or: vpy run myapp pip install mydep | |
# ./myapp.py | |
# | |
# ALTERNATIVES: | |
# - vex (https://github.com/sashahart/vex) | |
# - virtualenvwrapper (http://virtualenvwrapper.readthedocs.org/en/latest/) | |
# - capn (https://github.com/dustinlacewell/capn) | |
# - pew (https://github.com/berdario/pew) | |
# - inve (https://gist.github.com/datagrok/2199506) | |
me="$(readlink -f "$0")" | |
bn="$(basename "$me")" | |
name="$(basename "$0")" | |
default_version="3" | |
venv_base="$HOME/.virtualenv" | |
venv_env="$venv_base/environments" | |
venv_cfg="$venv_base/config" | |
version="$(echo "$name" | tr -d "[a-zA-Z-]")" | |
[ -d "$venv_base" ] || mkdir -p "$venv_base" | |
[ -e "$venv_cfg" ] || touch "$venv_cfg" | |
usage() { | |
echo "Usage: $bn <command> [OPTIONS]" | |
echo "" | |
echo " Commands:" | |
echo " - new <env> create a new environment named <env>" | |
echo " - del <env> delete existing environment named <env>" | |
echo " - add <env> <prog> add program to environment named <env>" | |
echo " - find <prog> locate environment where program runs (if any)" | |
echo " - pip <env> <cmd...> run pip in existing environment named <env>" | |
echo " - run <env> <cmd...> run command in existing environment named <env>" | |
exit 1 | |
} | |
# we keep track of a file's abs. path by hashing it; that way we don't | |
# need to deal with special characters when storing it | |
vpy_hash() { | |
readlink -f "$1" | sha1sum | cut -f1 -d' ' | |
} | |
vpy_lookup() { | |
sed -n '/^'"$(vpy_hash "$1")"'/s/^[^\s]\+\s\+//p' "$venv_cfg" | |
} | |
vpy_delete() { | |
sed -i '/^[0-9a-f]* '"$1"'$/d' "$venv_cfg" | |
} | |
vpy_add() { | |
key="$1" | |
env="$2" | |
sed -i '/^'"$key"'\s/d' "$venv_cfg" | |
echo "$key $env" >> "$venv_cfg" | |
} | |
_vpy() { | |
[ -z "$version" ] && version="$default_version" | |
#[[ "$version" =~ [0-9].[0-9] ]] && version="-$version" | |
[ $# -lt 2 ] && usage | |
[ -z "$2" ] && usage | |
env="$2" | |
if [ "$1" == "new" ]; then | |
mkdir -p "$venv_env/$env" | |
exec "virtualenv${version:0:1}" --always-copy "$venv_env/$env" | |
elif [ "$1" == "del" ]; then | |
vpy_delete "$2" | |
exec rm -rf "$venv_env/$env" | |
elif [ "$1" == "add" ]; then | |
[ $# -lt 3 ] && usage | |
vpy_add "$(vpy_hash "$3")" "$env" | |
elif [ "$1" == "find" ]; then | |
vpy_lookup "$2" | |
elif [ "$1" == "hash" ]; then | |
vpy_hash "$2" | |
elif [ "$1" == "pip" ]; then | |
shift; shift | |
. "$venv_env/$env/bin/activate" | |
exec pip "$@" | |
elif [ "$1" == "run" ]; then | |
shift; shift | |
. "$venv_env/$env/bin/activate" | |
exec "$@" | |
else | |
usage | |
fi | |
} | |
# finds the first file argument on a typical python command-line | |
firstfile() { | |
lastchar=0 | |
for arg in "$@"; do | |
if [ "${arg:0:1}" == "-" ]; then | |
lastchar="${arg:1:2}" | |
continue | |
fi | |
case "$lastchar" in [cWmX]) discard=1 ;; *) discard=0 ;; esac | |
lastchar=0 | |
[ $discard -eq 1 ] && continue | |
echo "$arg" | |
return | |
done | |
} | |
if [[ "$name" =~ $bn[0-9.]* ]]; then | |
_vpy "$@" | |
elif [[ "$name" =~ python[0-9.]* ]]; then | |
file="$(firstfile "$@")" | |
[ -z "$file" ] || env="$(vpy_lookup "$file")" | |
[ -z "$env" ] || . "$venv_env/$env/bin/activate" | |
for ver in $(which -a "python$version"); do | |
[ "$(readlink -f "$ver")" != "$me" ] && exec "$ver" "$@" | |
done | |
echo "Unable to find suitable python version matching \"python$version\"" | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment