From a2cc7d8ee7878f193d9a0117791d6dc768049c02 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Sun, 17 Jul 2022 07:49:24 +0800 Subject: [PATCH] fix: don't save python path for venv commands (#1231) * fix: don't save python path for venv commands * improve the error message * add test to cover changed code * fix test * reuse the saved python if possible --- news/1230.bugfix.md | 1 + pdm/cli/commands/venv/activate.py | 10 +++++++++- pdm/cli/commands/venv/backends.py | 7 +++++-- tests/cli/test_venv.py | 22 ++++++++++++++++++---- 4 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 news/1230.bugfix.md diff --git a/news/1230.bugfix.md b/news/1230.bugfix.md new file mode 100644 index 00000000..5edaa5cc --- /dev/null +++ b/news/1230.bugfix.md @@ -0,0 +1 @@ +Don't save python path for venv commands. diff --git a/pdm/cli/commands/venv/activate.py b/pdm/cli/commands/venv/activate.py index 109d69ac..2b29f93d 100644 --- a/pdm/cli/commands/venv/activate.py +++ b/pdm/cli/commands/venv/activate.py @@ -33,7 +33,15 @@ class ActivateCommand(BaseCommand): raise SystemExit(1) else: # Use what is saved in .pdm.toml - interpreter = project.python_executable + interpreter = project.project_config.get("python.path") + if not interpreter: + project.core.ui.echo( + "The project doesn't have a saved python.path. " + "Run [green]pdm use[/] to pick one.", + style="yellow", + err=True, + ) + raise SystemExit(1) venv = get_venv_like_prefix(interpreter) if venv is None: project.core.ui.echo( diff --git a/pdm/cli/commands/venv/backends.py b/pdm/cli/commands/venv/backends.py index 62e1d828..6cc1a5a2 100644 --- a/pdm/cli/commands/venv/backends.py +++ b/pdm/cli/commands/venv/backends.py @@ -26,11 +26,14 @@ class Backend(abc.ABC): @cached_property def _resolved_interpreter(self) -> PythonInfo: if not self.python: - return self.project.python + saved_python = self.project.project_config.get("python.path") + if saved_python: + return PythonInfo.from_path(saved_python) try: # pragma: no cover return next(iter(self.project.find_interpreters(self.python))) except StopIteration: # pragma: no cover - raise VirtualenvCreateError(f"Can't find python interpreter {self.python}") + python = f" {self.python}" if self.python else "" + raise VirtualenvCreateError(f"Can't resolve python interpreter{python}") @property def ident(self) -> str: diff --git a/tests/cli/test_venv.py b/tests/cli/test_venv.py index 2db2a1ce..db3de5b5 100644 --- a/tests/cli/test_venv.py +++ b/tests/cli/test_venv.py @@ -22,6 +22,7 @@ def fake_create(monkeypatch): @pytest.mark.usefixtures("fake_create") def test_venv_create(invoke, project): + project.project_config.pop("python.path", None) project.project_config["venv.in_project"] = False result = invoke(["venv", "create"], obj=project) assert result.exit_code == 0, result.stderr @@ -29,6 +30,7 @@ def test_venv_create(invoke, project): r"Virtualenv (.+) is created successfully", result.output ).group(1) assert os.path.exists(venv_path) + assert "python.path" not in project.project_config @pytest.mark.usefixtures("fake_create") @@ -109,6 +111,13 @@ def test_venv_activate(invoke, mocker, project): assert result.output.startswith("source") +def test_venv_activate_project_without_python(invoke, project): + project.project_config.pop("python.path", None) + result = invoke(["venv", "activate"], obj=project) + assert result.exit_code != 0 + assert "The project doesn't have a saved python.path" in result.stderr + + @pytest.mark.usefixtures("fake_create") def test_venv_activate_error(invoke, project): project.project_config["venv.in_project"] = False @@ -187,7 +196,6 @@ def test_venv_purge_interactive(invoke, user_choices, is_path_exists, project): def test_virtualenv_backend_create(project, mocker): - interpreter = project.python_executable backend = backends.VirtualenvBackend(project, None) assert backend.ident mock_call = mocker.patch("subprocess.check_call") @@ -202,20 +210,26 @@ def test_virtualenv_backend_create(project, mocker): "--no-wheel", str(location), "-p", - interpreter, + str(backend._resolved_interpreter.executable), ], stdout=ANY, ) def test_venv_backend_create(project, mocker): - interpreter = project.python_executable backend = backends.VenvBackend(project, None) assert backend.ident mock_call = mocker.patch("subprocess.check_call") location = backend.create() mock_call.assert_called_once_with( - [interpreter, "-m", "venv", "--without-pip", str(location)], stdout=ANY + [ + str(backend._resolved_interpreter.executable), + "-m", + "venv", + "--without-pip", + str(location), + ], + stdout=ANY, ) -- GitLab