diff --git a/src/poetry/config/config.py b/src/poetry/config/config.py index 636fa2097dd..86a863b0e7a 100644 --- a/src/poetry/config/config.py +++ b/src/poetry/config/config.py @@ -38,6 +38,7 @@ class Config: "in-project": None, "path": os.path.join("{cache-dir}", "virtualenvs"), "options": {"always-copy": False, "system-site-packages": False}, + "prefer-shell-python": False, }, "experimental": {"new-installer": True}, "installer": {"parallel": True, "max-workers": None}, @@ -138,6 +139,7 @@ def _get_normalizer(name: str) -> Callable: "virtualenvs.in-project", "virtualenvs.options.always-copy", "virtualenvs.options.system-site-packages", + "virtualenvs.options.prefer-shell-python", "experimental.new-installer", "installer.parallel", }: diff --git a/src/poetry/console/application.py b/src/poetry/console/application.py index 80cde5dcfb7..94adddd1fba 100644 --- a/src/poetry/console/application.py +++ b/src/poetry/console/application.py @@ -1,4 +1,3 @@ -import contextlib import logging import re import subprocess @@ -19,6 +18,7 @@ from cleo.exceptions import CleoException from cleo.formatters.style import Style from cleo.io.inputs.argv_input import ArgvInput +from cleo.io.outputs.output import Verbosity from poetry.core.utils._compat import PY37 from poetry.__version__ import __version__ @@ -229,6 +229,30 @@ def _configure_io(self, io: "IO") -> None: return super()._configure_io(io) + def _detect_active_python(self, io: "IO") -> str: + executable = None + + try: + io.write_line( + "Trying to detect current active python executable as specified in the config.", + verbosity=Verbosity.VERBOSE, + ) + executable = decode( + subprocess.check_output( + list_to_shell_command( + ["python", "-c", '"import sys; print(sys.executable)"'] + ), + shell=True, + ).strip() + ) + io.write_line(f"Found: {executable}", verbosity=Verbosity.VERBOSE) + except CalledProcessError: + io.write_line( + "Unable to detect the current active python executable. Falling back to default.", + verbosity=Verbosity.VERBOSE, + ) + return executable + def register_command_loggers( self, event: "ConsoleCommandEvent", event_name: str, _: Any ) -> None: @@ -287,28 +311,17 @@ def configure_env( io = event.io poetry = command.poetry - executable = None - find_compatible = None - - # add on option to trigger this - with contextlib.suppress(CalledProcessError): - executable = decode( - subprocess.check_output( - list_to_shell_command( - [ - "python", - "-c", - '"import sys; print(sys.executable)"', - ] - ), - shell=True, - ).strip() - ) - find_compatible = True + executable = ( + self._detect_active_python(io) + if poetry.config.get("virtualenvs.prefer-shell-python") + else None + ) env_manager = EnvManager(poetry) env = env_manager.create_venv( - io, executable=executable, find_compatible=find_compatible + io, + executable=executable, + find_compatible=True if executable else None, ) if env.is_venv() and io.is_verbose(): diff --git a/src/poetry/console/commands/config.py b/src/poetry/console/commands/config.py index 96df3cd4514..a8f78867757 100644 --- a/src/poetry/console/commands/config.py +++ b/src/poetry/console/commands/config.py @@ -78,6 +78,11 @@ def unique_config_values(self) -> Dict[str, Tuple[Any, Any, Any]]: lambda val: str(Path(val)), str(Path(CACHE_DIR) / "virtualenvs"), ), + "virtualenvs.prefer-shell-python": ( + boolean_validator, + boolean_normalizer, + False, + ), "experimental.new-installer": ( boolean_validator, boolean_normalizer, diff --git a/tests/console/commands/test_config.py b/tests/console/commands/test_config.py index 3278b19a170..9aca2b3d78a 100644 --- a/tests/console/commands/test_config.py +++ b/tests/console/commands/test_config.py @@ -56,6 +56,7 @@ def test_list_displays_default_value_if_not_set( virtualenvs.options.always-copy = false virtualenvs.options.system-site-packages = false virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} +virtualenvs.prefer-shell-python = false """ assert expected == tester.io.fetch_output() @@ -79,6 +80,7 @@ def test_list_displays_set_get_setting( virtualenvs.options.always-copy = false virtualenvs.options.system-site-packages = false virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} +virtualenvs.prefer-shell-python = false """ assert config.set_config_source.call_count == 0 @@ -126,6 +128,7 @@ def test_list_displays_set_get_local_setting( virtualenvs.options.always-copy = false virtualenvs.options.system-site-packages = false virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} +virtualenvs.prefer-shell-python = false """ assert config.set_config_source.call_count == 1