diff --git a/src/poetry/utils/env.py b/src/poetry/utils/env.py index 36f2f0e598a..544e5fe78ae 100644 --- a/src/poetry/utils/env.py +++ b/src/poetry/utils/env.py @@ -450,6 +450,17 @@ def __init__(self, expected: str, given: str | None = None) -> None: super().__init__(message) +class InvalidCurrentPythonVersionError(EnvError): + def __init__(self, expected: str, given: str) -> 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.' + ) + + super().__init__(message) + + class EnvManager: """ Environments manager @@ -809,6 +820,13 @@ def create_venv( if env.is_venv() and not force: # Already inside a virtualenv. + current_python = Version.parse( + ".".join(str(c) for c in env.version_info[:3]) + ) + if not self._poetry.package.python_constraint.allows(current_python): + raise InvalidCurrentPythonVersionError( + self._poetry.package.python_versions, str(current_python) + ) return env create_venv = self._poetry.config.get("virtualenvs.create") diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py index 5e4ebef1ace..e92f391e1fe 100644 --- a/tests/utils/test_env.py +++ b/tests/utils/test_env.py @@ -24,6 +24,7 @@ from poetry.utils.env import EnvCommandError from poetry.utils.env import EnvManager from poetry.utils.env import GenericEnv +from poetry.utils.env import InvalidCurrentPythonVersionError from poetry.utils.env import NoCompatiblePythonVersionFound from poetry.utils.env import SystemEnv from poetry.utils.env import VirtualEnv @@ -993,6 +994,33 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( ) +def test_create_venv_fails_if_current_python_version_is_not_supported( + manager: EnvManager, poetry: "Poetry" +): + if "VIRTUAL_ENV" in os.environ: + del os.environ["VIRTUAL_ENV"] + + manager.create_venv(NullIO()) + + current_version = Version.parse(".".join(str(c) for c in sys.version_info[:3])) + next_version = ".".join( + str(c) for c in (current_version.major, current_version.minor + 1, 0) + ) + package_version = "~" + next_version + poetry.package.python_versions = package_version + + with pytest.raises(InvalidCurrentPythonVersionError) as e: + manager.create_venv(NullIO()) + + expected_message = ( + f"Current Python version ({current_version}) is not allowed by the project" + f' ({package_version}).\nPlease change python executable via the "env use"' + " command." + ) + + assert expected_message == str(e.value) + + def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( manager: EnvManager, poetry: Poetry,