Auto-virtualenv, now with more magic

Following yesterday’s post about Auto-virtualenv trick, today I managed to fix the issue of “auto-virtualenv loses the virtualenv if you go into a subdirectory of the directory with the .venv“.

The only change is the _venv_cd function. All the other alias still remain the same.

function _upwards_search {
    venv=""
    curdir=`pwd`

    while [[ `pwd` != '/' ]]; do
        if [ -f ./.venv ]; then
            venv=`cat ./.venv`
            break
        fi
        cd ..
    done

    cd $curdir
    echo $venv;
}

function _venv_cd { 
    if [ ! -f $PWD/$1 -a "$VIRTUAL_ENV." != "."  ]; then 
        deactivate
    fi;
    \cd $1
    venv=$(_upwards_search)
    if [ -n "$venv" ]; then 
        venv $venv 
    fi
}
alias cd=_venv_cd

Next step: remove all this stuff from my .bashrc, move to a single file which can be easily sourced inside your on .bashrc and drop it in a repository somewhere.

NOTE: Apparently, there is something wrong with the test for empty venv. Hold down your horses for a sec.

NOTE 2: Ok, problem solved. Also, the repository is now live at https://bitbucket.org/juliobiason/auto-virtualenv.

My magical auto-virtualenv trick (without VirtualenvWrapper)

One thing that pissed me off a few days ago was working in a Python project with some modules and switching between virtualenvs every time[1]. So I quickly hacked a solution.

But before going further, let me say that the solution is highly based on VirtualenvWrapper — to the point that I’m using the same environment variables. I just didn’t want to install a whole package for a simple feature.

And, without further ado…

The whole thing started with two alias added in my .bashrc, one to create a virtualenv and another to “active” the virtualenv. Today, they look like this:

export WORKON_HOME=$HOME/Venv
function venv { source $WORKON_HOME/$1/bin/activate; }
function mkenv { virtualenv $WORKON_HOME/$1; venv $1; echo "$1" > ./.venv; }

Nothing fancy here: I’m using WORKON_HOME exactly as it is used with VirtualenvWrapper, to point the directory where all virtualenvs sit. Then, to avoid going full path to activate them, I can simply use venv <virtualenv-name> to activate any virtualenv and, finally, to create virtualenvs in the right directory, I have mkenv <virtualenv-name>. Simple as that.

One thing you may notice is that I’m saving the virtualenv name in a hidden file inside the current directory, called .venv. This is what makes the magic happen.

Then, I have this script + alias:

function _venv_cd { 
if [ ! -f $PWD/$1 -a "$VIRTUAL_ENV." != "."  ]; then 
    deactivate
fi;
\cd $1; 
if [ -f ./.venv ]; then 
    venv `cat ./.venv`; 
fi }
alias cd=_venv_cd

This basically replaces cd with my function, which checks if the target directory have a .venv and, if it does, activate the virtualenv (so I don’t need to use venv anymore in normal situations); if there is no .venv but a virtualenv is active, deactivate it.

The only problema I still have is that going up inside the project/module won’t check if there is a .venv in any of the parent directories and, thus, would disable the virtualenv.

[1] It was just a matter of “keeping each with their own”. The whole project goes around creating modules for a web framework and each module must be capable of working standalone, without the others.