pyenv-virtualenv icon indicating copy to clipboard operation
pyenv-virtualenv copied to clipboard

pyenv-virtualenv is not compatible with brew pyenv-sync

Open regulskimichal opened this issue 1 year ago • 7 comments

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"

regulskimichal avatar Feb 26 '25 17:02 regulskimichal

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 avatar Feb 26 '25 17:02 native-api

@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 python command is invoked. Depending on a distribution or system configuration, python may or may not be installed. If python is installed its target interpreter may refer to python2 or python3.

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.

reegnz avatar Mar 14 '25 12:03 reegnz

Depending on a distribution or system configuration, python may 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 venv package or a similar tool such as virtualenv or conda) is active, the python command should refer to the virtual environment's interpreter and should always be available. The python3 or python2 command (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".

native-api avatar Mar 14 '25 17:03 native-api

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.

native-api avatar Mar 14 '25 17:03 native-api

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.

reegnz avatar Mar 16 '25 15:03 reegnz

Pyenv-managed installations are activated environments. You explicitly activate them by selecting a version to use other than system.

native-api avatar Mar 16 '25 15:03 native-api

The fact that the activation process looks different doesn't matter -- the principle and the net effect are the same.

native-api avatar Mar 16 '25 15:03 native-api