Skip to content

Commit

Permalink
Fallback functionality for interpreter discovery
Browse files Browse the repository at this point in the history
Signed-off-by: Bernát Gábor <[email protected]>
  • Loading branch information
gaborbernat committed Oct 24, 2020
1 parent 03ad839 commit c8c74d1
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 11 deletions.
5 changes: 1 addition & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@ repos:
rev: 5.6.4
hooks:
- id: isort
- repo: https://github.com/ambv/black
- repo: https://github.com/psf/black
rev: 20.8b1
hooks:
- id: black
args: [--safe]
language_version: python3.8
- repo: https://github.com/asottile/blacken-docs
rev: v1.8.0
hooks:
- id: blacken-docs
additional_dependencies: [black==20.8b1]
language_version: python3.8
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.6.0
hooks:
Expand All @@ -50,4 +48,3 @@ repos:
hooks:
- id: flake8
additional_dependencies: ["flake8-bugbear == 20.1.4"]
language_version: python3.8
2 changes: 2 additions & 0 deletions docs/changelog/1995.feature.rst
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
setup(
use_scm_version={
"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"],
)
17 changes: 12 additions & 5 deletions src/virtualenv/discovery/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class Builtin(Discover):
def __init__(self, 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

@classmethod
Expand All @@ -25,18 +25,25 @@ def add_parser_arguments(cls, parser):
"--python",
dest="python",
metavar="py",
help="target interpreter for which to create a virtual (either absolute path or identifier string)",
default=sys.executable,
action="append",
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):
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):
return ensure_str(self.__unicode__())

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):
Expand Down
24 changes: 23 additions & 1 deletion tests/unit/discovery/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import logging
import os
import sys
from argparse import Namespace
from uuid import uuid4

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.info import fs_supports_symlink
from virtualenv.util.path import Path
Expand Down Expand Up @@ -53,3 +54,24 @@ def test_relative_path(tmp_path, session_app_data, monkeypatch):
relative = str(sys_executable.relative_to(cwd))
result = get_interpreter(relative, session_app_data)
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

0 comments on commit c8c74d1

Please sign in to comment.