Skip to main content
  1. Dispatches/

TIL - Automatically Set Your virtualenv

·321 words·2 mins
TIL Python Poetry Hatch Venv Direnv
Daniel Andrlik
Author
Daniel Andrlik
Daniel Andrlik lives in the suburbs of Philadelphia. By day he manages product teams. The rest of the time he is a podcast host and producer, writer of speculative fiction, a rabid reader, and a programmer.

I’m a big fan of using direnv to set project-specific env variables. And at one point I was using it to automatically activate my poetry virtualenv whenever I entered the directory per this function. However, lately I’ve also been playing with hatch or just calling python -m venv directly, so I wanted to work out a way to have a unified approach.

This is what I came up with, and I’m sure there is a more elegant way to do this, but it works, and that’s what matters for now.

First, you add the following functions to ~/.config/direnv/direnvrc:

layout_env() {
  if [[ ! -f pyproject.toml ]]; then
    log_error 'No pyproject.toml found. Cannot determine appropriate env to activate.'
    exit 2
  fi

  grep -q poetry pyproject.toml
  retVal=$?
  if [ $retVal -ne 0 ]; then
     grep -q hatch pyproject.toml
     hatchVal=$?
     if [ $hatchVal -ne 0 ]; then
       layout_venv
     else
       layout_hatch
     fi
  else
    layout_poetry
  fi

}
layout_poetry() {
  if [[ ! -f pyproject.toml ]]; then
    log_error 'No pyproject.toml found.  Use `poetry new` or `poetry init` to create one first.'
    exit 2
  fi

  local VENV=$(dirname $(poetry run which python))
  export VIRTUAL_ENV=$(echo "$VENV" | rev | cut -d'/' -f2- | rev)
  export POETRY_ACTIVE=1
  PATH_add "$VENV"
}

layout_hatch() {
  if [[ ! -f pyproject.toml ]]; then
    log_error 'No pyproject.toml found! Create one first using your preferred tools.'
    exit 2
  fi
  
  local VENV=$(dirname $(hatch -q run which python))
  export VIRTUAL_ENV=$(echo "$VENV" | rev | cut -d'/' -f2- | rev)
  export HATCH_ENV_ACTIVE="default"
  PATH_add "$VENV"
}

layout_venv() {
  if [[ ! -d .venv ]]; then
    log_error 'No local virtual env exists yet. Create one using python -m venv --prompt . .venv'
    exit 2
  fi

  local VENV=".venv/bin"
  export VIRTUAL_ENV=$(echo "$VENV" | rev | cut -d'/' -f2- | rev)
  PATH_add "$VENV"
}

Then in any project directory’s .envrc add a single line:

layout_env

After making your changes, run direnv allow to approve the modified file for use and you’ll be good to go!

Related

TIL - Getting asdf Python with tkinter working on a M2 Mac
·312 words·2 mins
TIL Macos Python Homebrew Tkinter
This week I wanted to play around with tkinter a bit. But this proved to be difficult on my M2 Mac. I use asdf to manage various runtime versions, so first I checked to see if it was already working with my existing Python installation using the built in test method.
TIL - Importing annotations from future for concise Python typing
·110 words·1 min
TIL Python
Python 3.10 introduced several improvements for type hints, including a much more concise Union operator. This means that instead of using: def square(number: Union[int, float]) -> Union[int, float]: return number ** 2 You can instead write this:
TIL - Running make apidocs for Read the Docs
·196 words·1 min
TIL Python
I was hacking on my quote service the other day, and notice that Read the Docs wasn’t building my module level documentation, which meant that anyone that wanted to look at said modules in more detail was getting a 404 error.