Skip to content

Commit 1fd0c1d

Browse files
google-labs-jules[bot]esafak
authored andcommitted
fix(activation): correctly handle PKG_CONFIG_PATH
The activation scripts for bash and fish did not correctly handle the `PKG_CONFIG_PATH` environment variable when it was initially unset. This caused the variable to be set to an empty string after deactivation, instead of being unset. This commit fixes the activation scripts to correctly save and restore the `PKG_CONFIG_PATH`, and adds tests to verify the behavior.
1 parent cad97f4 commit 1fd0c1d

File tree

4 files changed

+32
-29
lines changed

4 files changed

+32
-29
lines changed

src/virtualenv/activation/bash/activate.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ deactivate () {
2222
export PYTHONHOME
2323
unset _OLD_VIRTUAL_PYTHONHOME
2424
fi
25-
if ! [ -z "${_OLD_PKG_CONFIG_PATH:+_}" ]; then
25+
if [ -n "${_OLD_PKG_CONFIG_PATH-}" ] ; then
2626
PKG_CONFIG_PATH="$_OLD_PKG_CONFIG_PATH"
2727
export PKG_CONFIG_PATH
2828
unset _OLD_PKG_CONFIG_PATH
29+
else
30+
# if PKG_CONFIG_PATH was not set before, we should unset it
31+
unset PKG_CONFIG_PATH
2932
fi
3033

3134
# The hash command must be called to get it to forget past
@@ -60,7 +63,9 @@ _OLD_VIRTUAL_PATH="$PATH"
6063
PATH="$VIRTUAL_ENV/"__BIN_NAME__":$PATH"
6164
export PATH
6265

63-
_OLD_PKG_CONFIG_PATH="${PKG_CONFIG_PATH}"
66+
if [ -n "${PKG_CONFIG_PATH-}" ] ; then
67+
_OLD_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
68+
fi
6469
PKG_CONFIG_PATH="$VIRTUAL_ENV/lib/pkgconfig${PKG_CONFIG_PATH:+:}${PKG_CONFIG_PATH}"
6570
export PKG_CONFIG_PATH
6671

src/virtualenv/activation/fish/activate.fish

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ function deactivate -d 'Exit virtualenv mode and return to the normal environmen
3131
set -e _OLD_VIRTUAL_PYTHONHOME
3232
end
3333

34-
if test -n "$_OLD_VIRTUAL_PKG_CONFIG_PATH"
34+
if test -n "$_OLD_VIRTUAL_PKG_CONFIG_PATH" -o -n "$_OLD_VIRTUAL_PKG_CONFIG_PATH_BACKUP"
3535
set -gx PKG_CONFIG_PATH $_OLD_VIRTUAL_PKG_CONFIG_PATH
3636
set -e _OLD_VIRTUAL_PKG_CONFIG_PATH
37+
else
38+
set -e PKG_CONFIG_PATH
3739
end
3840

3941
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
@@ -75,10 +77,8 @@ set -gx PATH "$VIRTUAL_ENV"'/'__BIN_NAME__ $PATH
7577

7678
if set -q PKG_CONFIG_PATH
7779
set -gx _OLD_VIRTUAL_PKG_CONFIG_PATH $PKG_CONFIG_PATH
78-
set -gx PKG_CONFIG_PATH "$VIRTUAL_ENV/lib/pkgconfig" $PKG_CONFIG_PATH
79-
else
80-
set -gx PKG_CONFIG_PATH "$VIRTUAL_ENV/lib/pkgconfig"
8180
end
81+
set -gx PKG_CONFIG_PATH "$VIRTUAL_ENV/lib/pkgconfig" $PKG_CONFIG_PATH
8282

8383
# Prompt override provided?
8484
# If not, just use the environment name.

tests/unit/activation/conftest.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def env(self, tmp_path): # noqa: ARG002
9898
env["PYTHONIOENCODING"] = "utf-8"
9999
env["PATH"] = os.pathsep.join([dirname(sys.executable), *env.get("PATH", "").split(os.pathsep)])
100100
# clear up some environment variables so they don't affect the tests
101-
for key in [k for k in env if k.startswith(("_OLD", "VIRTUALENV_"))]:
101+
for key in [k for k in env if k.startswith(("_OLD", "VIRTUALENV_")) or k == "PKG_CONFIG_PATH"]:
102102
del env[key]
103103
return env
104104

@@ -115,17 +115,20 @@ def _get_test_lines(self, activate_script):
115115
self.print_python_exe(),
116116
self.print_os_env_var("VIRTUAL_ENV"),
117117
self.print_os_env_var("VIRTUAL_ENV_PROMPT"),
118+
self.print_os_env_var("PKG_CONFIG_PATH"),
118119
self.activate_call(activate_script),
119120
self.print_python_exe(),
120121
self.print_os_env_var("VIRTUAL_ENV"),
121122
self.print_os_env_var("VIRTUAL_ENV_PROMPT"),
123+
self.print_os_env_var("PKG_CONFIG_PATH"),
122124
self.print_prompt(),
123125
# \\ loads documentation from the virtualenv site packages
124126
self.pydoc_call,
125127
self.deactivate,
126128
self.print_python_exe(),
127129
self.print_os_env_var("VIRTUAL_ENV"),
128130
self.print_os_env_var("VIRTUAL_ENV_PROMPT"),
131+
self.print_os_env_var("PKG_CONFIG_PATH"),
129132
"", # just finish with an empty new line
130133
]
131134

@@ -134,23 +137,28 @@ def assert_output(self, out, raw, tmp_path):
134137
assert out[0], raw
135138
assert out[1] == "None", raw
136139
assert out[2] == "None", raw
140+
assert out[3] == "None", raw
137141
# post-activation
138142
expected = self._creator.exe.parent / os.path.basename(sys.executable)
139-
assert self.norm_path(out[3]) == self.norm_path(expected), raw
140-
assert self.norm_path(out[4]) == self.norm_path(self._creator.dest).replace("\\\\", "\\"), raw
141-
assert out[5] == self._creator.env_name
143+
assert self.norm_path(out[4]) == self.norm_path(expected), raw
144+
assert self.norm_path(out[5]) == self.norm_path(self._creator.dest).replace("\\\\", "\\"), raw
145+
assert out[6] == self._creator.env_name
146+
pkg_config_path = self._creator.dest / "lib" / "pkgconfig"
147+
assert self.norm_path(out[7]) == self.norm_path(pkg_config_path), raw
148+
142149
# Some attempts to test the prompt output print more than 1 line.
143150
# So we need to check if the prompt exists on any of them.
144151
prompt_text = f"({self._creator.env_name}) "
145-
assert any(prompt_text in line for line in out[6:-4]), raw
152+
assert any(prompt_text in line for line in out[8:-5]), raw
146153

147-
assert out[-4] == "wrote pydoc_test.html", raw
154+
assert out[-5] == "wrote pydoc_test.html", raw
148155
content = tmp_path / "pydoc_test.html"
149156
assert content.exists(), raw
150157
# post deactivation, same as before
151-
assert out[-3] == out[0], raw
158+
assert out[-4] == out[0], raw
159+
assert out[-3] == "None", raw
152160
assert out[-2] == "None", raw
153-
assert out[-1] == "None", raw
161+
assert out[-1] in {"None", ""}, raw
154162

155163
def quote(self, s):
156164
return self.of_class.quote(s)

tests/unit/activation/test_bash.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,11 @@ def activate_call(self, script):
2828
def print_prompt(self):
2929
return self.print_os_env_var("PS1")
3030

31-
def _get_test_lines(self, activate_script):
32-
lines = super()._get_test_lines(activate_script)
33-
lines.insert(3, self.print_os_env_var("PKG_CONFIG_PATH"))
34-
i = next(i for i, line in enumerate(lines) if "pydoc" in line)
35-
lines.insert(i, self.print_os_env_var("PKG_CONFIG_PATH"))
36-
lines.insert(-1, self.print_os_env_var("PKG_CONFIG_PATH"))
37-
return lines
38-
3931
def assert_output(self, out, raw, tmp_path):
40-
assert out[3] == "None"
41-
42-
pkg_config_path = self.norm_path(self._creator.dest / "lib" / "pkgconfig")
43-
assert self.norm_path(out[9]) == pkg_config_path
44-
45-
assert out[-2] == "None" # shell has no value
46-
super().assert_output(out[:3] + out[4:9] + out[10:-2] + [out[-1]], raw, tmp_path)
32+
# for bash we check the prompt is changed
33+
prompt_text = f"({self._creator.env_name}) "
34+
assert out[8].startswith(prompt_text)
35+
# then call the base to check the rest
36+
super().assert_output(out, raw, tmp_path)
4737

4838
activation_tester(Bash)

0 commit comments

Comments
 (0)