Fix ansible-test virtualenv real python search.
ansible-test now properly searches for `pythonX.Y` instead of `python` when looking for the real python that created a `virtualenv`.
This commit is contained in:
parent
f2214951c5
commit
b91f452f4f
2 changed files with 60 additions and 12 deletions
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- ansible-test now properly searches for ``pythonX.Y`` instead of ``python`` when looking for the real python that created a ``virtualenv``
|
|
@ -4,6 +4,7 @@ __metaclass__ = type
|
|||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from . import types as t
|
||||
|
||||
|
@ -46,9 +47,13 @@ def create_virtual_environment(args, # type: EnvironmentConfig
|
|||
|
||||
if python_version >= (3, 0):
|
||||
# use the built-in 'venv' module on Python 3.x
|
||||
if run_venv(args, python, system_site_packages, pip, path):
|
||||
display.info('Created Python %s virtual environment using "venv": %s' % (version, path), verbosity=1)
|
||||
return True
|
||||
# creating a virtual environment using 'venv' when running in a virtual environment created by 'virtualenv' results
|
||||
# in a copy of the original virtual environment instead of creation of a new one
|
||||
# avoid this issue by only using "real" python interpreters to invoke 'venv'
|
||||
for real_python in iterate_real_pythons(args, version):
|
||||
if run_venv(args, real_python, system_site_packages, pip, path):
|
||||
display.info('Created Python %s virtual environment using "venv": %s' % (version, path), verbosity=1)
|
||||
return True
|
||||
|
||||
# something went wrong, most likely the package maintainer for the Python installation removed ensurepip
|
||||
# which will prevent creation of a virtual environment without installation of other OS packages
|
||||
|
@ -80,6 +85,56 @@ def create_virtual_environment(args, # type: EnvironmentConfig
|
|||
return False
|
||||
|
||||
|
||||
def iterate_real_pythons(args, version): # type: (EnvironmentConfig, str) -> t.Iterable[str]
|
||||
"""
|
||||
Iterate through available real python interpreters of the requested version.
|
||||
The current interpreter will be checked and then the path will be searched.
|
||||
"""
|
||||
version_info = tuple(int(n) for n in version.split('.'))
|
||||
current_python = None
|
||||
|
||||
if version_info == sys.version_info[:len(version_info)]:
|
||||
current_python = sys.executable
|
||||
real_prefix = get_python_real_prefix(args, current_python)
|
||||
|
||||
if real_prefix:
|
||||
current_python = find_python(version, os.path.join(real_prefix, 'bin'))
|
||||
|
||||
if current_python:
|
||||
yield current_python
|
||||
|
||||
path = os.environ.get('PATH', os.path.defpath)
|
||||
|
||||
if not path:
|
||||
return
|
||||
|
||||
found_python = find_python(version, path)
|
||||
|
||||
if not found_python:
|
||||
return
|
||||
|
||||
if found_python == current_python:
|
||||
return
|
||||
|
||||
real_prefix = get_python_real_prefix(args, found_python)
|
||||
|
||||
if real_prefix:
|
||||
found_python = find_python(version, os.path.join(real_prefix, 'bin'))
|
||||
|
||||
if found_python:
|
||||
yield found_python
|
||||
|
||||
|
||||
def get_python_real_prefix(args, path): # type: (EnvironmentConfig, str) -> t.Optional[str]
|
||||
"""
|
||||
Return the real prefix of the specified interpreter or None if the interpreter is not a virtual environment created by 'virtualenv'.
|
||||
"""
|
||||
cmd = [path, os.path.join(os.path.join(ANSIBLE_TEST_DATA_ROOT, 'virtualenvcheck.py'))]
|
||||
check_result = json.loads(run_command(args, cmd, capture=True, always=True)[0])
|
||||
real_prefix = check_result['real_prefix']
|
||||
return real_prefix
|
||||
|
||||
|
||||
def run_venv(args, # type: EnvironmentConfig
|
||||
run_python, # type: str
|
||||
system_site_packages, # type: bool
|
||||
|
@ -87,15 +142,6 @@ def run_venv(args, # type: EnvironmentConfig
|
|||
path, # type: str
|
||||
): # type: (...) -> bool
|
||||
"""Create a virtual environment using the 'venv' module. Not available on Python 2.x."""
|
||||
cmd = [run_python, os.path.join(os.path.join(ANSIBLE_TEST_DATA_ROOT, 'virtualenvcheck.py'))]
|
||||
check_result = json.loads(run_command(args, cmd, capture=True, always=True)[0])
|
||||
real_prefix = check_result['real_prefix']
|
||||
|
||||
if real_prefix:
|
||||
# we must use the real python to create a virtual environment with venv
|
||||
# attempting to use python from a virtualenv created virtual environment results in a copy of that environment instead
|
||||
run_python = os.path.join(real_prefix, 'bin', 'python')
|
||||
|
||||
cmd = [run_python, '-m', 'venv']
|
||||
|
||||
if system_site_packages:
|
||||
|
|
Loading…
Reference in a new issue