3

When I activate a Python virtualenv with workon, my prompt does not change to identify the environment.

I've confirmed that my activate script contains

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
    _OLD_VIRTUAL_PS1="$PS1"
    if [ "x" != x ] ; then
        PS1="$PS1"
    else
        PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"
    fi
    export PS1
fi

and that VIRTUAL_ENV_DISABLE_PROMPT is unset.

Why would this be happening and what can I do to fix it?


GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)


I've got some fancy footwork going on in my .bash_profile, but I don't see why any of this should matter once the prompt has been set:

declare PSCOLORPATH='\[\e[0;33m\]'
declare PSCOLORPROMPT='\[\e[1;32m\]'
declare PSCOLORHOST='\[\e[0;32m\]'
declare PSCOLOROOT='\[\e[1;31m\]'
declare PSCOLOREND='\[\e[m\]'
#echo $PSCOLORPATH
if [ $SSH_FLAG -eq 1 ] ; then
    declare PSHOST='\h:'
else
    declare PSHOST=''
fi
if [ $IS_SU -eq 1 ] ; then
    PS1_INFO="$PSCOLOROOT[SU] $PSCOLORHOST$PSHOST$PSCOLORPATH\w"
else
    PS1_INFO="$PSCOLORHOST$PSHOST$PSCOLORPATH\w"
fi
PS1_PROMPT="$PSCOLORPROMPT \\$ $PSCOLOREND"
declare -x PS1="$PS1_INFO$PS1_PROMPT"
#declare -x PS1="$PSCOLORHOST$PSHOST$PSCOLORPATH\w $PSCOLORPROMPT\\$ $PSCOLOREND"
declare -x PS2="$PSCOLORPROMPT> $PSCOLOREND"
declare -x PS4="$PSCOLORPROMPT+ $PSCOLOREND"

source $(brew --repository)/etc/bash_completion.d/git-prompt.sh

GIT_PS1_HIDE_IF_PWD_IGNORED=1
PS1_NORMAL=$PS1
_gitprompt () {
    if [ "$1" = "off" ]; then
        GIT_PS1_SHOWUPSTREAM=; GIT_PS1_SHOWDIRTYSTATE=; GIT_PS1_SHOWUNTRACKEDFILES=; GIT_PS1_SHOWCOLORHINTS=;
        PS1="$PS1_NORMAL"; PROMPT_COMMAND=; 
    else
        if [ "$1" = "verbose" ]; then
            GIT_PS1_SHOWUPSTREAM="auto"; GIT_PS1_SHOWDIRTYSTATE=1; GIT_PS1_SHOWUNTRACKEDFILES=1; GIT_PS1_SHOWCOLORHINTS=;
            PROMPT_COMMAND='__git_ps1 "$PS1_INFO" "$PS1_PROMPT"';           
        elif [ "$1" = "color" ]; then
            GIT_PS1_SHOWUPSTREAM=; GIT_PS1_SHOWDIRTYSTATE=; GIT_PS1_SHOWUNTRACKEDFILES=; GIT_PS1_SHOWCOLORHINTS=1;
            PROMPT_COMMAND='__git_ps1 "$PS1_INFO$PSCOLOREND" "$PS1_PROMPT"';            
        else
            GIT_PS1_SHOWUPSTREAM=; GIT_PS1_SHOWDIRTYSTATE=; GIT_PS1_SHOWUNTRACKEDFILES=; GIT_PS1_SHOWCOLORHINTS=;
            PROMPT_COMMAND='__git_ps1 "$PS1_INFO" "$PS1_PROMPT"';
        fi
    fi
}
alias gitprompt="_gitprompt"

gitprompt verbose

FWIW, set -x; source /path/to/activate gives:

+ __git_ps1 '\[\e[0;32m\]\[\e[0;33m\]\w' '\[\e[1;32m\] \$ \[\e[m\]'
+ local exit=126
+ local pcmode=no
+ local detached=no
+ local 'ps1pc_start=\u@\h:\w '
+ local 'ps1pc_end=\$ '
+ local 'printf_format= (%s)'
+ case "$#" in
+ pcmode=yes
+ ps1pc_start='\[\e[0;32m\]\[\e[0;33m\]\w'
+ ps1pc_end='\[\e[1;32m\] \$ \[\e[m\]'
+ printf_format=' (%s)'
+ PS1='\[\e[0;32m\]\[\e[0;33m\]\w\[\e[1;32m\] \$ \[\e[m\]'
+ local ps1_expanded=yes
+ '[' -z '' ']'
+ '[' -z '3.2.57(1)-release' ']'
+ shopt -q promptvars
+ local repo_info rev_parse_exit_code
+ git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree --short HEAD
+ repo_info=
+ rev_parse_exit_code=128
+ '[' -z '' ']'
+ return 126
~ $ set -x; source ~/Documents/Projects/Coding/Python/venvs/zoot/bin/activate
+ set -x
+ source /Users/Rax/Documents/Projects/Coding/Python/venvs/zoot/bin/activate
+ deactivate nondestructive
+ unset -f pydoc
+ '[' -z _ ']'
+ PATH=/Users/Rax/.cabal/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Rax/bin:/opt/X11/bin:/Library/TeX/texbin
+ export PATH
+ unset _OLD_VIRTUAL_PATH
+ '[' -z '' ']'
+ '[' -n /bin/bash ']'
+ hash -r
+ '[' -z _ ']'
+ PS1='\[\e[0;32m\]\[\e[0;33m\]\w\[\e[1;32m\] \$ \[\e[m\]'
+ export PS1
+ unset _OLD_VIRTUAL_PS1
+ unset VIRTUAL_ENV
+ '[' '!' nondestructive = nondestructive ']'
+ VIRTUAL_ENV=/Users/Rax/Documents/Projects/Coding/Python/venvs/zoot
+ export VIRTUAL_ENV
+ _OLD_VIRTUAL_PATH=/Users/Rax/.cabal/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Rax/bin:/opt/X11/bin:/Library/TeX/texbin
+ PATH=/Users/Rax/Documents/Projects/Coding/Python/venvs/zoot/bin:/Users/Rax/.cabal/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Rax/bin:/opt/X11/bin:/Library/TeX/texbin
+ export PATH
+ '[' -z '' ']'
+ '[' -z '' ']'
+ _OLD_VIRTUAL_PS1='\[\e[0;32m\]\[\e[0;33m\]\w\[\e[1;32m\] \$ \[\e[m\]'
+ '[' x '!=' x ']'
+ basename /Users/Rax/Documents/Projects/Coding/Python/venvs/zoot
+ PS1='(zoot) \[\e[0;32m\]\[\e[0;33m\]\w\[\e[1;32m\] \$ \[\e[m\]'
+ export PS1
+ alias pydoc
+ '[' -n /bin/bash ']'
+ hash -r
+ __git_ps1 '\[\e[0;32m\]\[\e[0;33m\]\w' '\[\e[1;32m\] \$ \[\e[m\]'
+ local exit=0
+ local pcmode=no
+ local detached=no
+ local 'ps1pc_start=\u@\h:\w '
+ local 'ps1pc_end=\$ '
+ local 'printf_format= (%s)'
+ case "$#" in
+ pcmode=yes
+ ps1pc_start='\[\e[0;32m\]\[\e[0;33m\]\w'
+ ps1pc_end='\[\e[1;32m\] \$ \[\e[m\]'
+ printf_format=' (%s)'
+ PS1='\[\e[0;32m\]\[\e[0;33m\]\w\[\e[1;32m\] \$ \[\e[m\]'
+ local ps1_expanded=yes
+ '[' -z '' ']'
+ '[' -z '3.2.57(1)-release' ']'
+ shopt -q promptvars
+ local repo_info rev_parse_exit_code
+ git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree --short HEAD
+ repo_info=
+ rev_parse_exit_code=128
+ '[' -z '' ']'
+ return 0
Andrea Corbellini
  • 17,339
  • 3
  • 53
  • 69
orome
  • 45,163
  • 57
  • 202
  • 418

4 Answers4

4

In your .bash_profile you are calling gitprompt verbose that in turn is setting:

PROMPT_COMMAND='__git_ps1 "$PS1_INFO" "$PS1_PROMPT"'

I don't know what __git_ps1 is, but from the output of set -x; source ... I can tell that it is the culprit:

+ hash -r  # <<< This is the last command executed by the 'activate' script
+ __git_ps1 '\[\e[0;32m\]\[\e[0;33m\]\w' '\[\e[1;32m\] \$ \[\e[m\]'  # <<< This is PROMPT_COMMAND being called
...
+ PS1='\[\e[0;32m\]\[\e[0;33m\]\w\[\e[1;32m\] \$ \[\e[m\]'  # <<< This is PS1 getting restored
...

Here you have a few options, choose the one you prefer:

  • modify activate and add a line to unset PROMPT_COMMAND;
  • modify __git_ps1 (if you can) so that it doesn't touch PS1 when VIRTUAL_ENV is set;
  • if you can't modify __git_ps1, then write a wrapper around it;
  • manually unset PROMPT_COMMAND before entering a virtualenv;
  • avoid calling gitprompt in your .bash_profile.
Andrea Corbellini
  • 17,339
  • 3
  • 53
  • 69
  • Note: I've updated the output I see from `et -x; source ...` (there was a lot of garbage in the earlier version). – orome Apr 06 '16 at 18:15
  • @raxacoricofallapatorius: that garbage was actually useful :) – Andrea Corbellini Apr 06 '16 at 18:15
  • It looks like `PROMPT_COMMAND` [is the issue](http://stackoverflow.com/a/3058366/656912), but I'm not sure how to address that (since virtualenv uses `PS1`). – orome Apr 06 '16 at 18:18
  • @raxacoricofallapatorius: I provided a few options. If you need help with any of them, just ask – Andrea Corbellini Apr 06 '16 at 18:19
  • This is really a bug/limitation in virtualenv. It should check whether `PROMPT_COMMAND` is in use and use that instead of `PS1` if it is. All I can do is `unset PROMPT_COMMAND` whenever I start a virtualenv. That needs to happen early in every `activate` though. Is there a way to achieve that? (In fact I'd like to unset and it then and restore it when I deactivate.) – orome Apr 06 '16 at 18:29
  • You can do that by editing `activate` and `deactivate` – Andrea Corbellini Apr 06 '16 at 18:44
  • For each virtualenv? – orome Apr 06 '16 at 18:46
  • FWIW, I've modified the `PROMPT_COMMAND='__git_ps1 ...` lines in my profile to `PROMPT_COMMAND='__venv_prefix; __git_ps1 ...`, where I've defined `__venv_prefix` as a shell function that (if appropriate) does `printf "(basename \"$VIRTUAL_ENV\")"`. This solves the problem, though it does cause some extra hesitation when the prompt is displayed. – orome Apr 06 '16 at 19:37
0

Putting together @orome and @Andrea discussed:

I added to following to my bash script:

__venv_prefix()
{
    printf "$CONDA_PROMPT_MODIFIER"
}

# git color hint branch name
source ~/git-prompt.sh
export PROMPT_COMMAND='__venv_prefix; __git_ps1 "\u@\h:\w" "\\\$ "'
export GIT_PS1_SHOWCOLORHINTS=1

It shows the conda env prefix when it is activated, git branch suffix when in a git repo, and both conda prefix and git suffix when both conditions are met.

EDIT: The above config has an issue that it does show conda environment on tab completion. The config below doesn't have the issue:

parse_git_branch() 
{
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u@\h\[\033[01;34m\] \w\[\033[01;33m\]\$(parse_git_branch)\[\033[01;34m\] \$\[\033[0m\] "
tartaruga_casco_mole
  • 1,086
  • 3
  • 21
  • 29
0

I had the same problem and it was annoying me so I added the following aliases to my .bash_aliases after seeing Andrea Corbellini's answer:

alias act="unset PROMPT_COMMAND && source ./.venv/bin/activate" 
alias dact="deactivate && export PROMPT_COMMAND=prompt_command"

I always use the same directory name (.venv) so this works fine for me. Hope it helps someone.

Oeg Bizz
  • 104
  • 6
0

If PROMPT_COMMAND is overriding your PS1 in bash, you can fix your prompt command function to be venv-aware:

my_prompt_command() {
    # ...do all your work to set PS1 here...

    if [[ -n "$VIRTUAL_ENV_PROMPT" ]]; then
        PS1="(venv) $PS1"
    fi
}
PROMPT_COMMAND=my_prompt_command
Alcamtar
  • 1,478
  • 13
  • 19