diff --git a/src/poetry/config/config.py b/src/poetry/config/config.py index 254666be20c..29ae160df7f 100644 --- a/src/poetry/config/config.py +++ b/src/poetry/config/config.py @@ -206,6 +206,13 @@ def _get_environment_repositories() -> dict[str, dict[str, str]]: def repository_cache_directory(self) -> Path: return Path(self.get("cache-dir")) / "cache" / "repositories" + @property + def virtualenvs_path(self) -> Path: + path = self.get("virtualenvs.path") + if path is None: + path = Path(self.get("cache-dir")) / "virtualenvs" + return Path(path).expanduser() + def get(self, setting_name: str, default: Any = None) -> Any: """ Retrieve a setting value. diff --git a/src/poetry/utils/env.py b/src/poetry/utils/env.py index b671c37253c..a045471e735 100644 --- a/src/poetry/utils/env.py +++ b/src/poetry/utils/env.py @@ -552,12 +552,7 @@ def _detect_active_python(self, io: IO) -> str | None: return executable def activate(self, python: str, io: IO) -> Env: - venv_path = self._poetry.config.get("virtualenvs.path") - if venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) - + venv_path = self._poetry.config.virtualenvs_path cwd = self._poetry.file.parent envs_file = TOMLFile(venv_path / self.ENVS_FILE) @@ -645,12 +640,7 @@ def activate(self, python: str, io: IO) -> Env: return self.get(reload=True) def deactivate(self, io: IO) -> None: - venv_path = self._poetry.config.get("virtualenvs.path") - if venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) - + venv_path = self._poetry.config.virtualenvs_path name = self._poetry.package.name name = self.generate_env_name(name, str(self._poetry.file.parent)) @@ -671,11 +661,7 @@ def get(self, reload: bool = False) -> Env: python_minor = ".".join([str(v) for v in sys.version_info[:2]]) - venv_path = self._poetry.config.get("virtualenvs.path") - if venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) + venv_path = self._poetry.config.virtualenvs_path cwd = self._poetry.file.parent envs_file = TOMLFile(venv_path / self.ENVS_FILE) @@ -712,11 +698,7 @@ def get(self, reload: bool = False) -> Env: if not create_venv: return self.get_system_env() - venv_path = self._poetry.config.get("virtualenvs.path") - if venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) + venv_path = self._poetry.config.virtualenvs_path name = f"{base_env_name}-py{python_minor.strip()}" @@ -741,13 +723,7 @@ def list(self, name: str | None = None) -> list[VirtualEnv]: name = self._poetry.package.name venv_name = self.generate_env_name(name, str(self._poetry.file.parent)) - - venv_path = self._poetry.config.get("virtualenvs.path") - if venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) - + venv_path = self._poetry.config.virtualenvs_path env_list = [ VirtualEnv(Path(p)) for p in sorted(venv_path.glob(f"{venv_name}-py*")) ] @@ -762,11 +738,7 @@ def list(self, name: str | None = None) -> list[VirtualEnv]: return env_list def remove(self, python: str) -> Env: - venv_path = self._poetry.config.get("virtualenvs.path") - if venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) + venv_path = self._poetry.config.virtualenvs_path cwd = self._poetry.file.parent envs_file = TOMLFile(venv_path / self.ENVS_FILE) @@ -875,7 +847,6 @@ def create_venv( create_venv = self._poetry.config.get("virtualenvs.create") root_venv = self._poetry.config.get("virtualenvs.in-project") - venv_path = self._poetry.config.get("virtualenvs.path") prefer_active_python = self._poetry.config.get( "virtualenvs.prefer-active-python" ) @@ -884,13 +855,7 @@ def create_venv( if not executable and prefer_active_python: executable = self._detect_active_python(io) - if root_venv: - venv_path = cwd / ".venv" - elif venv_path is None: - venv_path = self._poetry.config.get("cache-dir") / "virtualenvs" - else: - venv_path = Path(venv_path) - + venv_path = cwd / ".venv" if root_venv else self._poetry.config.virtualenvs_path if not name: name = self._poetry.package.name assert name is not None diff --git a/tests/config/test_config.py b/tests/config/test_config.py index 10dc8283c3b..ce691470585 100644 --- a/tests/config/test_config.py +++ b/tests/config/test_config.py @@ -3,6 +3,7 @@ import os import re +from pathlib import Path from typing import TYPE_CHECKING import pytest @@ -17,7 +18,6 @@ if TYPE_CHECKING: from collections.abc import Callable from collections.abc import Iterator - from pathlib import Path def get_options_based_on_normalizer(normalizer: Callable) -> str: @@ -66,3 +66,14 @@ def test_config_get_from_environment_variable( ): os.environ[env_var] = env_value assert config.get(name) is value + + +@pytest.mark.parametrize( + ("path_config", "expected"), + [("~/.venvs", Path.home() / ".venvs"), ("venv", Path("venv"))], +) +def test_config_expands_tilde_for_virtualenvs_path( + config: Config, path_config: str, expected: Path +): + config.merge({"virtualenvs": {"path": path_config}}) + assert config.virtualenvs_path == expected