Skip to content

Commit

Permalink
cli/env: handle removal of in-project venv
Browse files Browse the repository at this point in the history
Resolves: #2124
  • Loading branch information
abn committed Mar 5, 2024
1 parent 374babb commit 0007b0e
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 7 deletions.
9 changes: 9 additions & 0 deletions docs/managing-environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,12 @@ poetry env remove --all
```

If you remove the currently activated virtual environment, it will be automatically deactivated.

{{% note %}}
If you use the [`virtualenvs.in-project`]({{< relref "configuration#virtualenvsin-project" >}}) configuration, you
can simply use the command as shown below.

```bash
poetry env remove
```
{{% /note %}}
18 changes: 12 additions & 6 deletions src/poetry/console/commands/env/remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,30 @@ class EnvRemoveCommand(Command):
def handle(self) -> int:
from poetry.utils.env import EnvManager

is_in_project = self.poetry.config.get("virtualenvs.in-project")

pythons = self.argument("python")
all = self.option("all")
if not (pythons or all):
remove_all_envs = self.option("all")

if not (pythons or remove_all_envs or is_in_project):
self.line("No virtualenv provided.")

manager = EnvManager(self.poetry)
# TODO: refactor env.py to allow removal with one loop
for python in pythons:
venv = manager.remove(python)
self.line(f"Deleted virtualenv: <comment>{venv.path}</comment>")
if all:
if remove_all_envs or is_in_project:
for venv in manager.list():
manager.remove_venv(venv.path)
self.line(f"Deleted virtualenv: <comment>{venv.path}</comment>")
if not is_in_project or venv.path.is_relative_to(
self.poetry.pyproject_path.parent
):
manager.remove_venv(venv.path)
self.line(f"Deleted virtualenv: <comment>{venv.path}</comment>")
# Since we remove all the virtualenvs, we can also remove the entry
# in the envs file. (Strictly speaking, we should do this explicitly,
# in case it points to a virtualenv that had been removed manually before.)
if manager.envs_file.exists():
if remove_all_envs and manager.envs_file.exists():
manager.envs_file.remove_section(manager.base_env_name)

return 0
3 changes: 2 additions & 1 deletion tests/console/commands/env/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def venvs_in_project_dir(app: PoetryTestApplication) -> Iterator[Path]:
try:
yield venv_dir
finally:
venv_dir.rmdir()
if venv_dir.exists():
venv_dir.rmdir()


@pytest.fixture
Expand Down
11 changes: 11 additions & 0 deletions tests/console/commands/env/test_remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,14 @@ def test_remove_multiple(
for name in remaining_envs:
assert (venv_cache / name).exists()
assert set(tester.io.fetch_output().split("\n")) == expected


def test_remove_in_project(tester: CommandTester, venvs_in_project_dir: Path) -> None:
assert venvs_in_project_dir.exists()

tester.execute()

assert not venvs_in_project_dir.exists()

expected = f"Deleted virtualenv: {venvs_in_project_dir}\n"
assert tester.io.fetch_output() == expected

0 comments on commit 0007b0e

Please sign in to comment.