-
Notifications
You must be signed in to change notification settings - Fork 860
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
Virtual environments break on Homebrew upgrades due to using a Cellar
link
#1640
Comments
Do you by any chance have a link to the relevant PRs or issues in |
I don't, but FWIW |
Hmm yeah, we're using ❯ python3.8
Python 3.8.18 (default, Aug 24 2023, 19:48:18)
[Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys._base_executable
'/opt/homebrew/bin/python3.8' |
The problem is that we're calling |
We may want something like...
That's closer to virtualenv: # if we're not in a virtual environment, this is already a system python, so return the original executable
# note we must choose the original and not the pure executable as shim scripts might throw us off
return self.original_executable |
I don't know if it's quite relevant but they just fixed a bug by storing the resolved absolute path in the metadata file that is generated for virtual environments: pypa/virtualenv#2682 Also, I know all of you are basically Rust experts, but in case I am reading the source correctly please never ever use canonicalize directly as it is literally (I'm not joking) broken on Windows and will cause all of us bugs and unexpected behavior. Please don't use it. Instead, it's common to use the dunce crate or the normpath crate when you don't want to resolve symlinks. See even Armin talking about it. |
Haha. We do use |
I'd actually expect that virtualenv change to break this case, if I'm reading it correctly:
So now |
I don't own a macOS to test that for you unfortunately but that sounds right. |
On |
\cc @gaborbernat -- it seems like |
I do not have a good answer here. 😱 |
Agreed, i think this is better, i'm also thinking about the use case where somebody might have intentional redirects for their python setup. For the Cellar issue, note that technically different patch versions aren't compatible from a packaging perspective, technically a project could require |
It would be really nice if this was solved somehow, all my uv venvs break after a minor python update... Besides the difference in the picked executable symlink as described above, I find it interesting that both tools pick the absolute symlink completely differently:
FWIW my OCD prefers the pip version, the most specific filename has the absolute symlink ( In case it helps anyone here is also the difference between the --- pip_venv/pyvenv.cfg 2024-09-13 20:18:47.389618788 +0200
+++ uv_venv/pyvenv.cfg 2024-09-13 20:19:00.968279785 +0200
@@ -1,5 +1,6 @@
-home = /opt/homebrew/opt/python@3.12/bin
+home = /opt/homebrew/Cellar/python@3.12/3.12.6/Frameworks/Python.framework/Versions/3.12/bin
+implementation = CPython
+uv = 0.4.9
+version_info = 3.12.6
include-system-site-packages = false
-version = 3.12.6
-executable = /opt/homebrew/Cellar/python@3.12/3.12.6/Frameworks/Python.framework/Versions/3.12/bin/python3.12
-command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Volumes/sensitive/src/handmade/0/pip_venv
+relocatable = false |
I'm open to changing this since it's been reported multiple times. It might be considered breaking though. |
I suggest changing it to resolve symbolic links until a non-venv python is found. |
I think at the very least it would be nice to have a flag to force one behavior or the other, but maybe there's a concern of bloating commands with too many switches. |
I'm fine to change this but it probably requires 0.5. |
I'll look into this as part of v0.5. |
So just to summarize current behavior:
|
I don't fully understand the
But if I do the same with my non-Homebrew Python, I get:
|
Ok, if I use Homebrew's 3.12:
So it fully resolves the symlink when inside a virtualenv, and doesn't resolve it when outside a virtualenv. |
What we're suggesting is different than all of these: resolve until we see a non-virtualenv. But I think it makes sense. |
Ok, I'm guessing that the Homebrew Pythons didn't used to set |
(Gonna put together a table documenting all this.) |
Collated here: https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?usp=sharing (sorry, the formatting is terrible) |
uv's current behavior is closest to the new |
PR here: #8433 |
Thank you for looking into this. Out of curiosity, what is the use case of
Admittedly I am a very vanilla venv user, always use a homebrew python (or now uv) to create single simple venv's per projects, or until TBH while waiting for this feature to land I was even content just recreating and repopulating the venv's after a python upgrade, it's just so fast from the cache... Although I was a bit surprised that |
## Summary See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
## Summary See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
See extensive discussion in #8433 (comment). This PR brings us into alignment with the standard library by using `sys._base_executable` rather than canonicalizing the executable path. The benefits are primarily for Homebrew, where we'll now resolve to paths like `/opt/homebrew/opt/python@3.12/bin` instead of the undesirable `/opt/homebrew/Cellar/python@3.9/3.9.19_1/Frameworks/Python.framework/Versions/3.9/bin`. Most other users should see no change, though in some cases, nested virtual environments now have slightly different behavior -- namely, they _sometimes_ resolve to the virtual environment Python (at least for Homebrew; not for rtx or uv Pythons though). See [here](https://docs.google.com/spreadsheets/d/1Vw5ClYEjgrBJJhQiwa3cCenIA1GbcRyudYN9NwQaEcM/edit?gid=0#gid=0) for a breakdown. Closes #1640. Closes #1795.
We refined the behavior a bit in #9723. |
On Homebrew, virtual environments created by
uv venv
reference the Python installation underCellar
in their interpreter symlink andpyvenv.cfg
, which has the full downstream version in its path. These virtual environments break when Homebrew upgrades the respective Python package to the next maintenance release. In recent versions ofvenv
andvirtualenv
, this issue was resolved by using the stable link under$(brew --prefix)/opt/python@3.x/
instead. For example, on Python 3.11 macOS aarch64 this would be the interpreter in/opt/homebrew/opt/python@3.11/bin
.This shell session demonstrates the problem:
When Homebrew upgrades its
python@3.11
package and cleans up the old installation underCellar
, those references in the virtual environment start to dangle.For comparison, here's what I get with
venv
from Homebrew'spython@3.11
installation:And with
virtualenv
:❯ virtualenv --version virtualenv 20.25.0 from ~/.local/pipx/venvs/virtualenv/lib/python3.12/site-packages/virtualenv/__init__.py ❯ virtualenv .venv ❯ readlink .venv/bin/python /opt/homebrew/opt/python@3.12/bin/python3.12 ❯ grep ^home .venv/pyvenv.cfg home = /opt/homebrew/opt/python@3.12/bin
Affected platforms: Linux and macOS with Homebrew Python
The text was updated successfully, but these errors were encountered: