direnv / direnv

unclutter your .profile
http://direnv.net
MIT License
12.54k stars 639 forks source link

official support for uv #1250

Open dbrtly opened 8 months ago

dbrtly commented 8 months ago

Is your feature request related to a problem? Please describe. I'd like direnv to layout python using astral-sh/uv in an elegant way.

Describe the solution you'd like

While this works, it breaks the prompt somehow. By default, without using direnv, uv uses the name of the base directory for the venv prompt.


realpath() {
    [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
layout_python-uv() {
    local python=${1:-python3}
    [[ $# -gt 0 ]] && shift
    unset PYTHONHOME
    if [[ -n $VIRTUAL_ENV ]]; then
        VIRTUAL_ENV=$(realpath "${VIRTUAL_ENV}")
    else
        local python_version
        python_version=$("$python" -c "import platform; print(platform.python_version())")
        if [[ -z $python_version ]]; then
            log_error "Could not detect Python version"
            return 1
        fi
        VIRTUAL_ENV=$PWD/.direnv/python-venv-$python_version
    fi
    export VIRTUAL_ENV
    if [[ ! -d $VIRTUAL_ENV ]]; then
        log_status "no venv found; creating $VIRTUAL_ENV"
        uv venv "$VIRTUAL_ENV" 
    fi

    PATH="${VIRTUAL_ENV}/bin:${PATH}"
    export PATH
    source "${VIRTUAL_ENV}/bin/activate"
}

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

Additional context Add any other context or screenshots about the feature request here.

inklesspen commented 3 months ago

I've been using this in my .config/direnv/lib/python_uv.sh for a while now; it seems to work well:

layout_python_uv() {
  local python=${1:-python}
  [[ $# -gt 0 ]] && shift
  unset PYTHONHOME
  local python_version=$($python -V | cut -w -f 2 | cut -d . -f 1-2)
  if [[ -z $python_version ]]; then
      log_error "Could not find python's version"
      return 1
  fi

  if [[ -n "${VIRTUAL_ENV:-}" ]]; then
      local REPLY
      realpath.absolute "$VIRTUAL_ENV"
      VIRTUAL_ENV=$REPLY
  else
      VIRTUAL_ENV=$(direnv_layout_dir)/python-$python_version
  fi
  if [[ ! -d $VIRTUAL_ENV ]]; then
      uv venv -p $python "$@" "$VIRTUAL_ENV"
  fi
  export VIRTUAL_ENV
  PATH_add "$VIRTUAL_ENV/bin"
}
pjz commented 2 months ago

Couple of changes to run on linux:


layout_python_uv() {
  local python=${1:-python}
  [[ $# -gt 0 ]] && shift
  unset PYTHONHOME
  local python_path=$(uv python find $python)
  local python_version=$($python_path -V | cut -d' ' -f 2 | cut -d . -f 1-2)
  if [[ -z $python_version ]]; then
      log_error "Could not find python's version"
      return 1
  fi

  if [[ -n "${VIRTUAL_ENV:-}" ]]; then
      local REPLY
      realpath.absolute "$VIRTUAL_ENV"
      VIRTUAL_ENV=$REPLY
  else
      VIRTUAL_ENV=$(direnv_layout_dir)/python-$python_version
  fi
  export UV_PROJECT_ENVIRONMENT=$VIRTUAL_ENV
  if [[ ! -d $VIRTUAL_ENV ]]; then
      uv venv -p $python "$@" "$VIRTUAL_ENV"
  fi
  export VIRTUAL_ENV
  PATH_add "$VIRTUAL_ENV/bin"
}
  1. I dunno what version of cut supports -w, but mine doesn't. Replaced with -d' '.
  2. make a python_path tempvar so the version specified doesn't have to be on the $PATH as long as uv python knows where to find it.
  3. export UV_PROJECT_ENVIRONMENT so that running uv alone with use the correct venv.
zimbatm commented 2 months ago

Would be good to add it to the wiki.

If you believe the integration to be stable, sending a PR to add it to the stdlib would be fine as well.

thernstig commented 1 month ago

It has been added to the wiki by @doolio and @sephib and @consoull it seems.

(Though https://github.com/direnv/direnv/wiki was not updated to add it to the list there).

But would be great to add this to stdlib as I think it is quite obvious uv will take over more and more workflows.