-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
187 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# CLI usage | ||
|
||
Run `conda spawn --help` for details: | ||
|
||
```{program-output} python -m conda spawn --help | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# How-to guides | ||
|
||
(shell-cleanup)= | ||
## Clean up your shell initialization logic | ||
|
||
Since `conda-spawn` only relies on the `conda` entry point being on `PATH`, you will probably want to remove all the shell initialization stuff from your shell profiles with: | ||
|
||
```bash | ||
conda init --reverse | ||
``` | ||
|
||
Then, make sure you have added `$CONDA_ROOT/condabin` to your PATH, with `$CONDA_ROOT` being the path to your conda installation. For example, assuming you installed `conda` in `~/conda`, your `~/.bashrc` would only need this line: | ||
|
||
```bash | ||
export PATH="${PATH}:${HOME}/conda/condabin" | ||
``` | ||
|
||
On Windows, open the Start Menu and search for "environment variables". You will be able to add the equivalent location (e.g. `C:\Users\username\conda\condabin`) to the `PATH` variable via the UI. | ||
|
||
(in-script)= | ||
## Activate an environment inside a shell script | ||
|
||
For in-script usage, please consider these replacements for `conda activate`: | ||
|
||
For Unix shell scripts: | ||
|
||
```bash | ||
eval "$(conda spawn --hook --shell posix -n <ENV-NAME>)" | ||
``` | ||
|
||
For Windows CMD scripts: | ||
|
||
```batch | ||
FOR /F "tokens=*" %%g IN ('conda spawn --hook --shell cmd -n <ENV-NAME>') do @CALL %%g | ||
``` | ||
|
||
For Windows Powershell scripts: | ||
|
||
```powershell | ||
conda spawn --hook --shell powershell -n <ENV-NAME> | Out-String | Invoke-Expression | ||
``` | ||
|
||
For example, if you want to create a new environment and activate it, it would look like this: | ||
|
||
```bash | ||
# Assumes `conda` is in PATH | ||
conda create -n new-env python numpy | ||
eval "$(conda spawn --hook --shell powershell -n new-env)" | ||
python -c "import numpy" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Quickstart | ||
|
||
## What is this? | ||
|
||
`conda spawn` is a replacement subcommand for the `conda activate` and `conda deactivate` workflow. | ||
|
||
Instead of writing state to your current shell session, `conda spawn -n ENV-NAME` starts a new shell with your activated environment. To deactivate, exit the process with <kbd>Ctrl</kbd>+<kbd>D</kbd>, or run the command `exit`. | ||
|
||
The typical workflow looks like this: | ||
|
||
```bash | ||
~ $ which python | ||
python not found | ||
~ $ which conda | ||
/Users/user/Miniforge/condabin/conda | ||
~ $ conda spawn -n base | ||
(base) ~ $ which python | ||
/Users/user/Miniforge/bin/python | ||
(base) ~ $ python my_project.py | ||
working ... | ||
ok! | ||
(base) ~ $ export VAR=1 | ||
(base) ~ $ echo $VAR | ||
1 | ||
(base) ~ $ exit | ||
~ $ echo $VAR | ||
|
||
~ $ | ||
``` | ||
|
||
As you can see, variables set during the `spawn`ed shell session do not leak in the parent session once closed with `exit`. If you have used `poetry shell` or `pixi shell`, this is essentially the same but for `conda`. | ||
|
||
## Installation | ||
|
||
This is a `conda` plugin and goes in the `base` environment: | ||
|
||
```bash | ||
conda install -n base conda-forge::conda-spawn | ||
``` | ||
|
||
After this, you might want to {ref}`shell-cleanup`. | ||
|
||
## Usage | ||
|
||
To activate an environment named `my-project`: | ||
|
||
```bash | ||
conda spawn -n my-project | ||
``` | ||
|
||
To deactivate, exit the process with <kbd>Ctrl</kbd>+<kbd>D</kbd>, or run the command `exit`. | ||
|
||
|
||
## Why? | ||
|
||
The main reasons include: | ||
|
||
- Cleaner shell interaction with no need for a `conda` shell function. | ||
- Avoid messing with existing shell processes. | ||
- Faster shell startup when `conda` is not needed. | ||
- Simpler installation and bookkeeping. | ||
|
||
Do you want to learn more? Head over to {doc}`why`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Motivation and vision | ||
|
||
## Motivation | ||
|
||
The `conda activate` and `conda deactivate` subcommands were inspired by the `virtualenv` workflow, which implied `source`-ing a shell script shipped in the virtual environment directory. Initially implemented as `source activate` and `source deactivate`, these subcommands were promoted to the `conda` command namespace in [version 4.4.0](https://github.com/conda/conda/blob/main/CHANGELOG.md#440-2017-12-20). | ||
|
||
The 4.4.0 activation workflow is still used in `conda` (as of 25.1) and it goes a long way to provide the possibility of modifying the shell session in place. `conda activate` will modify `PATH`, inject a few environment variables and run some activation scripts. Then, `conda deactivate` needs to undo this. That's a lot of work (and code to maintain), specially considering we can accomplish the same thing in an easier way by starting a new shell with the needed modifications and then discarding the process once done. No cleanup necessary! | ||
|
||
However, that's not all. In order to provide in-process shell state updates, the `conda` Python entry point needs to be wrapped by a `conda` shell function that intercepts the subcommands and dispatches to either shell subcommands or regular Python subcommands. _Installing_ that shell function cannot be handled by regular Python packaging operations, so a block of code is injected in your shell profile (or platform equivalent). This is what `conda` calls "initialize your shell", as provided in `conda init`. | ||
|
||
The `conda` shell function wrapper and the initialization logic have a non-negligible maintenance cost, add testing burden, obfuscate the application model, and, more importantly, complicate the end-user installation in a very invasive way: the shell startup profile needs a block of code to define the `conda` shell function and auto-activation mechanisms. This has a non-negligible cost every time you start a login shell and leaves residual information on uninstalls. | ||
|
||
## Vision | ||
|
||
This project is inspired by the workflows implemented in `poetry shell` and `pixi shell`. These workflows prove that no shell initialization logic is needed for effective virtual environment management. | ||
|
||
The idea is to start new shell processes and then run the activation logic inside them. Once done, the user exits the process and returns to the parent session. This requires no shell function wrapper, which renders all the logic in `conda init` unnecessary; we only need `$CONDA_ROOT/condabin` in `PATH` so we can cleanly find the `conda` entry point. | ||
|
||
For now, this idea is distributed as an optional plugin. If proven successful and it's well received by the community, we would propose adding it as a default `conda` plugin and suggest deprecating the old workflow (`conda init`, `activate` and `deactivate`). | ||
|
||
## References | ||
|
||
- [`poetry shell` plugin](https://github.com/python-poetry/poetry-plugin-shell) | ||
- [conda deep dives: `conda init` and `conda activate`](https://docs.conda.io/projects/conda/en/24.11.x/dev-guide/deep-dives/activation.html) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters