berdario/pew — pull request #36 by rraval (2014-09-07 17:31:02+00:00)
Title: Add support for environment hooks

Hi, I have a use case for injecting environment variables into the `workon` environment and would like to take a step forward in addressing #3.

In my case, I'm trying to get `npm` dependencies to work nicely in `pew` virtual environments. There's 2 things that need to happen here:

1. Installing `npm` dependencies inside the container, which is easily accomplished by `npm install -g --prefix=$VIRTUAL_ENV`.

2. Automatically modifying `$NODE_PATH` inside the `workon` environment. Ideally, the new value would be `$VIRTUAL_ENV/lib/node_modules:$NODE_PATH`.

To get this to work, I've modified the `inve` script to respect an optional INI file: `$VIRTUAL_ENV/.inve.ini`. There's precedent for that convention in the form of the `.project` file.

Right now, `inve` only respects the `env` section in the INI file, which defines a set of environment variables to be injected. The file format is fairly extensible, and can be used to define other hooks (and even scripts to run) in the future. Sample `$VIRTUAL_ENV/.inve.ini`:

```
# INI files support comments
[env]
# both $foo and ${foo} syntax is supported
NODE_PATH = $VIRTUAL_ENV/lib/node_modules:${NODE_PATH}
# can inject new environment variables as well
AWS_ACCESS_KEY_ID = something
```

Current Implementation Details:

- I used `RawConfigParser` and `string.Template` interpolation instead of using `ConfigParser` builtin interpolation. The builtin interpolation has tons of quirks:

- Using builtin interpolation requires setting `os.environ` as the `defaults`. Iterating over the keys in the `env` section includes the `defaults` as well, even though the INI file makes no mention of them.

- The interpolators allow referring to other variables defined in the section. This means something like `NODE_PATH = ${VIRTUAL_ENV}/lib/node_modules:${NODE_PATH}` hits the recursion depth limit.

- Using `string.Template.safe_substitute` means that if a variable is not defined in the host environment, it is passed along in its original form. Ideally it would be replaced by an empty string to match shell semantics.