Fix VIRTUALENV_PYTHON environment lookup (#1998)

This commit is contained in:
Patrice Neff 2020-10-28 16:10:36 +00:00 committed by GitHub
parent 0a5009aee7
commit d89f97683e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 7 deletions

View file

@ -0,0 +1,2 @@
Fix processing of the ``VIRTUALENV_PYTHON`` environment variable and make it
multi-value as well (separated by comma) - by :user:`pneff`.

View file

@ -71,15 +71,21 @@ variable ``VIRTUALENV_PYTHON`` like:
env VIRTUALENV_PYTHON=/opt/python-3.8/bin/python virtualenv
This also works for appending command line options, like :option:`extra-search-dir`, where a literal newline
is used to separate the values:
Where the option accepts multiple values, for example for :option:`python` or
:option:`extra-search-dir`, the values can be separated either by literal
newlines or commas. Newlines and commas can not be mixed and if both are
present only the newline is used for separating values. Examples for multiple
values:
.. code-block:: console
env VIRTUALENV_EXTRA_SEARCH_DIR=/path/to/dists\n/path/to/other/dists virtualenv
env VIRTUALENV_PYTHON=/opt/python-3.8/bin/python,python3.8 virtualenv
env VIRTUALENV_EXTRA_SEARCH_DIR=/path/to/dists\n/path/to/other/dists virtualenv
The equivalent CLI-flags based invocation, for the above example, would be:
The equivalent CLI-flags based invocation for the above examples would be:
.. code-block:: console
virtualenv --python=/opt/python-3.8/bin/python --python=python3.8
virtualenv --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists

View file

@ -46,9 +46,7 @@ class ListType(TypeData):
""""""
def convert(self, value, flatten=True):
if isinstance(value, (str, bytes)):
value = filter(None, [x.strip() for x in value.splitlines()])
values = list(value)
values = self.split_values(value)
result = []
for value in values:
sub_values = value.split(os.pathsep)
@ -56,6 +54,25 @@ class ListType(TypeData):
converted = [self.as_type(i) for i in result]
return converted
def split_values(self, value):
"""Split the provided value into a list.
First this is done by newlines. If there were no newlines in the text,
then we next try to split by comma.
"""
if isinstance(value, (str, bytes)):
# Use `splitlines` rather than a custom check for whether there is
# more than one line. This ensures that the full `splitlines()`
# logic is supported here.
values = value.splitlines()
if len(values) <= 1:
values = value.split(",")
values = filter(None, [x.strip() for x in values])
else:
values = list(value)
return values
def convert(value, as_type, source):
"""Convert the value as a given type where the value comes from the given source"""

View file

@ -25,6 +25,7 @@ class Builtin(Discover):
"--python",
dest="python",
metavar="py",
type=str,
action="append",
default=[],
help="interpreter based on what to create environment (path/identifier) "

View file

@ -4,6 +4,7 @@ import os
import pytest
from virtualenv.config.cli.parser import VirtualEnvOptions
from virtualenv.config.ini import IniConfig
from virtualenv.run import session_via_cli
from virtualenv.util.path import Path
@ -31,6 +32,34 @@ def test_value_bad(monkeypatch, caplog, empty_conf):
assert "invalid literal" in caplog.messages[0]
def test_python_via_env_var(monkeypatch):
options = VirtualEnvOptions()
monkeypatch.setenv(str("VIRTUALENV_PYTHON"), str("python3"))
session_via_cli(["venv"], options=options)
assert options.python == ["python3"]
def test_python_multi_value_via_env_var(monkeypatch):
options = VirtualEnvOptions()
monkeypatch.setenv(str("VIRTUALENV_PYTHON"), str("python3,python2"))
session_via_cli(["venv"], options=options)
assert options.python == ["python3", "python2"]
def test_python_multi_value_newline_via_env_var(monkeypatch):
options = VirtualEnvOptions()
monkeypatch.setenv(str("VIRTUALENV_PYTHON"), str("python3\npython2"))
session_via_cli(["venv"], options=options)
assert options.python == ["python3", "python2"]
def test_python_multi_value_prefer_newline_via_env_var(monkeypatch):
options = VirtualEnvOptions()
monkeypatch.setenv(str("VIRTUALENV_PYTHON"), str("python3\npython2,python27"))
session_via_cli(["venv"], options=options)
assert options.python == ["python3", "python2,python27"]
def test_extra_search_dir_via_env_var(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
value = "a{}0{}b{}c".format(os.linesep, os.linesep, os.pathsep)