Fallback functionality for interpreter discovery (#1995)

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
This commit is contained in:
Bernát Gábor 2020-10-25 00:01:36 +01:00 committed by GitHub
parent 601b813e45
commit aac61dfbaf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 11 deletions

View file

@ -19,18 +19,16 @@ repos:
rev: 5.6.4 rev: 5.6.4
hooks: hooks:
- id: isort - id: isort
- repo: https://github.com/ambv/black - repo: https://github.com/psf/black
rev: 20.8b1 rev: 20.8b1
hooks: hooks:
- id: black - id: black
args: [--safe] args: [--safe]
language_version: python3.8
- repo: https://github.com/asottile/blacken-docs - repo: https://github.com/asottile/blacken-docs
rev: v1.8.0 rev: v1.8.0
hooks: hooks:
- id: blacken-docs - id: blacken-docs
additional_dependencies: [black==20.8b1] additional_dependencies: [black==20.8b1]
language_version: python3.8
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.6.0 rev: v1.6.0
hooks: hooks:
@ -50,4 +48,3 @@ repos:
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies: ["flake8-bugbear == 20.1.4"] additional_dependencies: ["flake8-bugbear == 20.1.4"]
language_version: python3.8

View file

@ -0,0 +1,2 @@
The python specification can now take one or more values, first found is used to create the virtual environment - by
:user:`gaborbernat`.

View file

@ -6,7 +6,7 @@ if int(__version__.split(".")[0]) < 41:
setup( setup(
use_scm_version={ use_scm_version={
"write_to": "src/virtualenv/version.py", "write_to": "src/virtualenv/version.py",
"write_to_template": 'from __future__ import unicode_literals;\n\n__version__ = "{version}"', "write_to_template": 'from __future__ import unicode_literals\n\n__version__ = "{version}"\n',
}, },
setup_requires=["setuptools_scm >= 2"], setup_requires=["setuptools_scm >= 2"],
) )

View file

@ -15,7 +15,7 @@ from .py_spec import PythonSpec
class Builtin(Discover): class Builtin(Discover):
def __init__(self, options): def __init__(self, options):
super(Builtin, self).__init__(options) super(Builtin, self).__init__(options)
self.python_spec = options.python self.python_spec = options.python if options.python else [sys.executable]
self.app_data = options.app_data self.app_data = options.app_data
@classmethod @classmethod
@ -25,18 +25,25 @@ class Builtin(Discover):
"--python", "--python",
dest="python", dest="python",
metavar="py", metavar="py",
help="target interpreter for which to create a virtual (either absolute path or identifier string)", action="append",
default=sys.executable, default=[],
help="interpreter based on what to create environment (path/identifier) "
"- by default use the interpreter where the tool is installed - first found wins",
) )
def run(self): def run(self):
return get_interpreter(self.python_spec, self.app_data) for python_spec in self.python_spec:
result = get_interpreter(python_spec, self.app_data)
if result is not None:
return result
return None
def __repr__(self): def __repr__(self):
return ensure_str(self.__unicode__()) return ensure_str(self.__unicode__())
def __unicode__(self): def __unicode__(self):
return "{} discover of python_spec={!r}".format(self.__class__.__name__, self.python_spec) spec = self.python_spec[0] if len(self.python_spec) == 1 else self.python_spec
return "{} discover of python_spec={!r}".format(self.__class__.__name__, spec)
def get_interpreter(key, app_data=None): def get_interpreter(key, app_data=None):

View file

@ -3,11 +3,12 @@ from __future__ import absolute_import, unicode_literals
import logging import logging
import os import os
import sys import sys
from argparse import Namespace
from uuid import uuid4 from uuid import uuid4
import pytest import pytest
from virtualenv.discovery.builtin import get_interpreter from virtualenv.discovery.builtin import Builtin, get_interpreter
from virtualenv.discovery.py_info import PythonInfo from virtualenv.discovery.py_info import PythonInfo
from virtualenv.info import fs_supports_symlink from virtualenv.info import fs_supports_symlink
from virtualenv.util.path import Path from virtualenv.util.path import Path
@ -53,3 +54,24 @@ def test_relative_path(tmp_path, session_app_data, monkeypatch):
relative = str(sys_executable.relative_to(cwd)) relative = str(sys_executable.relative_to(cwd))
result = get_interpreter(relative, session_app_data) result = get_interpreter(relative, session_app_data)
assert result is not None assert result is not None
def test_discovery_fallback_fail(session_app_data, caplog):
caplog.set_level(logging.DEBUG)
builtin = Builtin(Namespace(app_data=session_app_data, python=["magic-one", "magic-two"]))
result = builtin.run()
assert result is None
assert "accepted" not in caplog.text
def test_discovery_fallback_ok(session_app_data, caplog):
caplog.set_level(logging.DEBUG)
builtin = Builtin(Namespace(app_data=session_app_data, python=["magic-one", sys.executable]))
result = builtin.run()
assert result is not None, caplog.text
assert result.executable == sys.executable, caplog.text
assert "accepted" in caplog.text