Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a --python flag to allow installation into arbitrary Python interpreters #2000

Merged
merged 6 commits into from
Feb 28, 2024

Conversation

charliermarsh
Copy link
Member

@charliermarsh charliermarsh commented Feb 27, 2024

Summary

This PR adds a --python flag that allows users to provide a specific Python interpreter into which uv should install packages. This would replace the VIRTUAL_ENV= workaround that folks have been using to install into arbitrary, system environments, while also actually being correct for installing into non-virtual environments, where the bin and site-packages paths can differ.

The approach taken here is to use sysconfig.get_paths() to get the correct paths from the interpreter, and then use those for determining the bin and site-packages directories, rather than constructing them based on hard-coded expectations for each platform.

Closes #1396.

Closes #1779.

Closes #1988.

Test Plan

  • Verified that, on my Windows machine, I was able to install requests into a global environment with: cargo run pip install requests --python 'C:\\Users\\crmarsh\\AppData\\Local\\Programs\\Python\\Python3.12\\python.exe, then python and import requests.
  • Verified that, on macOS, I was able to install requests into a global environment installed via Homebrew with: cargo run pip install requests --python $(which python3.8).

@charliermarsh charliermarsh marked this pull request as draft February 27, 2024 01:48
@charliermarsh charliermarsh added bug Something isn't working enhancement New feature or request labels Feb 27, 2024
@charliermarsh charliermarsh marked this pull request as ready for review February 27, 2024 01:56
@charliermarsh charliermarsh force-pushed the charlie/py branch 2 times, most recently from 5c527c8 to 02698d2 Compare February 27, 2024 01:59
@charliermarsh charliermarsh marked this pull request as draft February 27, 2024 02:03
@charliermarsh
Copy link
Member Author

Marking as draft, one important thing to fix here when creating environments for isolated builds (hence test failures). I see the problem.

crates/uv/src/main.rs Outdated Show resolved Hide resolved
@charliermarsh charliermarsh force-pushed the charlie/py branch 8 times, most recently from 654bc4c to 210ac9d Compare February 27, 2024 05:17
@charliermarsh charliermarsh marked this pull request as ready for review February 27, 2024 05:18
platlib: platform.venv_site_packages(&venv_root, self.python_tuple()),
scripts: platform.venv_scripts_dir(&venv_root),
data: platform.venv_data_dir(&venv_root),
include: self.sysconfig.include,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\cc @konstin - I think include is the same in a venv as not...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd, the docs make it look as if should also change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which docs? Link please!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.python.org/3/library/sysconfig.html#installation-paths

But i don't disagree, include is also an outlier for me:

Paths: 
        data = "/home/konsti/projects/uv/.venv"
        include = "/home/konsti/.pyenv/versions/3.10.13/include/python3.10"
        platinclude = "/home/konsti/.pyenv/versions/3.10.13/include/python3.10"
        platlib = "/home/konsti/projects/uv/.venv/lib/python3.10/site-packages"
        platstdlib = "/home/konsti/projects/uv/.venv/lib/python3.10"
        purelib = "/home/konsti/projects/uv/.venv/lib/python3.10/site-packages"
        scripts = "/home/konsti/projects/uv/.venv/bin"
        stdlib = "/home/konsti/.pyenv/versions/3.10.13/lib/python3.10"

Same with the apt installed python as base:

Paths: 
        data = "/home/konsti/projects/uv/.venv"
        include = "/usr/include/python3.11"
        platinclude = "/usr/include/python3.11"
        platlib = "/home/konsti/projects/uv/.venv/lib/python3.11/site-packages"
        platstdlib = "/home/konsti/projects/uv/.venv/lib/python3.11"
        purelib = "/home/konsti/projects/uv/.venv/lib/python3.11/site-packages"
        scripts = "/home/konsti/projects/uv/.venv/bin"
        stdlib = "/usr/lib/python3.11"

Copy link
Contributor

@samypr100 samypr100 Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on the build headers I think? There was an issue a while ago with deadsnakes changing them to /usr/local/include vs canonical /usr/include the headers had deadsnakes/issues#237

@charliermarsh charliermarsh force-pushed the charlie/py branch 6 times, most recently from 99d1064 to af8e92f Compare February 27, 2024 05:39
@charliermarsh charliermarsh force-pushed the charlie/py branch 14 times, most recently from 7343e80 to 91bff57 Compare February 28, 2024 02:02
@charliermarsh
Copy link
Member Author

Gonna put up some follow-up PRs. Merging for now.

@charliermarsh charliermarsh merged commit 1017514 into main Feb 28, 2024
7 checks passed
@charliermarsh charliermarsh deleted the charlie/py branch February 28, 2024 02:10
@charliermarsh
Copy link
Member Author

518e74b contains a test script and a GitHub Actions workflow to install on system python on macOS and Linux. (I tried to get it to work on Windows, but I wasted too much time trying to get GitHub Actions to work.)

charliermarsh added a commit that referenced this pull request Mar 10, 2024
## Summary

In #2000, I shipped a regression whereby we stopped writing relative
paths for scripts within `data` directories. The net effect here is that
we aren't _uninstalling_ binaries in all cases. (This does _not_ apply
to entrypoints, only scripts in `data` directories.)

Closes #2330.

## Test Plan

Most Python packages ship entrypoints, not binaries, so I don't know how
to test this cheaply. But I did test it locally by verifying that `uv`
is now removed from the `bin` directory after an uninstall.
@wimglenn
Copy link
Contributor

wimglenn commented Mar 18, 2024

Hi @charliermarsh , this is a very useful feature, thanks! I have a couple of questions on usage.

Q1: is it expected that using a relative path is not working (edit: on macOS - seems to work fine on Linux)?

$ uv pip install --dry-run --python .venv/bin/python six 
error: Failed to query Python interpreter at `.venv/bin/python`
  Caused by: No such file or directory (os error 2)

An absolute path to the same python exe is working:

$ pwd
/Users/wim
$ uv pip install --dry-run --python /Users/wim/.venv/bin/python six
Audited 1 package in 1ms
Would make no changes

edit: I can't reproduce this on 0.1.22. I checked again after downgrading back to 0.1.21 (where I originally saw the issue) and could no longer reproduce it there either... 🤷

Q2: how do you actually use this feature with uv pip compile? I couldn't figure it out:

$ cat reqs.in                                                            
psycopg2-binary; implementation_name == 'cpython'
psycopg2; implementation_name != 'cpython'
$ uv pip compile reqs.in --python-version /tmp/pypy/.venv/bin/python
error: invalid value '/tmp/pypy/.venv/bin/python' for '--python-version <PYTHON_VERSION>': expected version to start with a number, but no leading ASCII digits were found

For more information, try '--help'.
$ uv pip compile reqs.in --python /tmp/pypy/.venv/bin/python        
error: unexpected argument '--python' found

  tip: a similar argument exists: '--python-version'

Usage: uv pip compile --python-version <PYTHON_VERSION> <SRC_FILE>...

For more information, try '--help'.

It works with uv pip install as expected.

$ uv pip install --dry-run --python /tmp/cpython/.venv/bin/python -r reqs.in
Resolved 1 package in 3ms
Would download 1 package
Would install 1 package
 + psycopg2-binary==2.9.9
$ uv pip install --dry-run --python /tmp/pypy/.venv/bin/python -r reqs.in   
Resolved 1 package in 3ms
Would download 1 package
Would install 1 package
 + psycopg2==2.9.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
7 participants