Add venv hooks for running custom scripts on activate/deactivate

I would like to see hooks added to the activate and deactivate venv scripts that allow for running custom script(s) when using a venv. These hooks would allow for running user-specified extras, such as setting/unsetting environment variables, which would be useful for some Python venvs.
By adding hooks that call a user defined script, the onus is on the developers of those custom scripts to maintain functionality rather than stdlib which prevents tech debt for stdlib maintainers.

One thing I would consider is the ability to configure a custom_script_path in the same way as other parameters are now. It would be used as follows: If not None, it should specify a directory, and the files in there would be copied to the target venv after the standard scripts are copied (possibly overwriting ones already there, such as “activate”), with the same variable substitutions that are currently done.
This approach allows for other things than just custom environment variable setting, and so it seems a more generic solution to the issue of customisability. While it involves the developers who require such functionality to maintain those scripts, it seems fair to place the onus on them, and not on stdlib maintainers.

https://github.com/python/cpython/issues/81530#issuecomment-1093827399

This comes from the related idea https://github.com/python/cpython/issues/81530 but I am breaking this out to a new discussion as the original Issue scope was only environment variables.

One use that I would have for this functionality relates to git hooks. I work on a monorepo which is primarily written in TypeScript so uses Husky git hooks, but we have an Python client within a subdirectory which uses pre-commit git hooks for the Python code. You can only have one of Husky or pre-commit as the git hook at any time, so a venv hook would allow for programmatic toggling between the relevant git hook depending on if the venv was activated or not. This functionality is something that environment variables alone would not be able to achieve, so a custom script would be much more useful, as well as including the functionality to set/unset env vars.

In the above case, my activate BASH script would look like:

_OLD_GIT_CORE_HOOKSPATH=$(git config --show-scope core.hooksPath)
if [ -n "${_OLD_GIT_CORE_HOOKSPATH}" ]; then
    git config --unset-all core.hooksPath
fi

and my deactivate BASH script would be:

if [ -n "${_OLD_GIT_CORE_HOOKSPATH}" ]; then
    git config "--$(echo "${_OLD_GIT_CORE_HOOKSPATH}" | cut -f1)" core.hooksPath "$(echo "${_OLD_GIT_CORE_HOOKSPATH}" | cut -f2)"
    unset _OLD_GIT_CORE_HOOKSPATH
fi

Why not write a script that adds what you want by wrapping the venv activate?
You can do that today without changes to python.

Also activate is optional, personall I never activate a venv.
I run the python inside it directly.

2 Likes

Why not write a script that adds what you want by wrapping the venv activate?

This is certainly a valid approach. The reason why I’d prefer the suggested standardised approach is because there already are hooks for customising other behaviour. It’s possible to subclass EnvBuilder and override setup_scripts, for example, to update the venv with extra functionality, so extending activate/deactivate is in-keeping with other related hooks.

That’s for apps that use venv. It’s a different sort of customisation then what you are asking for. But the docs say you can customise the activate scripts from EnvBuilder. So you could do that.

1 Like