From e534002e4d3ba48b70e9644e60ddd6a103b450a8 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Fri, 10 Nov 2017 12:45:09 +0000 Subject: [PATCH] Adding virtual env wrapper --- virtualenvwrapper.sh | 1352 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1352 insertions(+) create mode 100644 virtualenvwrapper.sh diff --git a/virtualenvwrapper.sh b/virtualenvwrapper.sh new file mode 100644 index 0000000..2104cb4 --- /dev/null +++ b/virtualenvwrapper.sh @@ -0,0 +1,1352 @@ +# -*- mode: shell-script -*- +# +# Shell functions to act as wrapper for Ian Bicking's virtualenv +# (http://pypi.python.org/pypi/virtualenv) +# +# +# Copyright Doug Hellmann, All Rights Reserved +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, +# provided that the above copyright notice appear in all copies and that +# both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of Doug Hellmann not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. +# +# DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# +# +# Project home page: http://www.doughellmann.com/projects/virtualenvwrapper/ +# +# +# Setup: +# +# 1. Create a directory to hold the virtual environments. +# (mkdir $HOME/.virtualenvs). +# 2. Add a line like "export WORKON_HOME=$HOME/.virtualenvs" +# to your .bashrc. +# 3. Add a line like "source /path/to/this/file/virtualenvwrapper.sh" +# to your .bashrc. +# 4. Run: source ~/.bashrc +# 5. Run: workon +# 6. A list of environments, empty, is printed. +# 7. Run: mkvirtualenv temp +# 8. Run: workon +# 9. This time, the "temp" environment is included. +# 10. Run: workon temp +# 11. The virtual environment is activated. +# + +# Locate the global Python where virtualenvwrapper is installed. +if [ "$VIRTUALENVWRAPPER_PYTHON" = "" ] +then + VIRTUALENVWRAPPER_PYTHON="$(command \which python)" +fi + +# Set the name of the virtualenv app to use. +if [ "$VIRTUALENVWRAPPER_VIRTUALENV" = "" ] +then + VIRTUALENVWRAPPER_VIRTUALENV="virtualenv" +fi + +# Set the name of the virtualenv-clone app to use. +if [ "$VIRTUALENVWRAPPER_VIRTUALENV_CLONE" = "" ] +then + VIRTUALENVWRAPPER_VIRTUALENV_CLONE="virtualenv-clone" +fi + +# Define script folder depending on the platorm (Win32/Unix) +VIRTUALENVWRAPPER_ENV_BIN_DIR="bin" +if [ "$OS" = "Windows_NT" ] && ([ "$MSYSTEM" = "MINGW32" ] || [ "$MSYSTEM" = "MINGW64" ]) +then + # Only assign this for msys, cygwin use standard Unix paths + # and its own python installation + VIRTUALENVWRAPPER_ENV_BIN_DIR="Scripts" +fi + +# Let the user override the name of the file that holds the project +# directory name. +if [ "$VIRTUALENVWRAPPER_PROJECT_FILENAME" = "" ] +then + export VIRTUALENVWRAPPER_PROJECT_FILENAME=".project" +fi + +# Let the user tell us they never want to cd to projects +# automatically. +export VIRTUALENVWRAPPER_WORKON_CD=${VIRTUALENVWRAPPER_WORKON_CD:-1} + +# Remember where we are running from. +if [ -z "$VIRTUALENVWRAPPER_SCRIPT" ] +then + if [ -n "$BASH" ] + then + export VIRTUALENVWRAPPER_SCRIPT="$BASH_SOURCE" + elif [ -n "$ZSH_VERSION" ] + then + export VIRTUALENVWRAPPER_SCRIPT="$0" + else + export VIRTUALENVWRAPPER_SCRIPT="${.sh.file}" + fi +fi + +# Portable shell scripting is hard, let's go shopping. +# +# People insist on aliasing commands like 'cd', either with a real +# alias or even a shell function. Under bash and zsh, "builtin" forces +# the use of a command that is part of the shell itself instead of an +# alias, function, or external command, while "command" does something +# similar but allows external commands. Under ksh "builtin" registers +# a new command from a shared library, but "command" will pick up +# existing builtin commands. We need to use a builtin for cd because +# we are trying to change the state of the current shell, so we use +# "builtin" for bash and zsh but "command" under ksh. +function virtualenvwrapper_cd { + if [ -n "$BASH" ] + then + builtin \cd "$@" + elif [ -n "$ZSH_VERSION" ] + then + builtin \cd -q "$@" + else + command \cd "$@" + fi +} + +function virtualenvwrapper_expandpath { + if [ "$1" = "" ]; then + return 1 + else + "$VIRTUALENVWRAPPER_PYTHON" -c "import os,sys; sys.stdout.write(os.path.normpath(os.path.expanduser(os.path.expandvars(\"$1\")))+'\n')" + return 0 + fi +} + +function virtualenvwrapper_absolutepath { + if [ "$1" = "" ]; then + return 1 + else + "$VIRTUALENVWRAPPER_PYTHON" -c "import os,sys; sys.stdout.write(os.path.abspath(\"$1\")+'\n')" + return 0 + fi +} + +function virtualenvwrapper_derive_workon_home { + typeset workon_home_dir="$WORKON_HOME" + + # Make sure there is a default value for WORKON_HOME. + # You can override this setting in your .bashrc. + if [ "$workon_home_dir" = "" ] + then + workon_home_dir="$HOME/.virtualenvs" + fi + + # If the path is relative, prefix it with $HOME + # (note: for compatibility) + if echo "$workon_home_dir" | (unset GREP_OPTIONS; command \grep '^[^/~]' > /dev/null) + then + workon_home_dir="$HOME/$WORKON_HOME" + fi + + # Only call on Python to fix the path if it looks like the + # path might contain stuff to expand. + # (it might be possible to do this in shell, but I don't know a + # cross-shell-safe way of doing it -wolever) + if echo "$workon_home_dir" | (unset GREP_OPTIONS; command \egrep '([\$~]|//)' >/dev/null) + then + # This will normalize the path by: + # - Removing extra slashes (e.g., when TMPDIR ends in a slash) + # - Expanding variables (e.g., $foo) + # - Converting ~s to complete paths (e.g., ~/ to /home/brian/ and ~arthur to /home/arthur) + workon_home_dir="$(virtualenvwrapper_expandpath "$workon_home_dir")" + fi + + echo "$workon_home_dir" + return 0 +} + +# Check if the WORKON_HOME directory exists, +# create it if it does not +# seperate from creating the files in it because this used to just error +# and maybe other things rely on the dir existing before that happens. +function virtualenvwrapper_verify_workon_home { + RC=0 + if [ ! -d "$WORKON_HOME/" ] + then + if [ "$1" != "-q" ] + then + echo "NOTE: Virtual environments directory $WORKON_HOME does not exist. Creating..." 1>&2 + fi + mkdir -p "$WORKON_HOME" + RC=$? + fi + return $RC +} + +#HOOK_VERBOSE_OPTION="-q" + +# Function to wrap mktemp so tests can replace it for error condition +# testing. +function virtualenvwrapper_mktemp { + command \mktemp "$@" +} + +# Expects 1 argument, the suffix for the new file. +function virtualenvwrapper_tempfile { + # Note: the 'X's must come last + typeset suffix=${1:-hook} + typeset file + + file="$(virtualenvwrapper_mktemp -t virtualenvwrapper-$suffix-XXXXXXXXXX)" + touch "$file" + if [ $? -ne 0 ] || [ -z "$file" ] || [ ! -f "$file" ] + then + echo "ERROR: virtualenvwrapper could not create a temporary file name." 1>&2 + return 1 + fi + echo $file + return 0 +} + +# Run the hooks +function virtualenvwrapper_run_hook { + typeset hook_script + typeset result + + hook_script="$(virtualenvwrapper_tempfile ${1}-hook)" || return 1 + + # Use a subshell to run the python interpreter with hook_loader so + # we can change the working directory. This avoids having the + # Python 3 interpreter decide that its "prefix" is the virtualenv + # if we happen to be inside the virtualenv when we start. + ( \ + virtualenvwrapper_cd "$WORKON_HOME" && + "$VIRTUALENVWRAPPER_PYTHON" -m 'virtualenvwrapper.hook_loader' \ + $HOOK_VERBOSE_OPTION --script "$hook_script" "$@" \ + ) + result=$? + + if [ $result -eq 0 ] + then + if [ ! -f "$hook_script" ] + then + echo "ERROR: virtualenvwrapper_run_hook could not find temporary file $hook_script" 1>&2 + command \rm -f "$hook_script" + return 2 + fi + # cat "$hook_script" + source "$hook_script" + elif [ "${1}" = "initialize" ] + then + cat - 1>&2 <&2 + return 1 + fi + if [ ! -e "$exe_path" ] + then + echo "ERROR: Found $1 in path as \"$exe_path\" but that does not exist" >&2 + return 1 + fi + return 0 +} + + +# Verify that virtualenv is installed and visible +function virtualenvwrapper_verify_virtualenv { + virtualenvwrapper_verify_resource $VIRTUALENVWRAPPER_VIRTUALENV +} + + +function virtualenvwrapper_verify_virtualenv_clone { + virtualenvwrapper_verify_resource $VIRTUALENVWRAPPER_VIRTUALENV_CLONE +} + + +# Verify that the requested environment exists +function virtualenvwrapper_verify_workon_environment { + typeset env_name="$1" + if [ ! -d "$WORKON_HOME/$env_name" ] + then + echo "ERROR: Environment '$env_name' does not exist. Create it with 'mkvirtualenv $env_name'." >&2 + return 1 + fi + return 0 +} + +# Verify that the active environment exists +function virtualenvwrapper_verify_active_environment { + if [ ! -n "${VIRTUAL_ENV}" ] || [ ! -d "${VIRTUAL_ENV}" ] + then + echo "ERROR: no virtualenv active, or active virtualenv is missing" >&2 + return 1 + fi + return 0 +} + +# Help text for mkvirtualenv +function virtualenvwrapper_mkvirtualenv_help { + echo "Usage: mkvirtualenv [-a project_path] [-i package] [-r requirements_file] [virtualenv options] env_name" + echo + echo " -a project_path" + echo + echo " Provide a full path to a project directory to associate with" + echo " the new environment." + echo + echo " -i package" + echo + echo " Install a package after the environment is created." + echo " This option may be repeated." + echo + echo " -r requirements_file" + echo + echo " Provide a pip requirements file to install a base set of packages" + echo " into the new environment." + echo; + echo 'virtualenv help:'; + echo; + "$VIRTUALENVWRAPPER_VIRTUALENV" $@; +} + +# Create a new environment, in the WORKON_HOME. +# +# Usage: mkvirtualenv [options] ENVNAME +# (where the options are passed directly to virtualenv) +# +#:help:mkvirtualenv: Create a new virtualenv in $WORKON_HOME +function mkvirtualenv { + typeset -a in_args + typeset -a out_args + typeset -i i + typeset tst + typeset a + typeset envname + typeset requirements + typeset packages + typeset interpreter + typeset project + + in_args=( "$@" ) + + if [ -n "$ZSH_VERSION" ] + then + i=1 + tst="-le" + else + i=0 + tst="-lt" + fi + while [ $i $tst $# ] + do + a="${in_args[$i]}" + # echo "arg $i : $a" + case "$a" in + -a) + i=$(( $i + 1 )) + project="${in_args[$i]}" + if [ ! -d "$project" ] + then + echo "Cannot associate project with $project, it is not a directory" 1>&2 + return 1 + fi + project="$(virtualenvwrapper_absolutepath ${project})";; + -h|--help) + virtualenvwrapper_mkvirtualenv_help $a; + return;; + -i) + i=$(( $i + 1 )); + packages="$packages ${in_args[$i]}";; + -p|--python*) + if echo "$a" | grep -q "=" + then + interpreter="$(echo "$a" | cut -f2 -d=)" + else + i=$(( $i + 1 )) + interpreter="${in_args[$i]}" + fi;; + -r) + i=$(( $i + 1 )); + requirements="${in_args[$i]}"; + requirements="$(virtualenvwrapper_expandpath "$requirements")";; + *) + if [ ${#out_args} -gt 0 ] + then + out_args=( "${out_args[@]-}" "$a" ) + else + out_args=( "$a" ) + fi;; + esac + i=$(( $i + 1 )) + done + + if [ ! -z $interpreter ] + then + out_args=( "--python=$interpreter" ${out_args[@]} ) + fi; + + set -- "${out_args[@]}" + + eval "envname=\$$#" + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_virtualenv || return 1 + ( + [ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT + virtualenvwrapper_cd "$WORKON_HOME" && + "$VIRTUALENVWRAPPER_VIRTUALENV" $VIRTUALENVWRAPPER_VIRTUALENV_ARGS "$@" && + [ -d "$WORKON_HOME/$envname" ] && \ + virtualenvwrapper_run_hook "pre_mkvirtualenv" "$envname" + ) + typeset RC=$? + [ $RC -ne 0 ] && return $RC + + # If they passed a help option or got an error from virtualenv, + # the environment won't exist. Use that to tell whether + # we should switch to the environment and run the hook. + [ ! -d "$WORKON_HOME/$envname" ] && return 0 + + # If they gave us a project directory, set it up now + # so the activate hooks can find it. + if [ ! -z "$project" ] + then + setvirtualenvproject "$WORKON_HOME/$envname" "$project" + RC=$? + [ $RC -ne 0 ] && return $RC + fi + + # Now activate the new environment + workon "$envname" + + if [ ! -z "$requirements" ] + then + pip install -r "$requirements" + fi + + for a in $packages + do + pip install $a + done + + virtualenvwrapper_run_hook "post_mkvirtualenv" +} + +#:help:rmvirtualenv: Remove a virtualenv +function rmvirtualenv { + virtualenvwrapper_verify_workon_home || return 1 + if [ ${#@} = 0 ] + then + echo "Please specify an enviroment." >&2 + return 1 + fi + + # support to remove several environments + typeset env_name + # Must quote the parameters, as environments could have spaces in their names + for env_name in "$@" + do + echo "Removing $env_name..." + typeset env_dir="$WORKON_HOME/$env_name" + if [ "$VIRTUAL_ENV" = "$env_dir" ] + then + echo "ERROR: You cannot remove the active environment ('$env_name')." >&2 + echo "Either switch to another environment, or run 'deactivate'." >&2 + return 1 + fi + + if [ ! -d "$env_dir" ]; then + echo "Did not find environment $env_dir to remove." >&2 + fi + + # Move out of the current directory to one known to be + # safe, in case we are inside the environment somewhere. + typeset prior_dir="$(pwd)" + virtualenvwrapper_cd "$WORKON_HOME" + + virtualenvwrapper_run_hook "pre_rmvirtualenv" "$env_name" + command \rm -rf "$env_dir" + virtualenvwrapper_run_hook "post_rmvirtualenv" "$env_name" + + # If the directory we used to be in still exists, move back to it. + if [ -d "$prior_dir" ] + then + virtualenvwrapper_cd "$prior_dir" + fi + done +} + +# List the available environments. +function virtualenvwrapper_show_workon_options { + virtualenvwrapper_verify_workon_home || return 1 + # NOTE: DO NOT use ls or cd here because colorized versions spew control + # characters into the output list. + # echo seems a little faster than find, even with -depth 3. + # Note that this is a little tricky, as there may be spaces in the path. + # + # 1. Look for environments by finding the activate scripts. + # Use a subshell so we can suppress the message printed + # by zsh if the glob pattern fails to match any files. + # This yields a single, space-separated line containing all matches. + # 2. Replace the trailing newline with a space, so every + # possible env has a space following it. + # 3. Strip the bindir/activate script suffix, replacing it with + # a slash, as that is an illegal character in a directory name. + # This yields a slash-separated list of possible env names. + # 4. Replace each slash with a newline to show the output one name per line. + # 5. Eliminate any lines with * on them because that means there + # were no envs. + (virtualenvwrapper_cd "$WORKON_HOME" && echo */$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate) 2>/dev/null \ + | command \tr "\n" " " \ + | command \sed "s|/$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate |/|g" \ + | command \tr "/" "\n" \ + | command \sed "/^\s*$/d" \ + | (unset GREP_OPTIONS; command \egrep -v '^\*$') 2>/dev/null +} + +function _lsvirtualenv_usage { + echo "lsvirtualenv [-blh]" + echo " -b -- brief mode" + echo " -l -- long mode" + echo " -h -- this help message" +} + +#:help:lsvirtualenv: list virtualenvs +function lsvirtualenv { + + typeset long_mode=true + if command -v "getopts" &> /dev/null + then + # Use getopts when possible + OPTIND=1 + while getopts ":blh" opt "$@" + do + case "$opt" in + l) long_mode=true;; + b) long_mode=false;; + h) _lsvirtualenv_usage; + return 1;; + ?) echo "Invalid option: -$OPTARG" >&2; + _lsvirtualenv_usage; + return 1;; + esac + done + else + # fallback on getopt for other shell + typeset -a args + args=($(getopt blh "$@")) + if [ $? != 0 ] + then + _lsvirtualenv_usage + return 1 + fi + for opt in $args + do + case "$opt" in + -l) long_mode=true;; + -b) long_mode=false;; + -h) _lsvirtualenv_usage; + return 1;; + esac + done + fi + + if $long_mode + then + allvirtualenv showvirtualenv "$env_name" + else + virtualenvwrapper_show_workon_options + fi +} + +#:help:showvirtualenv: show details of a single virtualenv +function showvirtualenv { + typeset env_name="$1" + if [ -z "$env_name" ] + then + if [ -z "$VIRTUAL_ENV" ] + then + echo "showvirtualenv [env]" + return 1 + fi + env_name=$(basename "$VIRTUAL_ENV") + fi + + virtualenvwrapper_run_hook "get_env_details" "$env_name" + echo +} + +# Show help for workon +function virtualenvwrapper_workon_help { + echo "Usage: workon env_name" + echo "" + echo " Deactivate any currently activated virtualenv" + echo " and activate the named environment, triggering" + echo " any hooks in the process." + echo "" + echo " workon" + echo "" + echo " Print a list of available environments." + echo " (See also lsvirtualenv -b)" + echo "" + echo " workon (-h|--help)" + echo "" + echo " Show this help message." + echo "" + echo " workon (-c|--cd) envname" + echo "" + echo " After activating the environment, cd to the associated" + echo " project directory if it is set." + echo "" + echo " workon (-n|--no-cd) envname" + echo "" + echo " After activating the environment, do not cd to the" + echo " associated project directory." + echo "" +} + +#:help:workon: list or change working virtualenvs +function workon { + typeset -a in_args + typeset -a out_args + + in_args=( "$@" ) + + if [ -n "$ZSH_VERSION" ] + then + i=1 + tst="-le" + else + i=0 + tst="-lt" + fi + typeset cd_after_activate=$VIRTUALENVWRAPPER_WORKON_CD + while [ $i $tst $# ] + do + a="${in_args[$i]}" + case "$a" in + -h|--help) + virtualenvwrapper_workon_help; + return 0;; + -n|--no-cd) + cd_after_activate=0;; + -c|--cd) + cd_after_activate=1;; + *) + if [ ${#out_args} -gt 0 ] + then + out_args=( "${out_args[@]-}" "$a" ) + else + out_args=( "$a" ) + fi;; + esac + i=$(( $i + 1 )) + done + + set -- "${out_args[@]}" + + typeset env_name="$1" + if [ "$env_name" = "" ] + then + lsvirtualenv -b + return 1 + elif [ "$env_name" = "." ] + then + # The IFS default of breaking on whitespace causes issues if there + # are spaces in the env_name, so change it. + IFS='%' + env_name="$(basename $(pwd))" + unset IFS + fi + + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_workon_environment "$env_name" || return 1 + + activate="$WORKON_HOME/$env_name/$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate" + if [ ! -f "$activate" ] + then + echo "ERROR: Environment '$WORKON_HOME/$env_name' does not contain an activate script." >&2 + return 1 + fi + + # Deactivate any current environment "destructively" + # before switching so we use our override function, + # if it exists. + type deactivate >/dev/null 2>&1 + if [ $? -eq 0 ] + then + deactivate + unset -f deactivate >/dev/null 2>&1 + fi + + virtualenvwrapper_run_hook "pre_activate" "$env_name" + + source "$activate" + + # Save the deactivate function from virtualenv under a different name + virtualenvwrapper_original_deactivate=`typeset -f deactivate | sed 's/deactivate/virtualenv_deactivate/g'` + eval "$virtualenvwrapper_original_deactivate" + unset -f deactivate >/dev/null 2>&1 + + # Replace the deactivate() function with a wrapper. + eval 'deactivate () { + typeset env_postdeactivate_hook + typeset old_env + + # Call the local hook before the global so we can undo + # any settings made by the local postactivate first. + virtualenvwrapper_run_hook "pre_deactivate" + + env_postdeactivate_hook="$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/postdeactivate" + old_env=$(basename "$VIRTUAL_ENV") + + # Call the original function. + virtualenv_deactivate $1 + + virtualenvwrapper_run_hook "post_deactivate" "$old_env" + + if [ ! "$1" = "nondestructive" ] + then + # Remove this function + unset -f virtualenv_deactivate >/dev/null 2>&1 + unset -f deactivate >/dev/null 2>&1 + fi + + }' + + VIRTUALENVWRAPPER_PROJECT_CD=$cd_after_activate virtualenvwrapper_run_hook "post_activate" + + return 0 +} + + +# Prints the Python version string for the current interpreter. +function virtualenvwrapper_get_python_version { + # Uses the Python from the virtualenv rather than + # VIRTUALENVWRAPPER_PYTHON because we're trying to determine the + # version installed there so we can build up the path to the + # site-packages directory. + "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/python" -V 2>&1 | cut -f2 -d' ' | cut -f-2 -d. +} + +# Prints the path to the site-packages directory for the current environment. +function virtualenvwrapper_get_site_packages_dir { + "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/python" -c "import distutils; print(distutils.sysconfig.get_python_lib())" +} + +# Path management for packages outside of the virtual env. +# Based on a contribution from James Bennett and Jannis Leidel. +# +# add2virtualenv directory1 directory2 ... +# +# Adds the specified directories to the Python path for the +# currently-active virtualenv. This will be done by placing the +# directory names in a path file named +# "virtualenv_path_extensions.pth" inside the virtualenv's +# site-packages directory; if this file does not exist, it will be +# created first. +# +#:help:add2virtualenv: add directory to the import path +function add2virtualenv { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_active_environment || return 1 + + site_packages="`virtualenvwrapper_get_site_packages_dir`" + + if [ ! -d "${site_packages}" ] + then + echo "ERROR: currently-active virtualenv does not appear to have a site-packages directory" >&2 + return 1 + fi + + # Prefix with _ to ensure we are loaded as early as possible, + # and at least before easy_install.pth. + path_file="$site_packages/_virtualenv_path_extensions.pth" + + if [ "$*" = "" ] + then + echo "Usage: add2virtualenv dir [dir ...]" + if [ -f "$path_file" ] + then + echo + echo "Existing paths:" + cat "$path_file" | grep -v "^import" + fi + return 1 + fi + + remove=0 + if [ "$1" = "-d" ] + then + remove=1 + shift + fi + + if [ ! -f "$path_file" ] + then + echo "import sys; sys.__plen = len(sys.path)" > "$path_file" || return 1 + echo "import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)" >> "$path_file" || return 1 + fi + + for pydir in "$@" + do + absolute_path="$(virtualenvwrapper_absolutepath "$pydir")" + if [ "$absolute_path" != "$pydir" ] + then + echo "Warning: Converting \"$pydir\" to \"$absolute_path\"" 1>&2 + fi + + if [ $remove -eq 1 ] + then + sed -i.tmp "\:^$absolute_path$: d" "$path_file" + else + sed -i.tmp '1 a\ +'"$absolute_path"' +' "$path_file" + fi + rm -f "${path_file}.tmp" + done + return 0 +} + +# Does a ``cd`` to the site-packages directory of the currently-active +# virtualenv. +#:help:cdsitepackages: change to the site-packages directory +function cdsitepackages { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_active_environment || return 1 + typeset site_packages="`virtualenvwrapper_get_site_packages_dir`" + virtualenvwrapper_cd "$site_packages/$1" +} + +# Does a ``cd`` to the root of the currently-active virtualenv. +#:help:cdvirtualenv: change to the $VIRTUAL_ENV directory +function cdvirtualenv { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_active_environment || return 1 + virtualenvwrapper_cd "$VIRTUAL_ENV/$1" +} + +# Shows the content of the site-packages directory of the currently-active +# virtualenv +#:help:lssitepackages: list contents of the site-packages directory +function lssitepackages { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_active_environment || return 1 + typeset site_packages="`virtualenvwrapper_get_site_packages_dir`" + ls $@ "$site_packages" + + path_file="$site_packages/_virtualenv_path_extensions.pth" + if [ -f "$path_file" ] + then + echo + echo "_virtualenv_path_extensions.pth:" + cat "$path_file" + fi +} + +# Toggles the currently-active virtualenv between having and not having +# access to the global site-packages. +#:help:toggleglobalsitepackages: turn access to global site-packages on/off +function toggleglobalsitepackages { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_active_environment || return 1 + typeset no_global_site_packages_file="`virtualenvwrapper_get_site_packages_dir`/../no-global-site-packages.txt" + if [ -f $no_global_site_packages_file ]; then + rm $no_global_site_packages_file + [ "$1" = "-q" ] || echo "Enabled global site-packages" + else + touch $no_global_site_packages_file + [ "$1" = "-q" ] || echo "Disabled global site-packages" + fi +} + +#:help:cpvirtualenv: duplicate the named virtualenv to make a new one +function cpvirtualenv { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_virtualenv_clone || return 1 + + typeset src_name="$1" + typeset trg_name="$2" + typeset src + typeset trg + + # without a source there is nothing to do + if [ "$src_name" = "" ]; then + echo "Please provide a valid virtualenv to copy." + return 1 + else + # see if it's already in workon + if [ ! -e "$WORKON_HOME/$src_name" ]; then + # so it's a virtualenv we are importing + # make sure we have a full path + # and get the name + src="$(virtualenvwrapper_expandpath "$src_name")" + # final verification + if [ ! -e "$src" ]; then + echo "Please provide a valid virtualenv to copy." + return 1 + fi + src_name="$(basename "$src")" + else + src="$WORKON_HOME/$src_name" + fi + fi + + if [ "$trg_name" = "" ]; then + # target not given, assume + # same as source + trg="$WORKON_HOME/$src_name" + trg_name="$src_name" + else + trg="$WORKON_HOME/$trg_name" + fi + trg="$(virtualenvwrapper_expandpath "$trg")" + + # validate trg does not already exist + # catch copying virtualenv in workon home + # to workon home + if [ -e "$trg" ]; then + echo "$trg_name virtualenv already exists." + return 1 + fi + + echo "Copying $src_name as $trg_name..." + ( + [ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT + virtualenvwrapper_cd "$WORKON_HOME" && + "$VIRTUALENVWRAPPER_VIRTUALENV_CLONE" "$src" "$trg" + [ -d "$trg" ] && + virtualenvwrapper_run_hook "pre_cpvirtualenv" "$src" "$trg_name" && + virtualenvwrapper_run_hook "pre_mkvirtualenv" "$trg_name" + ) + typeset RC=$? + [ $RC -ne 0 ] && return $RC + + [ ! -d "$WORKON_HOME/$trg_name" ] && return 1 + + # Now activate the new environment + workon "$trg_name" + + virtualenvwrapper_run_hook "post_mkvirtualenv" + virtualenvwrapper_run_hook "post_cpvirtualenv" +} + +# +# virtualenvwrapper project functions +# + +# Verify that the PROJECT_HOME directory exists +function virtualenvwrapper_verify_project_home { + if [ -z "$PROJECT_HOME" ] + then + echo "ERROR: Set the PROJECT_HOME shell variable to the name of the directory where projects should be created." >&2 + return 1 + fi + if [ ! -d "$PROJECT_HOME" ] + then + [ "$1" != "-q" ] && echo "ERROR: Project directory '$PROJECT_HOME' does not exist. Create it or set PROJECT_HOME to an existing directory." >&2 + return 1 + fi + return 0 +} + +# Given a virtualenv directory and a project directory, +# set the virtualenv up to be associated with the +# project +#:help:setvirtualenvproject: associate a project directory with a virtualenv +function setvirtualenvproject { + typeset venv="$1" + typeset prj="$2" + if [ -z "$venv" ] + then + venv="$VIRTUAL_ENV" + fi + if [ -z "$prj" ] + then + prj="$(pwd)" + else + prj=$(virtualenvwrapper_absolutepath "${prj}") + fi + + # If what we were given isn't a directory, see if it is under + # $WORKON_HOME. + if [ ! -d "$venv" ] + then + venv="$WORKON_HOME/$venv" + fi + if [ ! -d "$venv" ] + then + echo "No virtualenv $(basename $venv)" 1>&2 + return 1 + fi + + # Make sure we have a valid project setting + if [ ! -d "$prj" ] + then + echo "Cannot associate virtualenv with \"$prj\", it is not a directory" 1>&2 + return 1 + fi + + echo "Setting project for $(basename $venv) to $prj" + echo "$prj" > "$venv/$VIRTUALENVWRAPPER_PROJECT_FILENAME" +} + +# Show help for mkproject +function virtualenvwrapper_mkproject_help { + echo "Usage: mkproject [-f|--force] [-t template] [virtualenv options] project_name" + echo + echo "-f, --force Create the virtualenv even if the project directory" + echo " already exists" + echo + echo "Multiple templates may be selected. They are applied in the order" + echo "specified on the command line." + echo + echo "mkvirtualenv help:" + echo + mkvirtualenv -h + echo + echo "Available project templates:" + echo + "$VIRTUALENVWRAPPER_PYTHON" -c 'from virtualenvwrapper.hook_loader import main; main()' -l project.template +} + +#:help:mkproject: create a new project directory and its associated virtualenv +function mkproject { + typeset -a in_args + typeset -a out_args + typeset -i i + typeset tst + typeset a + typeset t + typeset force + typeset templates + + in_args=( "$@" ) + force=0 + + if [ -n "$ZSH_VERSION" ] + then + i=1 + tst="-le" + else + i=0 + tst="-lt" + fi + while [ $i $tst $# ] + do + a="${in_args[$i]}" + case "$a" in + -h|--help) + virtualenvwrapper_mkproject_help; + return;; + -f|--force) + force=1;; + -t) + i=$(( $i + 1 )); + templates="$templates ${in_args[$i]}";; + *) + if [ ${#out_args} -gt 0 ] + then + out_args=( "${out_args[@]-}" "$a" ) + else + out_args=( "$a" ) + fi;; + esac + i=$(( $i + 1 )) + done + + set -- "${out_args[@]}" + + # echo "templates $templates" + # echo "remainder $@" + # return 0 + + eval "typeset envname=\$$#" + virtualenvwrapper_verify_project_home || return 1 + + if [ -d "$PROJECT_HOME/$envname" -a $force -eq 0 ] + then + echo "Project $envname already exists." >&2 + return 1 + fi + + mkvirtualenv "$@" || return 1 + + virtualenvwrapper_cd "$PROJECT_HOME" + + virtualenvwrapper_run_hook "project.pre_mkproject" $envname + + echo "Creating $PROJECT_HOME/$envname" + mkdir -p "$PROJECT_HOME/$envname" + setvirtualenvproject "$VIRTUAL_ENV" "$PROJECT_HOME/$envname" + + virtualenvwrapper_cd "$PROJECT_HOME/$envname" + + for t in $templates + do + echo + echo "Applying template $t" + # For some reason zsh insists on prefixing the template + # names with a space, so strip them out before passing + # the value to the hook loader. + virtualenvwrapper_run_hook --name $(echo $t | sed 's/^ //') "project.template" "$envname" "$PROJECT_HOME/$envname" + done + + virtualenvwrapper_run_hook "project.post_mkproject" +} + +#:help:cdproject: change directory to the active project +function cdproject { + virtualenvwrapper_verify_workon_home || return 1 + virtualenvwrapper_verify_active_environment || return 1 + if [ -f "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_PROJECT_FILENAME" ] + then + typeset project_dir="$(cat "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_PROJECT_FILENAME")" + if [ ! -z "$project_dir" ] + then + virtualenvwrapper_cd "$project_dir" + else + echo "Project directory $project_dir does not exist" 1>&2 + return 1 + fi + else + echo "No project set in $VIRTUAL_ENV/$VIRTUALENVWRAPPER_PROJECT_FILENAME" 1>&2 + return 1 + fi + return 0 +} + +# +# Temporary virtualenv +# +# Originally part of virtualenvwrapper.tmpenv plugin +# +#:help:mktmpenv: create a temporary virtualenv +function mktmpenv { + typeset tmpenvname + typeset RC + typeset -a in_args + typeset -a out_args + + in_args=( "$@" ) + + if [ -n "$ZSH_VERSION" ] + then + i=1 + tst="-le" + else + i=0 + tst="-lt" + fi + typeset cd_after_activate=$VIRTUALENVWRAPPER_WORKON_CD + while [ $i $tst $# ] + do + a="${in_args[$i]}" + case "$a" in + -n|--no-cd) + cd_after_activate=0;; + -c|--cd) + cd_after_activate=1;; + *) + if [ ${#out_args} -gt 0 ] + then + out_args=( "${out_args[@]-}" "$a" ) + else + out_args=( "$a" ) + fi;; + esac + i=$(( $i + 1 )) + done + + set -- "${out_args[@]}" + + # Generate a unique temporary name + tmpenvname=$("$VIRTUALENVWRAPPER_PYTHON" -c 'import uuid,sys; sys.stdout.write(uuid.uuid4()+"\n")' 2>/dev/null) + if [ -z "$tmpenvname" ] + then + # This python does not support uuid + tmpenvname=$("$VIRTUALENVWRAPPER_PYTHON" -c 'import random,sys; sys.stdout.write(hex(random.getrandbits(64))[2:-1]+"\n")' 2>/dev/null) + fi + tmpenvname="tmp-$tmpenvname" + + # Create the environment + mkvirtualenv "$@" "$tmpenvname" + RC=$? + if [ $RC -ne 0 ] + then + return $RC + fi + + # Change working directory + [ "$cd_after_activate" = "1" ] && cdvirtualenv + + # Create the tmpenv marker file + echo "This is a temporary environment. It will be deleted when you run 'deactivate'." | tee "$VIRTUAL_ENV/README.tmpenv" + + # Update the postdeactivate script + cat - >> "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/postdeactivate" < "$req_file" + if [ -n "$(cat "$req_file")" ] + then + echo "Uninstalling packages:" + cat "$req_file" + echo + pip uninstall -y $(cat "$req_file" | grep -v '^-f' | sed 's/>/=/g' | cut -f1 -d=) + else + echo "Nothing to remove." + fi + rm -f "$req_file" +} + +# +# Run a command in each virtualenv +# +#:help:allvirtualenv: run a command in all virtualenvs +function allvirtualenv { + virtualenvwrapper_verify_workon_home || return 1 + typeset d + + # The IFS default of breaking on whitespace causes issues if there + # are spaces in the env_name, so change it. + IFS='%' + virtualenvwrapper_show_workon_options | while read d + do + [ ! -d "$WORKON_HOME/$d" ] && continue + echo "$d" + echo "$d" | sed 's/./=/g' + # Activate the environment, but not with workon + # because we don't want to trigger any hooks. + (source "$WORKON_HOME/$d/$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate"; + virtualenvwrapper_cd "$VIRTUAL_ENV"; + "$@") + echo + done + unset IFS +} + +#:help:virtualenvwrapper: show this help message +function virtualenvwrapper { + cat <