Not long ago I've switched from virtualenvwrapper to self-made solution based on this idea by datagrok. It works pretty well for me and I'd like to share it here.
The idea is to have a root directory ($HOME/_dev
in my case)
for all projects and to have shell helper to easily jump into any project
and to automatically activate it's virtualenv if it exists.
Here is how it looks in bash
:
[local] [egorov@asus 11:33:19]:~ $ dev blog Virtual environment found in /home/egorov/_dev/blog/env, activated. (blog) [local] [egorov@asus 11:34:31]:~/_dev/blog git:master= $
Besides just jumping into directory I wanted to have tab
autocompletion and
easy way to create new projects home
directory:
# autocompletion [local] [egorov@asus 11:43:01]:~ $ dev service- # tab hitted twice service-account service-feedback service-products service-workers # new project home [local] [egorov@asus 11:52:08]:~ $ dev rogue mkdir: created directory '/home/egorov/_dev/rogue' No virtual environment found, skipping activate. [local] [egorov@asus 11:52:25]:~/_dev/rogue $
So, here are bash
helpers which should be placed somewhere inside ~/.bashrc
or ~/.bash_profile
(mine lives there).
_dev
function depends on inve
shell script which must be available
in PATH
(I have $HOME/bin
in PATH
for this and inve
lives there).
# dev DEV=${HOME}/_dev # home for all projects _dev() { local p=${DEV}/$1 [ ! -d $p ] && mkdir $p cd $p inve # binary file to be accessible in PATH return 0 } _dev_complete() { local cur prev opts local p=${DEV} [ ! -d $p ] && `which mkdir` $p COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts=`cd $p && find -L . -maxdepth 1 -type d | sed 's|[\./]||g'` COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) } alias dev=_dev complete -F _dev_complete dev
inve
executable content:
#!/usr/bin/env bash # tuned idea from: https://gist.github.com/datagrok/2199506 # # inve # # For use with Ian Bicking's virtualenv tool. Attempts to find the root of # a virtual environment and activate it in subshell. # First, locate the root of the current virtualenv cwd=$PWD export DEV_ROOT=$cwd while [ "$PWD" != "/" ]; do # Stop here if this the root of a virtualenv # will look for virtualenv in `current dir` or in `env` subdirectory if [ \ -x bin/python \ -a -e lib/python*/site.py \ -a -e include/python*/Python.h ] then export VIRTUAL_ENV="$PWD" break elif [ \ -x env/bin/python \ -a -e env/lib/python*/site.py \ -a -e env/include/python*/Python.h ] then export VIRTUAL_ENV="$PWD/env" break fi cd .. done if [ "$PWD" = "/" ]; then export PATH="$cwd/node_modules/.bin:$PATH" echo "No virtual environment found, skipping activate." >&2 cd $cwd else # Activate export PATH="$VIRTUAL_ENV/bin:$cwd/node_modules/.bin:$PATH" unset PYTHONHOME echo "Virtual environment found in ${VIRTUAL_ENV}, activated." >&2 fi exec "$SHELL"
inve
script looks for virtualenv
in env
subdirectory or attempts to
find it somewhere upper in the filesystem tree. It modifies PATH
prepending
$VIRTUALENV/bin
and node_modules/.bin
directories and starts new shell.
I like the idea of starting a new subshell in order to activate virtualenv
as
this way we can be sure there will be no problems with PATH
within shell and
it's pretty safe to exit this subshell and have parent shell clean as it should
be.
To easily navigate to some directories within activated virtualenv
I have a
couple of bash aliases defined:
alias cdsrc='cd ${VIRTUAL_ENV}/src' alias cdsitepackages='cd ${VIRTUAL_ENV}/lib/python*/site-packages/' alias cdproject='cd ${DEV_ROOT:-VIRTUAL_ENV}; if [ `basename ${PWD}` = "env" ]; then cd ..; fi'
This approach allows me to have virtual environments using python2
or
python3
under single root directory and to have single tool to jump into
project be it python2
, python3
or even nodejs
project.
Everything works pretty good for me.