bug-guix
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#59774: Activating conda environments breaks the prompt because bash


From: Hugo Buddelmeijer
Subject: bug#59774: Activating conda environments breaks the prompt because bash eats PS1
Date: Fri, 2 Dec 2022 13:47:52 +0100

Hi all,

### Summary ####

Activating a conda environment on guix will break your bash prompt, because guix' binary-replacing-bash-script eats PS1.


### Reproduce ####

E.g.:

# Start a container with conda
hugo@alex ~/t $ guix shell -C conda sudo bash

# Add conda functions to ~/.bashrc. This raises errors but does work.
hugo@alex ~/t [env]$ conda init bash
# ignore the errors

# Add the functions to bash. This activates the conda environment called "base".
hugo@alex ~/t [env]$ source ~/.bashrc
sh: dirname: command not found
sh: dirname: command not found
(base)

# Deactivate the environment.
(base) conda deactivate


### Actual and expected behaviour ###

The prompt is now empty. The expected result is that the "(base)" string is prefixed to the prompt when activating an environment (or replaced when switching environments). "base" is the default environment. The string should be removed when the environment is deactivated.

However, instead, upon activating an environment, the entire prompt is replaced with "(base)". Deactivating the environment removes the string, resulting in an empty prompt.


### Cause ###

The cause of the disappearing prompt is due to an interplay between conda and guix and bash. Normally, "conda" is either a binary executable, or a bash function, but in guix it can also be a bash script.

What normally happens after installing conda is:
- The user calls "conda init bash". This is the binary executable "conda", which adds the "conda" bash function to ~/.bashrc. This is only done once for each user, after which the shell is restarted.

What normally happens in a user session is:
- The shell implicitly calls "conda activate base" through ~/.bashrc, or the user calls it explicitly (usually not with "base", but with their own environment). This "conda" is the conda bash function.
- The conda bash function calls the conda binary, passing PS1 (and other variables).
- The conda binary uses PS1 to construct a new string to be used as a prompt, and returns that to the conda bash function.
- The conda bash function uses the output from the conda binary to set PS1. It also makes a backup of PS1 in CONDA_PS1_BACKUP.

But in guix, the conda binary is renamed to conda_real, and is replaced with [by?] the conda bash script. Therefore this happens:
- The conda shell function is called through "conda activate base".
- The conda shell function calls the conda bash script. The conda bash script eats PS1 because it is non-interactive.
- The conda bash script calls the conda_real binary, specifying an empty PS1.
- The conda_real binary adds the "(base)" prefix to the empty string and returns the string to the conda bash script.
- The conda bash script returns the string to the conda bash function.
- The conda bash function sets PS1 to the new string, which is just "(base)".


### Workaround ###

My personal workaround is to skip the "conda init bash" step entirely, but do something equivalent manually:
- Call "conda shell.bash hook" and store the output in ~/.conda_shell.bash_hook.sh .
- Replace the "$CONDA_EXE" at the top of the file with "${HOME}/.guix-profile/bin/conda"; otherwise it contains an absolute path, including a guix hash. (This is another problem, I now realize.)
- Add "--norc -i" to every "$CONDA_EXE" call in that file.
- Add ". ~/.conda_shell.bash_hook.sh" to ~/.bash_profile (has to be .bash_profile and not .bashrc because otherwise it would be called from the conda bash script, leading to recursion).

The crux is that now it calls the conda bash script (created by guix) with the -i flag (interactive mode), which prevents PS1 from being eaten. The --norc prevents .bash_profile from being read again, thereby preventing recursion.


### Proper Solution ###

I can see two possible proper solutions; but I cannot vouch for the feasibility in guix.

1) Use another shell than bash for the executable-replacing-script of the conda package. Only bash eats PS1, other POSIX-compliant shells do not; e.g. dash. Is it possible to use another shell than bash for guix packages?

2) "conda shell.bash hook" uses the contents of /etc/profile.d/conda.sh to create the conda bash function. Perhaps it would be possible to patch that file to include the "--norc -i" flags. Maybe this would also require placing the "conda init" output in ".bash_profile"
 instead of ".bashrc", not sure.


### Disclaimer ###

My ultimate goal is to ditch conda altogether and use guix instead. However, it will take a while to convince everyone. In the meantime it would help to have conda running well. That would also make it easier to attract conda package maintainers.


Cheers,
Hugo













reply via email to

[Prev in Thread] Current Thread [Next in Thread]