Vex
Run a command in the named virtualenv.
Install / Use
/learn @sashahart/VexREADME
Vex
Run a command in the named virtualenv.
vex is an alternative to virtualenv's source wherever/bin/activate
and deactivate, and virtualenvwrapper's workon, and also
virtualenv-burrito if you use that.
It works in a more elegant way, though it does less.
You might find it nicer to use.
And it works with non-bash shells.
How it works
vex just runs any command in a virtualenv, without modifying the current
shell environment.
To know why this is different, you have to understand a little about how
virtualenv normally works.
The normal way people use a virtualenv (other than virtualenvwrapper,
which does this for them) is to open a shell and source
a file called whatever/bin/activate.
Sourcing this shell script modifies the environment in the current shell.
It saves the old values and sets up a shell function named deactivate
which restores those old values. When you run deactivate it restores
its saved values.
This is also the way virtualenvwrapper's workon functions - after all, it
is a wrapper for virtualenv.
If you want to use a virtualenv inside a script you probably don't use
activate, though, you just run the python that is inside the virtualenv's
bin/ directory.
The way virtualenv's activate works isn't elegant, but it usually works fine. It's just specific to the shell, and sometimes gets a little fiddly, because of that decision to modify the current shell environment.
The principle of vex is much simpler, and it doesn't care what shell you
use, because it does not modify the current environment. It only sets up the
environment of the new process, and those environment settings just go away
when the process does. So no deactivate or restoration of environment is
necessary.
For example, if you run vex foo bash then that bash shell has the right
environment setup, but specifically "deactivating the virtualenv" is
unnecessary; the virtualenv "deactivates" when the process ends,
e.g. if you use exit or Ctrl-D as normal to leave bash. That's just
an example with bash, it works the same with anything.
(More examples in the Examples section.)
Examples
vex should work with most commands you can think of. Try it out.
vex foo bash
Launch a bash shell with virtualenv foo activated in it.
To deactivate, just exit the shell (using "exit" or Ctrl-D).
vex foo python
Launch a Python interpreter inside virtualenv foo.
vex foo which python
Verify the path to python from inside virtualenv foo.
vex foo pip freeze
See what's installed in virtualenv foo.
vex foo pip install ipython
Install ipython inside virtualenv foo.
vex foo ipython
Launch the ipython interpreter you have installed inside virtualenv foo.
vex foo
Launch your shell (as specified in SHELL or ~/.vexrc) in virtualenv foo
(this is like a direct replacement for 'workon').
vex foo cmd
On Windows, this launches a "DOS" shell using virtualenv foo.
(Try that with virtualenvwrapper!)
vex foo powershell
On Windows, this launches a PowerShell instance using virtualenv foo.
vex -mr ephemeral
In one command, this creates a virtualenv named ephemeral, then runs
a shell (since there was no argument), then after that shell exits, vex
removes the virtualenv named ephemeral.
If you break things by doing weird fun things with vex, you get to keep all the pieces left over.
How to install vex
You can just 'pip install vex,' but for convenience it's recommended to install vex with the user scheme as follows::
pip install --user vex
Though --user requires a little initial setup, this setup occurs once for all tools (see the next section), experienced Python developers have already done it, and there are two reasons for using it despite the small extra trouble.
First, it is not that convenient to use vex only from a virtualenv (though you can) because then you need to use some other technique to activate the virtualenv in which you have vex installed, in order to get access to it. That would usually be an unnecessary waste of time.
Second, it does not require root privileges and does not make any system-wide
messes. Installing Python libraries system-wide is something you should
normally leave to your OS package manager; you are probably doing yourself
a favor if you learn never to use sudo pip or sudo easy_install.
pip install --user mostly substitutes for the purposes which would
otherwise use sudo.
As an added benefit, you can use pip install --user on systems where you
are not allowed to make global modifications, or voluntarily refrain in order
to protect the global configuration.
You shouldn't normally have to separately install virtualenv; pip should drag that in if you don't already have it.
If you don't have pip, learn to install pip <http://pip.readthedocs.org/en/latest/installing.html>_.
To uninstall, just use pip uninstall vex -y.
First-time setup for Python beginners
The PATH problem
Though pip install --user is the way I recommend to install command-line
Python tools like vex, it won't necessarily give you immediate results if your
machine is not fully set up for Python development. The reason is that
pip install --user puts the script in a directory which isn't on the
default $PATH (Windows: %PATH%; PowerShell: $env:path).
For example, a Linux user named sam might see the script installed at::
/home/sam/.local/bin/vex
(the exact path may vary); typing 'vex' will result in a 'command not found', though inconveniently typing the absolute path will work. Similarly, a Windows user named sam might see the script installed at::
c:\users\sam\appdata\roaming\python\scripts\vex
and typing 'vex' will result in 'is not recognized' ... but again, giving an absolute path will work, it's just inconvenient. This is not that hard to solve, if you have it then PLEASE take a few minutes to walk through the next section.
The PATH solution
The solution is to adjust your PATH to include the appropriate directory.
For example, on Linux, sam might edit his shell config (e.g., ~/.profile) at the end, to read::
PATH=$PATH:/home/sam/.local/bin
while on Windows, sam might go into the 'Environment Variables' control panel (Control Panel > System > Advanced System Settings > Environment Variables) and in the upper box under 'User variables for sam', double-click 'PATH', and append the following to its current value (semicolon and all)::
;c:\users\sam\appdata\roaming\python\scripts
This will allow Windows to know what you mean when you type 'vex' (or the name
of any Python command-line tool which supports Windows and which you have
wisely installed with pip install --user).
Another PATH problem
Unless you already know better, if you need to adjust PATH for the benefit of your shell or installing some utility, you probably want to do that with changes in ~/.profile or equivalent (e.g. ~/.bash_profile, ~/.zprofile), which will take effect the next time you start a login shell. Otherwise, you might break a whole class of things that includes vex, in a way that cannot be reasonably automatically corrected.
If you understood that, then you don't have to read the rest of this section which is just for explanation. Here's the longer story:
Apparently some command-line tools have recommended in their docs that you stick things on the front of $PATH from ~/.bashrc (equivalently .zshrc, etc.) But this can cause problems for other utilities and scripts, if you do not understand the meaning of doing it this way instead of another way. The meaning of making these changes in files like ~/.bashrc instead of other files is this: "I want this directory to be searched for executables before ANY other directory, EVERY time. This is VERY important to me. It's my favorite directory to find executables in."
This might not normally be a problem for you. But it means that any other script or utility which puts another directory at the front of PATH is going to be overruled. For example, vex helpfully puts the bin/ directory of the relevant virtualenv at the head of PATH. It's the only reasonable way to achieve this effect. But if your ~/.bashrc says "SMASH PATH" then when you run bash under vex, vex will hand off a perfectly good virtualenv-activated environment for bash to use, and then after vex hands off bash will smash PATH as you instructed, and something else will have priority before your virtualenv stuff.
There's nothing bash or vex can do about this because, first, it's impossible to determine whether this was a mistake or something you literally intended, and not okay to squash the people who might literally intend this; and second, the only way that vex could override what you told bash to do would be for me to give you more shell-specific crap for you to source in ~/.bashrc that mutates the current environment, which is exactly what vex is getting away from. There is literally no way for vex to stop processes from messing up their own environments, the best it can do is hand off the right thing.
So instead of telling bash to do something that breaks vex, then wanting vex to do something which breaks everything else to override what you told bash to do, just don't make this change in ~/.bashrc unless you WANT other things to take precedence over your virtualenvs whenever you start bash.
A good solution is to use ~/.profile (or similar files your shell uses like ~/.bash_profile, ~/.zprofile) to make changes in PATH. Because this only runs at the creation of a login shell, e.g. when you log in to X, it is possible for vex and other utilities to make the right adjustment without something in ~/.bashrc squishing it immediately afterward. And when the subprocess goes away, there is no environmenta
