Skip to content

Commit

Permalink
Replace poetry shell command with poetry env activate (#9763)
Browse files Browse the repository at this point in the history
  • Loading branch information
Secrus authored Oct 28, 2024
1 parent 856e5f4 commit 6d6971e
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 367 deletions.
21 changes: 1 addition & 20 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -657,26 +657,7 @@ Note that this command has no option.

## shell

The shell command spawns a shell within the project's virtual environment.

By default, the current active shell is detected and used. Failing that,
the shell defined via the environment variable `SHELL` (on *nix) or
`COMSPEC` (on Windows) is used.

If a virtual environment does not exist, it will be created.

```bash
poetry shell
```

Note that this command starts a new shell and activates the virtual environment.

As such, `exit` should be used to properly exit the shell and the virtual environment instead of `deactivate`.

{{% note %}}
Poetry internally uses the [Shellingham](https://github.com/sarugaku/shellingham) project to detect current
active shell.
{{% /note %}}
The `shell` command was moved to a plugin: [`poetry-plugin-shell`](https://github.com/python-poetry/poetry-plugin-shell)

## check

Expand Down
38 changes: 38 additions & 0 deletions docs/managing-environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,44 @@ special `system` Python version to retrieve the default behavior:
poetry env use system
```

## Activating the environment

{{% note %}}
Looking for `poetry shell`? It was moved to a plugin: [`poetry-plugin-shell`](https://github.com/python-poetry/poetry-plugin-shell)
{{% /note %}}

The `poetry env activate` command prints the activate command of the virtual environment to the console.
You can run the output command manually or feed it to the eval command of your shell to activate the environment.
This way you won't leave the current shell.

{{< tabs tabTotal="3" tabID1="bash-csh-zsh" tabID2="fish" tabID3="powershell" tabName1="Bash/Zsh/Csh" tabName2="Fish" tabName3="Powershell" >}}

{{< tab tabID="bash-csh-zsh" >}}

```bash
$ eval $(poetry env activate)
(test-project-for-test) $ # Virtualenv entered
```

{{< /tab >}}
{{< tab tabID="fish" >}}

```bash
$ eval (poetry env activate)
(test-project-for-test) $ # Virtualenv entered
```

{{< /tab >}}
{{< tab tabID="powershell" >}}

```ps1
PS1> Invoke-Expression (poetry env activate)
(test-project-for-test) PS1> # Virtualenv entered
```

{{< /tab >}}
{{< /tabs >}}

## Displaying the environment information

If you want to get basic information about the currently activated virtual environment,
Expand Down
27 changes: 1 addition & 26 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ installer = "^0.7.0"
keyring = "^25.1.0"
# packaging uses calver, so version is unclamped
packaging = ">=24.0"
pexpect = "^4.7.0"
pkginfo = "^1.10"
platformdirs = ">=3.0.0,<5"
pyproject-hooks = "^1.0.0"
Expand Down Expand Up @@ -179,7 +178,6 @@ module = [
'deepdiff.*',
'fastjsonschema.*',
'httpretty.*',
'pexpect.*',
'requests_toolbelt.*',
'shellingham.*',
'virtualenv.*',
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/console/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ def _load() -> Command:
"remove",
"run",
"search",
"shell",
"show",
"update",
"version",
Expand All @@ -73,6 +72,7 @@ def _load() -> Command:
"debug info",
"debug resolve",
# Env commands
"env activate",
"env info",
"env list",
"env remove",
Expand Down
69 changes: 69 additions & 0 deletions src/poetry/console/commands/env/activate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import shlex

from typing import TYPE_CHECKING

import shellingham

from poetry.console.commands.command import Command
from poetry.utils._compat import WINDOWS


if TYPE_CHECKING:
from poetry.utils.env import Env


class ShellNotSupportedError(Exception):
"""Raised when a shell doesn't have an activator in virtual environment"""


class EnvActivateCommand(Command):
name = "env activate"
description = "Print the command to activate a virtual environment."

def handle(self) -> int:
from poetry.utils.env import EnvManager

env = EnvManager(self.poetry).get()

if command := self._get_activate_command(env):
self.line(command)
return 0
else:
raise ShellNotSupportedError(
"Discovered shell doesn't have an activator in virtual environment"
)

def _get_activate_command(self, env: Env) -> str:
try:
shell, _ = shellingham.detect_shell()
except shellingham.ShellDetectionFailure:
shell = ""
if shell == "fish":
command, filename = "source", "activate.fish"
elif shell == "nu":
command, filename = "overlay use", "activate.nu"
elif shell == "csh":
command, filename = "source", "activate.csh"
elif shell in ["powershell", "pwsh"]:
command, filename = ".", "Activate.ps1"
elif shell == "cmd":
command, filename = ".", "activate.bat"
else:
command, filename = "source", "activate"

if (activation_script := env.bin_dir / filename).exists():
if WINDOWS:
return f"{self._quote(str(activation_script), shell)}"
return f"{command} {self._quote(str(activation_script), shell)}"
return ""

@staticmethod
def _quote(command: str, shell: str) -> str:
if WINDOWS:
if shell == "cmd":
return f'"{command}"'
if shell in ["powershell", "pwsh"]:
return f'& "{command}"'
return shlex.quote(command)
57 changes: 0 additions & 57 deletions src/poetry/console/commands/shell.py

This file was deleted.

4 changes: 4 additions & 0 deletions src/poetry/utils/env/base_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ def __init__(self, path: Path, base: Path | None = None) -> None:

self._embedded_pip_path: Path | None = None

@property
def bin_dir(self) -> Path:
return self._bin_dir

@property
def path(self) -> Path:
return self._path
Expand Down
Loading

0 comments on commit 6d6971e

Please sign in to comment.