Skip to content
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

Clarifying virtualenv 20's -p behavior #1777

Closed
Julian opened this issue Apr 19, 2020 · 8 comments
Closed

Clarifying virtualenv 20's -p behavior #1777

Julian opened this issue Apr 19, 2020 · 8 comments
Labels

Comments

@Julian
Copy link

Julian commented Apr 19, 2020

Issue

Hi hi.

I apologize in advance, still digging through some of the issues on the tracker so this may be known, or even intentional, but virtualenv>=20's -p behavior is confusing me quite a bit.

Specifically, in pre-rewrite virtualenv, -p was somewhat simplish to me, it basically searched PATH for most of my uses of it.

Post 20 though, it now seems to work significantly differently, so I wanted to confirm whether its new behavior is entirely expected/intentional. Specifically, here are some significant differences in what it does:

Setup both old and new virtualenv
~/Desktop
⊙  virtualenv --python /usr/local/bin/python3 venv16 && venv16/bin/python -m pip install virtualenv'<20'                                                                                          julian@Air
created virtual environment CPython3.7.7.final.0-64 in 412ms
  creator CPython3Posix(dest=/Users/julian/Desktop/venv16, clear=False, global=False)
  seeder FromAppData(download=False, pip=latest, setuptools=latest, wheel=latest, via=copy, app_data_dir=/Users/julian/Library/Application Support/virtualenv/seed-app-data/v1.0.1)
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
Collecting virtualenv<20
  Using cached virtualenv-16.7.10-py2.py3-none-any.whl (3.4 MB)
Installing collected packages: virtualenv
Successfully installed virtualenv-16.7.10

~/Desktop
⊙  virtualenv --python /usr/local/bin/python3 venv20 && venv20/bin/python -m pip install virtualenv'>=20'                                                                                         julian@Air
created virtual environment CPython3.7.7.final.0-64 in 405ms
  creator CPython3Posix(dest=/Users/julian/Desktop/venv20, clear=False, global=False)
  seeder FromAppData(download=False, pip=latest, setuptools=latest, wheel=latest, via=copy, app_data_dir=/Users/julian/Library/Application Support/virtualenv/seed-app-data/v1.0.1)
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
Collecting virtualenv>=20
  Using cached virtualenv-20.0.18-py2.py3-none-any.whl (4.6 MB)
Collecting filelock<4,>=3.0.0
  Using cached filelock-3.0.12-py3-none-any.whl (7.6 kB)
Collecting six<2,>=1.9.0
  Using cached six-1.14.0-py2.py3-none-any.whl (10 kB)
Processing /Users/julian/Library/Caches/pip/wheels/6e/e8/db/c73dae4867666e89ba3cfbc4b5c092446f0e584eda6f409cbb/distlib-0.3.0-cp37-none-any.whl
Collecting importlib-metadata<2,>=0.12; python_version < "3.8"
  Using cached importlib_metadata-1.6.0-py2.py3-none-any.whl (30 kB)
Collecting appdirs<2,>=1.4.3
  Using cached appdirs-1.4.3-py2.py3-none-any.whl (12 kB)
Collecting zipp>=0.5
  Using cached zipp-3.1.0-py3-none-any.whl (4.9 kB)
Installing collected packages: filelock, six, distlib, zipp, importlib-metadata, appdirs, virtualenv
Successfully installed appdirs-1.4.3 distlib-0.3.0 filelock-3.0.12 importlib-metadata-1.6.0 six-1.14.0 virtualenv-20.0.18 zipp-3.1.0

On virtualenv<20, running -p python searches PATH for an executable named python and uses that to create a virtualenv (for me, this will find a pypy interpreter):

⊙  venv16/bin/virtualenv --python python venv2 && rm -rf venv2                                                                                                                                    julian@Air
Running virtualenv with interpreter /Users/julian/.local/bin/python
Already using interpreter /Users/julian/.local/bin/python
Using real prefix '/usr/local/Cellar/pypy/7.3.1_1/libexec'
  No LICENSE.txt / LICENSE found in source
Path not in prefix '/Users/julian/.local/share/virtualenvs/dev/include' '/usr/local/Cellar/pypy/7.3.1_1/libexec'
New pypy executable in /Users/julian/Desktop/venv2/bin/python
Also creating executable in /Users/julian/Desktop/venv2/bin/pypy
Installing setuptools, pip, wheel...
done.

which corresponds to:

⊙  type -a python                                                                                                                                                                                 julian@Air
python is /Users/julian/.local/bin/python
python is /usr/local/bin/python
python is /usr/bin/python

where /Users/julian/.local/bin/python --version is that PyPy interpreter.

But on >=20, it instead finds a CPython3.7 (the one virtualenv happens to be installed to in this case):

~/Desktop
⊙  venv20/bin/virtualenv --python python venv2 && rm -rf venv2                                                                                                                                    julian@Air
created virtual environment CPython3.7.7.final.0-64 in 365ms
  creator CPython3Posix(dest=/Users/julian/Desktop/venv2, clear=False, global=False)
  seeder FromAppData(download=False, pip=latest, setuptools=latest, wheel=latest, via=copy, app_data_dir=/Users/julian/Library/Application Support/virtualenv/seed-app-data/v1.0.1)
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

I see that's documented (the docs say using python will essentially find "any python"), but that still seems surprising, so I'm including it (seems likely it's intended in this case?).

More importantly though, things that are on the PATH, are still not found. For instance, on virtualenv<20, running

⊙  venv16/bin/virtualenv --python pypy venv2 && rm -rf venv2                                                                                                                                      julian@Air
Running virtualenv with interpreter /usr/local/bin/pypy
Already using interpreter /usr/local/bin/pypy
  No LICENSE.txt / LICENSE found in source
New pypy executable in /Users/julian/Desktop/venv2/bin/pypy
Installing setuptools, pip, wheel...
done.

will find a pypy binary on my PATH. But on virtualenv>=20 I instead get:

⊙  venv20/bin/virtualenv --python pypy venv2 && rm -rf venv2                                                                                                                                      julian@Air
RuntimeError: failed to detect pypy2.7.13-64|pypy2.7.13|pypy2.7-64|pypy2.7|pypy2-64|pypy2|pypy-64|pypy|python2.7.13-64|python2.7.13|python2.7-64|python2.7|python2-64|python2|python-64|python in /usr/local/Cellar/pypy/7.3.1_1/libexec

even though there indeed is such a binary present:

⊙  type -a pypy                                                                                                                                                                                   julian@Air
pypy is /usr/local/bin/pypy

Even more surprisingly is that if I ask for a PyPy3, >=20 still seems to be searching for a PyPy2 (and still not considering PATH):

⊙  venv20/bin/virtualenv --python pypy3 venv2 && rm -rf venv2                                                                                                                                     julian@Air
RuntimeError: failed to detect pypy2.7.13-64|pypy2.7.13|pypy2.7-64|pypy2.7|pypy2-64|pypy2|pypy-64|pypy|python2.7.13-64|python2.7.13|python2.7-64|python2.7|python2-64|python2|python-64|python in /usr/local/Cellar/pypy/7.3.1_1/libexec

with me having:

⊙  type -a pypy3                                                                                                                                                                                  julian@Air
pypy3 is /usr/local/bin/pypy3

which worked on <20:

⊙  venv16/bin/virtualenv --python pypy3 venv2 && rm -rf venv2                                                                                                                                     julian@Air
Running virtualenv with interpreter /usr/local/bin/pypy3
Already using interpreter /usr/local/bin/pypy3
Using base prefix '/usr/local/Cellar/pypy3/7.3.1_1/libexec'
  No LICENSE.txt / LICENSE found in source
New pypy executable in /Users/julian/Desktop/venv2/bin/pypy3
Also creating executable in /Users/julian/Desktop/venv2/bin/pypy
Installing setuptools, pip, wheel...
done.

So yeah -- are any / all of the above intended behavior? I can imagine reasons to change -p to not be PATH-searching and instead have more of a language for finding a suitable interpreter without connection to what it's called, but at least a few of the above seem quite invasive, so figured I'd confirm. If it's intended I can obviously adjust my own workflow to search PATH first and give the absolute path to virtualenv.

TIA!

Environment

OS: macOS, Python / PyPy installed via Homebrew

``pip list`` of the host python where ``virtualenv`` is installed
Package        Version
-------------- -------
appdirs        1.4.3  
attrs          19.3.0 
Automat        20.2.0 
click          7.1.1  
colorama       0.4.3  
constantly     15.1.0 
distlib        0.3.0  
filelock       3.0.12 
filesystems    0.25.0 
hyperlink      19.0.0 
idna           2.9    
incremental    17.5.0 
packaging      20.3   
pip            19.2.3 
pudb           2019.2 
Pygments       2.6.1  
PyHamcrest     2.0.2  
pyparsing      2.4.7  
pyrsistent     0.16.0 
setuptools     41.2.0 
six            1.14.0 
toml           0.10.0 
tomlkit        0.6.0  
tqdm           4.45.0 
Twisted        20.3.0 
urwid          2.1.0  
venvs          6.11.9 
virtualenv     20.0.18
virtue         0.8.1  
zope.interface 5.1.0  
@Julian Julian added the bug label Apr 19, 2020
@gaborbernat
Copy link
Contributor

Did you read the detailed documentation under https://virtualenv.pypa.io/en/latest/user_guide.html#python-discovery?

@gaborbernat
Copy link
Contributor

I'd say the first case is expected. The pypy and pypy3 parts though are likely a bug, and we'll need more information on it to pin it down. -p now rhoughly wants to be what py - would be 🤔

@Julian
Copy link
Author

Julian commented Apr 19, 2020

I did see that page yeah, just before I filed this, but it still wasn't entirely clear to me (it certainly made me think some of this is intentional, even though I'm still not sure it's obvious to me this is significantly better than the old behavior but I certainly trust you to have thought more carefully than I have about it)

But e.g. in that section I saw:

Try to discover a matching python executable within the folders enumerated on the PATH environment variable. In this case we’ll try to find an executable that has a name roughly similar to the specification (for exact logic, please see the implementation code).

Which told me at least some part of this should be searching PATH I thought. (Have not yet read the implementation though).

Also -- does that mean that the current recommended way to get the old behavior is to do the PATH searching external to virtualenv? (I assume so, but just confirming)?

@Julian
Copy link
Author

Julian commented Apr 19, 2020

Does this have any additional useful information to diagnose the second piece:

⊙  venv20/bin/virtualenv --python pypy3 venv2 -vvvv && rm -rf venv2                                                                                                                               julian@Air
87 setup logging to NOTSET [DEBUG report:43]
96 find interpreter for spec PythonSpec(implementation=pypy, major=3) [INFO builtin:44]
96 discover exe for PythonInfo(spec=CPython3.7.7.final.0-64, exe=/Users/julian/Desktop/venv20/bin/python, platform=darwin, version='3.7.7 (default, Mar 10 2020, 15:43:33) \n[Clang 11.0.0 (clang-1100.0.33.17)]', encoding_fs_io=utf-8-UTF-8) in /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7 [DEBUG py_info:353]
97 filesystem is not case-sensitive [DEBUG info:28]
100 Attempting to acquire lock 4389751440 on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/b1ee2994a8d19e55c7dc42974d2e280efd5048978fc45dcb2fffdaa115de311b.lock [DEBUG filelock:270]
100 Lock 4389751440 acquired on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/b1ee2994a8d19e55c7dc42974d2e280efd5048978fc45dcb2fffdaa115de311b.lock [INFO filelock:274]
101 get PythonInfo from /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/b1ee2994a8d19e55c7dc42974d2e280efd5048978fc45dcb2fffdaa115de311b.json for /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/bin/python3.7 [DEBUG cached_py_info:79]
101 Attempting to release lock 4389751440 on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/b1ee2994a8d19e55c7dc42974d2e280efd5048978fc45dcb2fffdaa115de311b.lock [DEBUG filelock:315]
101 Lock 4389751440 released on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/b1ee2994a8d19e55c7dc42974d2e280efd5048978fc45dcb2fffdaa115de311b.lock [INFO filelock:318]
102 Attempting to acquire lock 4389752272 on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/df955ce39d0f31d56d4bb2fe0a613e5326ba60723fd33d8303a3aede8f65715c.lock [DEBUG filelock:270]
102 Lock 4389752272 acquired on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/df955ce39d0f31d56d4bb2fe0a613e5326ba60723fd33d8303a3aede8f65715c.lock [INFO filelock:274]
103 get PythonInfo from /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/df955ce39d0f31d56d4bb2fe0a613e5326ba60723fd33d8303a3aede8f65715c.json for /usr/local/opt/python/bin/python3.7 [DEBUG cached_py_info:79]
103 Attempting to release lock 4389752272 on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/df955ce39d0f31d56d4bb2fe0a613e5326ba60723fd33d8303a3aede8f65715c.lock [DEBUG filelock:315]
103 Lock 4389752272 released on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/df955ce39d0f31d56d4bb2fe0a613e5326ba60723fd33d8303a3aede8f65715c.lock [INFO filelock:318]
103 proposed PythonInfo(spec=CPython3.7.7.final.0-64, system=/usr/local/opt/python/bin/python3.7, exe=/Users/julian/Desktop/venv20/bin/python, platform=darwin, version='3.7.7 (default, Mar 10 2020, 15:43:33) \n[Clang 11.0.0 (clang-1100.0.33.17)]', encoding_fs_io=utf-8-UTF-8) [INFO builtin:50]
104 discover PATH[0]=/Users/julian/.local/bin [DEBUG builtin:84]
106 Attempting to acquire lock 4389883344 on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/66dffc3615b313df0566342e7329fe6a533efad6f35430a65794f4a4862223d2.lock [DEBUG filelock:270]
106 Lock 4389883344 acquired on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/66dffc3615b313df0566342e7329fe6a533efad6f35430a65794f4a4862223d2.lock [INFO filelock:274]
106 get PythonInfo from /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/66dffc3615b313df0566342e7329fe6a533efad6f35430a65794f4a4862223d2.json for /Users/julian/.local/bin/python [DEBUG cached_py_info:79]
107 Attempting to release lock 4389883344 on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/66dffc3615b313df0566342e7329fe6a533efad6f35430a65794f4a4862223d2.lock [DEBUG filelock:315]
107 Lock 4389883344 released on /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/66dffc3615b313df0566342e7329fe6a533efad6f35430a65794f4a4862223d2.lock [INFO filelock:318]
107 discover exe for PathPythonInfo(spec=PyPy2.7.13.final.42-64, exe=/Users/julian/.local/bin/python, platform=darwin, version='2.7.13 (?, Apr 18 2020, 18:43:27)\n[PyPy 7.3.1 with GCC 4.2.1 Compatible Apple LLVM 11.0.3 (clang-1103.0.32.59)]', encoding_fs_io=UTF-8-None) in /usr/local/Cellar/pypy/7.3.1_1/libexec [DEBUG py_info:353]
108 RuntimeError: failed to detect pypy2.7.13-64|pypy2.7.13|pypy2.7-64|pypy2.7|pypy2-64|pypy2|pypy-64|pypy|python2.7.13-64|python2.7.13|python2.7-64|python2.7|python2-64|python2|python-64|python in /usr/local/Cellar/pypy/7.3.1_1/libexec [ERROR __main__:57]

@Julian
Copy link
Author

Julian commented Apr 19, 2020

(If not I am likely going to step through things in a debugger maybe tomorrow or something)

Julian added a commit to Julian/venvs that referenced this issue Apr 20, 2020
In virtualenv>=20, the behavior of -p is different.

Specifically, -p takes something resembling more like
a specification than the name of a binary.

It's possible that this project should follow suit,
but for the moment, even my own venvs configuration is
broken :) so for now just reimplement the old behavior.

See https://virtualenv.pypa.io/en/latest/user_guide.html#python-discovery
for full details.

And pypa/virtualenv#1777 for possible further clarification.
@mattip
Copy link
Contributor

mattip commented Apr 20, 2020

There is additional logic in the code to determine whether the exe found via the spec is valid. For pypy2 this is here, for pypy3 it is here. It assumes there will be a directory lib under sys.system_prefix. Perhaps the installation in question does not meet those criteria?

@gaborbernat gaborbernat changed the title Clarifying virtualenv 20's -p behavior pypy discovery issues Apr 20, 2020
@gaborbernat
Copy link
Contributor

gaborbernat commented Apr 20, 2020

Which told me at least some part of this should be searching PATH I thought. (Have not yet read the implementation though).

This could be improved. But basically it's not guaranteed to be searched on the PATH. The idea is that you give a python specification string, and we'll try to resolve that. If the host python of virtualenv already satisfies this we'll not move ahead to searching the PATH (furthermore on Windows the Windows registry entries will be queried before the PATH too). Looking at the log you've displayed you can see evidence of this:


96 find interpreter for spec PythonSpec(implementation=pypy, major=3)

96 discover exe for PythonInfo(spec=CPython3.7.7.final.0-64, exe=/Users/julian/Desktop/venv20/bin/python, platform=darwin, version='3.7.7 (default, Mar 10 2020, 15:43:33) \n[Clang 11.0.0 (clang-1100.0.33.17)]', encoding_fs_io=utf-8-UTF-8) in /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7 [DEBUG py_info:353]
101 get PythonInfo from /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/b1ee2994a8d19e55c7dc42974d2e280efd5048978fc45dcb2fffdaa115de311b.json for /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/bin/python3.7 [DEBUG cached_py_info:79]
103 get PythonInfo from /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/df955ce39d0f31d56d4bb2fe0a613e5326ba60723fd33d8303a3aede8f65715c.json for /usr/local/opt/python/bin/python3.7 [DEBUG cached_py_info:79]
103 proposed PythonInfo(spec=CPython3.7.7.final.0-64, system=/usr/local/opt/python/bin/python3.7, exe=/Users/julian/Desktop/venv20/bin/python, platform=darwin, version='3.7.7 (default, Mar 10 2020, 15:43:33) \n[Clang 11.0.0 (clang-1100.0.33.17)]', encoding_fs_io=utf-8-UTF-8) [INFO builtin:50]

104 discover PATH[0]=/Users/julian/.local/bin [DEBUG builtin:84]

106 get PythonInfo from /Users/julian/Library/Application Support/virtualenv/py_info/20.0.18/66dffc3615b313df0566342e7329fe6a533efad6f35430a65794f4a4862223d2.json for /Users/julian/.local/bin/python [DEBUG cached_py_info:79]
107 discover exe for PathPythonInfo(spec=PyPy2.7.13.final.42-64, exe=/Users/julian/.local/bin/python, platform=darwin, version='2.7.13 (?, Apr 18 2020, 18:43:27)\n[PyPy 7.3.1 with GCC 4.2.1 Compatible Apple LLVM 11.0.3 (clang-1103.0.32.59)]', encoding_fs_io=UTF-8-None) in /usr/local/Cellar/pypy/7.3.1_1/libexec [DEBUG py_info:353]
108 RuntimeError: failed to detect pypy2.7.13-64|pypy2.7.13|pypy2.7-64|pypy2.7|pypy2-64|pypy2|pypy-64|pypy|python2.7.13-64|python2.7.13|python2.7-64|python2.7|python2-64|python2|python-64|python in /usr/local/Cellar/pypy/7.3.1_1/libexec [ERROR __main__:57]

To make it easier to see separated into three sections and removed the lock acquire/release operation not relevant for this:

  • First one shows we're looking here for a PyPy interpreter that has a major version 3.
  • Initially, we want to look into the host python interpreter; which is venv20/bin/python - when creating virtual environments we really need the system Python, and not a virtual environment so we actually end up doing 2 lookups to find this; first we resolve venv20/bin/python to map to /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/bin/python3.7; which then point us to /usr/local/opt/python/bin/python3.7. This does not match the queried spec of pypy 3, so we move on.
  • Now we look unto the PATH, first element /Users/julian/.local/bin.
  • We try first with the python executable. This points us to a host python having its prefix under /usr/local/Cellar/pypy/7.3.1_1/libexec. Now we need to find the system pythons executable location under this prefix (there's no conf within the interpreter to point us directly to the executable), so we're doing some heuristic search with the assumption this is a PyPy2 interpreter. Hence why we try an exhaustive list of pypy2.7.13-64|pypy2.7.13|pypy2.7-64|pypy2.7|pypy2-64|pypy2|pypy-64|pypy|python2.7.13-64|python2.7.13|python2.7-64|python2.7|python2-64|python2|python-64|python. Sadly none of this we can find so we fail. We should probably still continue the search in such cases with other executables, this feels like a bug in our discovery logic.

Follow-up items, created

As @mattip said above now we don't accept blindly found pythons... only if it satisfies the necessary invariants to then create a virtual environment from it. In this case, though we'll log a rejection message I think in the log.

@gaborbernat gaborbernat changed the title pypy discovery issues failing to discover a python interpreters executable stops the discovery with an error Apr 20, 2020
@gaborbernat gaborbernat added question and removed bug labels Apr 20, 2020
@gaborbernat gaborbernat changed the title failing to discover a python interpreters executable stops the discovery with an error Clarifying virtualenv 20's -p behavior Apr 20, 2020
@Julian
Copy link
Author

Julian commented Apr 20, 2020

A ha! I see, thanks for the explanation.

Sounds good thanks! Will follow the 2 follow-up tickets.

@pypa pypa locked and limited conversation to collaborators Jan 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants