pyenv-virtualenv is not compatible with brew pyenv-sync
I want to install and manage Python instances with brew. Unfortunately, this plugin seems incompatible with a feature called pyenv-sync, that automatically links the brew installations with pyenv versions. Whenever I try to use a version different than system, e.g. pyenv --debug virtualenv 3.10 venv, the command exits with error code 127 and echo pyenv: pip: command not found.
I found that fixing this issue with this commit introduces issue. It is because pyenv-virtualenv script assumes that versions different than system are virtualenvs and uses python as the python binary. In result the script does not resolve pip properly and the whole creation of venv fails.
$ brew -v
Homebrew 4.4.22-57-g19332ee
Homebrew/homebrew-core (git revision 3a740ab22a6; last commit 2025-02-26)
Homebrew/homebrew-cask (git revision d01fa801c8f; last commit 2025-02-26)
$ brew list --versions | egrep 'python|env'
pyenv 2.5.3
pyenv-virtualenv 1.2.4
python-packaging 24.2
[email protected] 3.12.9
[email protected] 3.13.2
virtualenv 20.29.2
$ pyenv -v
pyenv 2.5.3
$ pyenv virtualenv --version
pyenv-virtualenv 1.2.4 (virtualenv virtualenv 20.29.2 from /opt/homebrew/Cellar/virtualenv/20.29.2/libexec/lib/python3.13/site-packages/virtualenv/__init__.py)
pyenv virtualenv --version points at virtualenv that is installed system-wide and uses [email protected] as a dependency
I quickly analysed the script and IMO the easiest way to fix that is to add python3 as a fallback in detect_venv() when PYENV_VERSION is not equal to "system"
This is Pyenv-Sync's problem. As per PEP 394, custom Python environments are expected to provide the python command. It's Pyenv-Sync's job to ensure that whatever it adds under $(pyenv root)/versions is usable as a custom Python installation.
See https://github.com/pyenv/pyenv/issues/3105 for a similar issue.
A possible fix is to make Homebrew somehow create the python executable in the package's bin directory ($(brew --prefix)/opt/<package>/bin) which pyenv-sync links to -- but not link it to $(brew --prefix)/bin when brew link is called.
@native-api Actually, the behaviour you requre, pointing at PEP-394 got patched in the PEP years ago: https://github.com/python/peps/pull/989
Reading the PEP it has this sentence in it's first paragraph of the abstract now:
This PEP outlines the behavior of Python scripts when the
pythoncommand is invoked. Depending on a distribution or system configuration,pythonmay or may not be installed. Ifpythonis installed its target interpreter may refer topython2orpython3.
So actually it is NOT required to have a python executable and this is a bug in pyenv-virtualenv.
Please fix pyenv-virtualenv so it treats PEP-394 as optional as the PEP states.
Depending on a distribution or system configuration,
pythonmay or may not be installed.
This phrase in the PEP refers to the default, system-provided Python. Pyenv-managed installations are not system-provided Pythons.
The PEP goes on to say (emphasis mine):
- When a virtual environment (created by the
venvpackage or a similar tool such asvirtualenvorconda) is active, thepythoncommand should refer to the virtual environment's interpreter and should always be available. Thepython3orpython2command (according to the environment's interpreter version) should also be available.
There isn't a specific section for private alternative installations, so Pyenv falls under "similar tool".
In fact, as a corollary of the PEP, we cannot, in the general case, use an executable name other than python -- because nothing else is guaranteed to exist!
While the vast majority of installations are Python 3 and thus provide python3, e.g. PyPy still supports Python 2.
Actually, pyenv-sync did not provide python3 until very recently -- and it was fixed.
So there's no reason why it cannot be fixed again.
Please read the PEP. python is only mandatory inside an activated virtualenv. Everywhere else it's not. This is a big in pyenv-virtualenv. pyenv-sync in Homebrew works properly with pyenv but not with pyenv-virtualenv.
Pyenv-managed installations are activated environments. You explicitly activate them by selecting a version to use other than system.
The fact that the activation process looks different doesn't matter -- the principle and the net effect are the same.