astral-sh / uv

An extremely fast Python package installer and resolver, written in Rust.
https://astral.sh/
Apache License 2.0
15.16k stars 437 forks source link

Create stub for `uv` in virtual environments #1632

Open zanieb opened 5 months ago

zanieb commented 5 months ago

It seems like we should probably stub uv into the environment by default so that you can use python -m uv. I'm not exactly sure what that would look like.

Originally posted by @zanieb in https://github.com/astral-sh/uv/issues/1598#issuecomment-1950259889

SnoopJ commented 4 months ago

+1 to the idea of a stub, it seems like a fairly natural solution to #1625.

It seems to me that the mechanism would be to include a symlink to or copy of uv in the venv (gated by a flag perhaps?) and inspect argv[0] when doing venv detection. I believe the analogous CPython behavior that allows /path/to/venv/bin/python3 to Just Work™ is scanning for a nearby pyvenv.cfg and it seems like uv could probably use the same process as an early step in the venv detection logic.

zanieb commented 4 months ago

We added a similar scan for the pyvenv.cfg in #1504

henryiii commented 4 months ago

(pyvenv.cfg, you mean?)

zanieb commented 4 months ago

Thanks :) fixed

wpk-nist-gov commented 4 months ago

Playing around, I think there's workable solution (with a caveat) right now. I did the following:

# 1. create environment using global uv
$ uv venv .venv

# 2. install uv in the venv
$ uv pip install uv

# 3. hack.  Remove uv executable, but leaves python uv interface
$ rm .venv/bin/uv

# 4. This still works. (find_uv_bin() finds my globally installed uv)
$ cd somewhere/else
$ full/path/to/.venv/bin/python -m uv pip freeze
uv==0.1.8

Basically, the code in python/uv is your stub. Maybe just spin off a package python-uv which could be (optionally?) included when creating a venv.

However, regardless of step 3 (the hack), using the full path to the python doesn't work if a virtualenv is also activated. For example (continuing from above):

$ uv venv .venv2
$ source .venv2/bin/activate

# Now try to install to .venv using path...
$ .venv/bin/python -m uv pip install typing-extensions

# This installs into .venv2!
$ uv pip freeze
typing-extensions==4.9.0

# not in .venv
$ source .venv/bin/activate
$ uv pip freeze
uv==0.1.8

I'm pretty sure this is not the intended behavior. I'm guessing a solution to #1396 will allow this to be fixed. For example, if an option --python-executable is available, then instead of searching for, and setting VIRTUAL_ENV variable here, you could simply pass f"--python-executable={sys.executable}".

I figured it made sense to add this to this issue. Please let me know if I should start a new issue instead.

Thank you to all the developers for this awesome package!