Paczesiowa / virthualenv

Virtual Haskell Environment builder
BSD 3-Clause "New" or "Revised" License
69 stars 7 forks source link

Cannot deactivate virthualenv inside screen/tmux #38

Open jgrocho opened 12 years ago

jgrocho commented 12 years ago

If I activate a virthualenv in a shell and then start screen or tmux, the virthualenv persists and I can use it as normal, as I would expect. However, I cannot deactivate it as the deactivate function is not exported by bin/activate. I would recommend exporting that function, but I don't know if that would have other undesirable consequences, and I haven't yet had a chance to test it out.

I think we should either find a way to safely and robustly deactivate from within screen/tmux or at least make it explicit in the documentation that it can't be done.

jgrocho commented 12 years ago

I can say that adding export -f deactivate somewhere after the definition of the function does make it available inside each screen/tmux window and appears to deactivate only within that shell.

Paczesiowa commented 12 years ago

ok, this one is hard.

first of all, after starting screen/tmux from inside virthualenv it does not work correctly (at least on my bash machine) - $PATH is not preserved, so it uses your bare/pre-virthualenv $PATH, so no cabal wrapper for you. you also lose fancy prompt, so it doesn't look correctly either.

export -f deactivate looks like a bash-specific thing, from bash --posix it works just like without that command. zsh displays deactivate's source code. so it looks, like it only works in bash and you still get broken virthualenv inside screen/tmux.

Python's virtualenv fails in the same way (and they have much bigger user base) and I don't know posix shell programming (or even bash) to make it work with screen/tmux, I'll have to leave it be.

The only idea I have is to add info about it to README and provide wrappers for screen and tmux binaries, that display big fat warning, that virtual environment will not work inside screen/tmux, wait for a key and then run screen/tmux, what do you think about it?

jgrocho commented 12 years ago

Doing some quick googling reveals that the virtualenv community hasn't solved this problem either, which is unfortunate for us.

I'm not a big fan of wrapping screen/tmux as that might have unforeseeable consequences for some people (it could interfere with custom aliases, wouldn't work if screen/tmux as called by absolute path or indirectly via some other command). I would say that you need to test for screen/tmux before providing wrappers for them. Otherwise, the user might think a command is installed when in fact it's really just the wrapper.

If you do wrap screen/tmux, it may be a better idea to call deactivate and then tell the user to manually call activate in each terminal. This solution seems to generate the fewest surprises for the user. They only get the one warning at the beginning instead of a warning and then a bunch of other things not functioning as expected.

Paczesiowa commented 12 years ago

it could interfere with custom aliases

hmm, only if those aliases are defined earlier using something like which screen

wouldn't work if screen/tmux as called by absolute path

I think it's really not-unixy to call binaries by hardcoded paths

I would say that you need to test for screen/tmux before providing wrappers for them.

good point.

it may be a better idea to call deactivate and then tell the user to manually call activate in each terminal.

great idea! seems like the best solution.

cenkalti commented 8 years ago

I wrote a simple wrapper for tmux command:

# virtualenv does not work correctly when tmux is run inside virtualenv.
# this function is a wrapper around tmux command that deactivates virtualenv
# before running tmux and reactivates it again. --cenkalti
tmux()
{
    local current_env=""
    if [ "$VIRTUAL_ENV" != "" ]; then
        current_env="$VIRTUAL_ENV"
        deactivate
    fi

    command tmux "$@"
    local ret=$?

    if [ "$current_env" != "" ]; then
        workon $(basename $current_env)
    fi

    return $ret
}
pavlocat commented 5 years ago

It seems commands after tmux execution is executed after the tmux subprocess is detached or exited. So I wrote that part in bashrc directly instead. The following code works for me:

(write in ~/.bashrc, for instance)

if [ "$current_env" != "" ]; then
    workon $(basename $current_env)
    unset current_env
fi

tmux()
{
    current_env=""
    if [ "$VIRTUAL_ENV" != "" ]; then
        current_env="$VIRTUAL_ENV"
        deactivate
        export current_env
    fi

    command tmux "$@"
}

The same way is available for screen, too.