Skip to content

Commit 4ee196d

Browse files
committed
Use deactivate to tell if in virtual environment
This patch makes it so the combined definition of $VIRTUAL_ENV and existence of the shell function deactivate environment are used to tell whether a virtual environment is active. This was done to fix some issues where the plugin collided with other virtual environment managers like Direnv. Direnv sets $VIRTUAL_ENV but crucially does not create the disable shell function, which makes sense, as Direnv manages that for the user. Previosly, the plugin would not discover the virtual environment created by Direnv and (since Direnv set VIRTUAL_ENV) decide that it should leave the virtual environment. This would print an error message as deactivate is not defined by Direnv.
1 parent 3e3581a commit 4ee196d

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ How it works
2020
The heart of this plugin is the following table, corresponding to the logic in
2121
`_autovenv_update`.
2222

23-
| | No active venv (`$VIRTUAL_ENV` is unset) | Active venv (`$VIRTUAL_ENV` is set) |
24-
|-------------------------------:|------------------------------------------|-------------------------------------|
25-
| PWD has virtual environment | Activate it | Switch if they aren't the same |
26-
| PWD has no virtual environment | Do nothing | Deactivate it |
23+
| | No active venv (`deactivate` is unset) | Active venv (`deactivate` is set) |
24+
|-------------------------------:|----------------------------------------|-----------------------------------|
25+
| PWD has virtual environment | Activate it | Switch if they aren't the same\* |
26+
| PWD has no virtual environment | Do nothing | Deactivate it |
27+
28+
\* The path of the virtual env discovered from `$PWD` is compared to the one
29+
specified py `$VIRTUAL_ENV`. If they are dissimilar, the latter is deactivated
30+
and the former is activated.
2731

2832
The rest of the logic should be pretty clear from the source code (as clear as
2933
shell script can be, that is).

autovenv.plugin.zsh

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
# FIXME: direnv messes this up
2+
# FIXME: sometimes VIRTUAL_ENV is set when we aren't in virtual env, like with 'nix shell' or subshells (?). maybe use deactivate function as signifier instead?
3+
14
# Perform an update (leaving, entering, switching virtual environments).
25
_autovenv_update () {
36
env_path="$(_autovenv_find_env_path)"
47

58
if [ -n "$env_path" ]; then
6-
if [ -v VIRTUAL_ENV ]; then
9+
if _autovenv_in_virtual_env; then
710
if [ "${env_path:P}" != "${VIRTUAL_ENV:P}" ]; then
811
echo "autovenv: switching from $VIRTUAL_ENV -> $env_path"
912
deactivate
@@ -16,13 +19,19 @@ _autovenv_update () {
1619
_autovenv_post-activate_sanity_check "$env_path"
1720
fi
1821
else
19-
if [ -v VIRTUAL_ENV ]; then
22+
if _autovenv_in_virtual_env; then
2023
echo "autovenv: leaving virtual environment at $VIRTUAL_ENV"
2124
deactivate
2225
fi
2326
fi
2427
}
2528

29+
# Check wether a virtual environment is currently active.
30+
_autovenv_in_virtual_env () {
31+
typeset -f deactivate >/dev/null && [ -v VIRTUAL_ENV ]
32+
return $?
33+
}
34+
2635
_autovenv_post-activate_sanity_check () {
2736
local env_path="$1"
2837

@@ -55,6 +64,15 @@ _autovenv_post-activate_sanity_check () {
5564
thinks it's in the old location. The autovenv plugin will behave
5665
strangely becuase of this.
5766
EOF
67+
68+
# Check that deactivate function was defined.
69+
if ! typeset -f deactivate >/dev/null; then
70+
cat >&2 <<-EOF
71+
autovenv: warning: $env_path/bin/activate did not define the shell
72+
function \`disable\`. The autovenv plugin uses this variable to detect
73+
if it's inside a virtual environment and won't work without it.
74+
EOF
75+
return
5876
fi
5977
}
6078

create_examples.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,13 @@ mkdir $'example-special \t\n!characters '
4444
cd $'example-special \t\n!characters '
4545
"$PYTHON" -m virtualenv .venv
4646
cd ..
47+
48+
# Create one managed by direnv, if available.
49+
# The plugin should NOT activate in here.
50+
if command -v direnv >/dev/null; then
51+
mkdir example-direnv
52+
cd example-direnv
53+
echo 'layout python3' >.envrc
54+
direnv allow
55+
cd ..
56+
fi

0 commit comments

Comments
 (0)