Skip to content

Commit b01b088

Browse files
jakelodwickJSL
authored andcommitted
Cache prompt hook state to skip redundant pyenv sh-activate calls
Track five values between prompts ($PWD, $PYENV_VERSION, .python-version content, $PYENV_ROOT/version content, $VIRTUAL_ENV) using shell builtins. When all match, return immediately without forking. Covers cd, pyenv shell/local/global, and manual venv activate/deactivate. Implemented for bash/zsh/ksh (shared POSIX path) and fish.
1 parent 38f3333 commit b01b088

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

bin/pyenv-virtualenv-init

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,31 @@ fish )
106106
cat <<EOS
107107
function _pyenv_virtualenv_hook --on-event fish_prompt;
108108
set -l ret \$status
109+
set -l pvh_local ""
110+
if test -f "\$PWD/.python-version"
111+
read pvh_local < "\$PWD/.python-version" 2>/dev/null; or true
112+
end
113+
set -l pvh_global ""
114+
if test -f "\$PYENV_ROOT/version"
115+
read pvh_global < "\$PYENV_ROOT/version" 2>/dev/null; or true
116+
end
117+
if test "\$PWD" = "\$_PYENV_VH_PWD" \\
118+
-a "\$PYENV_VERSION" = "\$_PYENV_VH_VERSION" \\
119+
-a "\$pvh_local" = "\$_PYENV_VH_LOCAL" \\
120+
-a "\$pvh_global" = "\$_PYENV_VH_GLOBAL" \\
121+
-a "\$VIRTUAL_ENV" = "\$_PYENV_VH_VENV"
122+
return \$ret
123+
end
109124
if [ -n "\$VIRTUAL_ENV" ]
110125
pyenv activate --quiet; or pyenv deactivate --quiet; or true
111126
else
112127
pyenv activate --quiet; or true
113128
end
129+
set -g _PYENV_VH_PWD "\$PWD"
130+
set -g _PYENV_VH_VERSION "\$PYENV_VERSION"
131+
set -g _PYENV_VH_LOCAL "\$pvh_local"
132+
set -g _PYENV_VH_GLOBAL "\$pvh_global"
133+
set -g _PYENV_VH_VENV "\$VIRTUAL_ENV"
114134
return \$ret
115135
end
116136
EOS
@@ -130,11 +150,31 @@ esac
130150
if [[ "$shell" != "fish" ]]; then
131151
cat <<EOS
132152
local ret=\$?
153+
local pvh_local=""
154+
if [ -f "\${PWD}/.python-version" ]; then
155+
IFS= read -r pvh_local < "\${PWD}/.python-version" 2>/dev/null || true
156+
fi
157+
local pvh_global=""
158+
if [ -f "\${PYENV_ROOT}/version" ]; then
159+
IFS= read -r pvh_global < "\${PYENV_ROOT}/version" 2>/dev/null || true
160+
fi
161+
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
162+
&& [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
163+
&& [ "\${pvh_local}" = "\${_PYENV_VH_LOCAL-}" ] \\
164+
&& [ "\${pvh_global}" = "\${_PYENV_VH_GLOBAL-}" ] \\
165+
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
166+
return \$ret
167+
fi
133168
if [ -n "\${VIRTUAL_ENV-}" ]; then
134169
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
135170
else
136171
eval "\$(pyenv sh-activate --quiet || true)" || true
137172
fi
173+
_PYENV_VH_PWD="\${PWD}"
174+
_PYENV_VH_VERSION="\${PYENV_VERSION-}"
175+
_PYENV_VH_LOCAL="\${pvh_local}"
176+
_PYENV_VH_GLOBAL="\${pvh_global}"
177+
_PYENV_VH_VENV="\${VIRTUAL_ENV-}"
138178
return \$ret
139179
};
140180
EOS

test/init.bats

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,31 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
5454
export PYENV_VIRTUALENV_INIT=1;
5555
_pyenv_virtualenv_hook() {
5656
local ret=\$?
57+
local pvh_local=""
58+
if [ -f "\${PWD}/.python-version" ]; then
59+
IFS= read -r pvh_local < "\${PWD}/.python-version" 2>/dev/null || true
60+
fi
61+
local pvh_global=""
62+
if [ -f "\${PYENV_ROOT}/version" ]; then
63+
IFS= read -r pvh_global < "\${PYENV_ROOT}/version" 2>/dev/null || true
64+
fi
65+
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
66+
&& [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
67+
&& [ "\${pvh_local}" = "\${_PYENV_VH_LOCAL-}" ] \\
68+
&& [ "\${pvh_global}" = "\${_PYENV_VH_GLOBAL-}" ] \\
69+
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
70+
return \$ret
71+
fi
5772
if [ -n "\${VIRTUAL_ENV-}" ]; then
5873
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
5974
else
6075
eval "\$(pyenv sh-activate --quiet || true)" || true
6176
fi
77+
_PYENV_VH_PWD="\${PWD}"
78+
_PYENV_VH_VERSION="\${PYENV_VERSION-}"
79+
_PYENV_VH_LOCAL="\${pvh_local}"
80+
_PYENV_VH_GLOBAL="\${pvh_global}"
81+
_PYENV_VH_VENV="\${VIRTUAL_ENV-}"
6282
return \$ret
6383
};
6484
if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then
@@ -78,11 +98,31 @@ set -gx PATH '${TMP}/pyenv/plugins/pyenv-virtualenv/shims' \$PATH;
7898
set -gx PYENV_VIRTUALENV_INIT 1;
7999
function _pyenv_virtualenv_hook --on-event fish_prompt;
80100
set -l ret \$status
101+
set -l pvh_local ""
102+
if test -f "\$PWD/.python-version"
103+
read pvh_local < "\$PWD/.python-version" 2>/dev/null; or true
104+
end
105+
set -l pvh_global ""
106+
if test -f "\$PYENV_ROOT/version"
107+
read pvh_global < "\$PYENV_ROOT/version" 2>/dev/null; or true
108+
end
109+
if test "\$PWD" = "\$_PYENV_VH_PWD" \\
110+
-a "\$PYENV_VERSION" = "\$_PYENV_VH_VERSION" \\
111+
-a "\$pvh_local" = "\$_PYENV_VH_LOCAL" \\
112+
-a "\$pvh_global" = "\$_PYENV_VH_GLOBAL" \\
113+
-a "\$VIRTUAL_ENV" = "\$_PYENV_VH_VENV"
114+
return \$ret
115+
end
81116
if [ -n "\$VIRTUAL_ENV" ]
82117
pyenv activate --quiet; or pyenv deactivate --quiet; or true
83118
else
84119
pyenv activate --quiet; or true
85120
end
121+
set -g _PYENV_VH_PWD "\$PWD"
122+
set -g _PYENV_VH_VERSION "\$PYENV_VERSION"
123+
set -g _PYENV_VH_LOCAL "\$pvh_local"
124+
set -g _PYENV_VH_GLOBAL "\$pvh_global"
125+
set -g _PYENV_VH_VENV "\$VIRTUAL_ENV"
86126
return \$ret
87127
end
88128
EOS
@@ -97,11 +137,31 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
97137
export PYENV_VIRTUALENV_INIT=1;
98138
_pyenv_virtualenv_hook() {
99139
local ret=\$?
140+
local pvh_local=""
141+
if [ -f "\${PWD}/.python-version" ]; then
142+
IFS= read -r pvh_local < "\${PWD}/.python-version" 2>/dev/null || true
143+
fi
144+
local pvh_global=""
145+
if [ -f "\${PYENV_ROOT}/version" ]; then
146+
IFS= read -r pvh_global < "\${PYENV_ROOT}/version" 2>/dev/null || true
147+
fi
148+
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
149+
&& [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
150+
&& [ "\${pvh_local}" = "\${_PYENV_VH_LOCAL-}" ] \\
151+
&& [ "\${pvh_global}" = "\${_PYENV_VH_GLOBAL-}" ] \\
152+
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
153+
return \$ret
154+
fi
100155
if [ -n "\${VIRTUAL_ENV-}" ]; then
101156
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
102157
else
103158
eval "\$(pyenv sh-activate --quiet || true)" || true
104159
fi
160+
_PYENV_VH_PWD="\${PWD}"
161+
_PYENV_VH_VERSION="\${PYENV_VERSION-}"
162+
_PYENV_VH_LOCAL="\${pvh_local}"
163+
_PYENV_VH_GLOBAL="\${pvh_global}"
164+
_PYENV_VH_VENV="\${VIRTUAL_ENV-}"
105165
return \$ret
106166
};
107167
typeset -g -a precmd_functions

0 commit comments

Comments
 (0)