Fallback functionality for interpreter discovery (#1995)
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
This commit is contained in:
parent
601b813e45
commit
aac61dfbaf
5 changed files with 39 additions and 11 deletions
|
|
@ -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
|
|
||||||
|
|
|
||||||
2
docs/changelog/1995.feature.rst
Normal file
2
docs/changelog/1995.feature.rst
Normal 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`.
|
||||||
2
setup.py
2
setup.py
|
|
@ -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"],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue