Open bulletmark opened 4 months ago
This was changed in https://github.com/astral-sh/uv/pull/966 to fix something else. Maybe @konstin knows if we actually need to resolve symlinks there, or if we just needed to convert to an absolute path or something.
We need to resolve symlinks for the caching, but i think we can use the resolved version for caching and the original version for the venv. I think we should special case venv-from-venv cases, otherwise the new venv will break when deleting the venv it was created from.
This is related to a few other issues, but note that virtualenv (on main
) also resolves symlinks like this.
For the future: similar to https://github.com/astral-sh/uv/issues/1640. Need to decide if we want to preserve symlinks in these various cases.
$ ~/.pyenv/versions/3.12/bin/python -m venv venv $ ls -l venv/bin/python lrwxrwxrwx - mark mark 21 Feb 12:36 venv/bin/python -> /home/mark/.pyenv/versions/3.12/bin/python* $ uv venv -p ~/.pyenv/versions/3.12/bin/python uvenv Using Python 3.12.2 interpreter at /home/mark/.pyenv/versions/3.12.2/bin/python3.12 Creating virtualenv at: uvenv Activate with: source uvenv/bin/activate $ ls -l uvenv/bin/python lrwxrwxrwx - mark mark 21 Feb 12:42 uvenv/bin/python -> /home/mark/.pyenv/versions/3.12.2/bin/python3.12
uv venv
but without passing --python
, uv's report states that uv venv
didn't resolve versions/3.12
to versions/3.12.2
:+ type python
python is /home/ganden/.pyenv/shims/python
+ python -c 'import sys; print(sys.executable)'
/home/ganden/.pyenv/versions/3.12/bin/python
+ readlink -f /home/ganden/.pyenv/versions/3.12/bin/python
/home/ganden/.pyenv/versions/3.12.2/bin/python3.12
+ : '^^^ the above resolution is due to the symlinks'
+ readlink /home/ganden/.pyenv/versions/3.12 /home/ganden/.pyenv/versions/3.12.2/bin/python
3.12.2
python3.12
+ :
+ uv venv
Using Python 3.12.2 interpreter at: /home/ganden/.pyenv/versions/3.12/bin/python3
Creating virtualenv at: .venv
Activate with: source .venv/bin/activate
+ : '^^^ uv reports using versions/3.12'
+ readlink .venv/bin/python
/home/ganden/.pyenv/versions/3.12.2/bin/python3.12
+ : '^^^ but actually uses versions/3.12.2'
I'm not totally sure what we're supposed to do when creating a virtualenv from within a virtualenv.
python -m venv
seems to use the existing virtualenv as the base:
❯ cat .nested-venv/pyvenv.cfg
home = /Users/crmarsh/workspace/uv/.venv/bin
include-system-site-packages = false
version = 3.8.18
However, virtualenv
does not seem to do this.
I this is how it's supposed to work, then what's the proposed workflow to upgrade, say, 3.9.18 to 3.9.19 and repair all my venvs that I created to use 3.9? freeze, rm, venv, sync?
Yeah, that's technically the correct thing to do, because you could have packages in your environment that are compatible with the previous but not the updated patch version; or packages whose dependencies differ by patch version. Both of those things are allowed in Python / per the spec though are very rare in practice when talking about patch versions.
(We may change our behavior here eventually to preserve the symlink; undecided right now.)
Hmmm, right. Then maybe the correct thing would be the addition of some venv rebuild
command, the way pipx
has the reinstall
and reinstall-all
.
As far as creating virtualenvs from within virtualenvs goes, the python -m venv
behaviour is questionable, since it won't work in the general case (if you want to layer virtual environments together in a way that actually works, you currently need to add a sitecustomize.py
file to the upper layers to get everything resolving correctly at runtime, simply referencing a venv layout as your "base Python" environment may not work reliably because some of the files can end up in the wrong relative locations, especially when Python has been compiled as a shared library with a wrapper executable). (I haven't gone looking to see if there's an open bug report about this though)
Outside the specific scenario of being passed a virtual environment symlink, using a provided symlink as given rather than resolving it feels like it would be more correct, though.
Interesting. Perhaps what we want then, is: resolve the symlink if it's a virtualenv, preserve it if not?
This describes an issue where
uv venv
operates in an incompatible and less-optimal way compared topython -m venv
.I use
pyenv
to install multiple python versions etc. I don't use the pyenv shims and just specify the pyenv python executable when building my venv's. So I have symlinks to the latest minor versions, i.e:Now witness the difference in the created symlinks to the interpreter when making a venv using these links:
I.e.
python -m venv
creates a3.12
link as I specified butuv venv
dereferences that3.12
path and creates a final link to3.12.2
.This is undesirable because it means when
3.12
gets it's next compatible maintenance release, e.g.3.12.3
and the pyenv link is updated, then thepython -m venv
venv will automatically use that3.12.3
update but theuv venv
uvenv will continue to use the older release and requires the venv to be rebuilt against the new version.So is there any reason
uv venv
needs to resolve that symlink? It seems better to do whatpython -m venv
does and just use it directly.