From 2aa1503f544446844fdf32b76c5fde5fd8292554 Mon Sep 17 00:00:00 2001 From: lyijian86-source Date: Sat, 6 Jun 2026 20:36:58 +0800 Subject: [PATCH] fix(env): fail on incompatible Python without venv creation --- src/poetry/utils/env/env_manager.py | 8 +++++ src/poetry/utils/env/python/exceptions.py | 4 ++- tests/utils/env/test_env_manager.py | 41 +++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/poetry/utils/env/env_manager.py b/src/poetry/utils/env/env_manager.py index 2087b1b3f6e..6f9e17aab9d 100644 --- a/src/poetry/utils/env/env_manager.py +++ b/src/poetry/utils/env/env_manager.py @@ -421,6 +421,14 @@ def create_venv( python.patch_version.to_string(), ) + if create_venv is False: + raise InvalidCurrentPythonVersionError( + self._poetry.package.python_versions, + python.patch_version.to_string(), + "Poetry cannot switch to a compatible Python version because " + "virtualenv creation is disabled.", + ) + self._io.write_error_line( f"The currently activated Python version {python.patch_version.to_string()} is not" f" supported by the project ({self._poetry.package.python_versions}).\n" diff --git a/src/poetry/utils/env/python/exceptions.py b/src/poetry/utils/env/python/exceptions.py index 1663df16b50..fa7aa6eb29e 100644 --- a/src/poetry/utils/env/python/exceptions.py +++ b/src/poetry/utils/env/python/exceptions.py @@ -31,11 +31,13 @@ def __init__(self, expected: str, given: str | None = None) -> None: class InvalidCurrentPythonVersionError(PythonVersionError): - def __init__(self, expected: str, given: str) -> None: + def __init__(self, expected: str, given: str, note: str | None = None) -> None: message = ( f"Current Python version ({given}) " f"is not allowed by the project ({expected}).\n" 'Please change python executable via the "env use" command.' ) + if note is not None: + message = f"{message}\n{note}" super().__init__(message) diff --git a/tests/utils/env/test_env_manager.py b/tests/utils/env/test_env_manager.py index 3e990e81872..0f5a5f1ca1c 100644 --- a/tests/utils/env/test_env_manager.py +++ b/tests/utils/env/test_env_manager.py @@ -32,6 +32,7 @@ from collections.abc import Iterator from unittest.mock import MagicMock + from _pytest.monkeypatch import MonkeyPatch from cleo.io.buffered_io import BufferedIO from pytest import LogCaptureFixture from pytest_mock import MockerFixture @@ -1069,6 +1070,46 @@ def test_create_venv_fails_if_no_compatible_python_version_could_be_found( assert m.call_count == 0 +def test_create_venv_fails_if_current_python_is_not_supported_without_creating_venv( + manager: EnvManager, + poetry: Poetry, + config: Config, + mocker: MockerFixture, + mocked_python_register: MockedPythonRegister, + monkeypatch: MonkeyPatch, +) -> None: + config.config["virtualenvs"]["create"] = False + monkeypatch.delenv("VIRTUAL_ENV", raising=False) + + poetry.package.python_versions = "^3.10" + + current_python = mocked_python_register("3.9.0") + compatible_python = mocked_python_register("3.10.0") + mocker.patch( + "poetry.utils.env.env_manager.Python.get_preferred_python", + return_value=current_python, + ) + get_compatible_python = mocker.patch( + "poetry.utils.env.env_manager.Python.get_compatible_python", + return_value=compatible_python, + ) + build_venv = mocker.patch("poetry.utils.env.EnvManager.build_venv") + + with pytest.raises(InvalidCurrentPythonVersionError) as e: + manager.create_venv() + + expected_message = ( + "Current Python version (3.9.0) is not allowed by the project (^3.10).\n" + 'Please change python executable via the "env use" command.\n' + "Poetry cannot switch to a compatible Python version because virtualenv " + "creation is disabled." + ) + + assert str(e.value) == expected_message + get_compatible_python.assert_not_called() + build_venv.assert_not_called() + + @pytest.mark.parametrize("use_poetry_python", [True, False]) def test_create_venv_does_not_try_to_find_compatible_versions_with_executable( manager: EnvManager,