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 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 - Podcast hosts serve unreliable art mime types
·362 words·2 mins
TIL Podcasting Python Django Mime Types Rss
I’ve been toying with a small Django project that can be given a list of podcast feeds, and then regularly checks those feeds and updates some interesting metrics. Initially, I wanted to see how many comparable podcasts to my own made use of various RSS namespace elements, and also to pull some aggregate statistics around release frequency, episode length, etc…
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: