Skip to content

Commit a80fd70

Browse files
authored
Add Python activate hooks into shell integration scripts (microsoft#261094)
* Add activate hook for bash * Add bash Python activate hooks * Register zsh activate hooks * Add hooks for .ps1 * clean up for pwsh * Add /^VSCODE_(PWSH|ZSH|BASH)_ACTIVATE$/, * Do not let non-Python-env ext to set activate var * Remove comment * Add logService --> Need review! * Add fish activate hooks * enable log in envVarCollection.ts * Attach PYTHON after VSCODE for activate hook name * make blockPythonActivationVar func * Revert logService * Show the * next to error message. * clean-up * Dont forget to rename * Dont mess with original formatting * Still need .+, remove dup Python keysToRemove * Add tests for Python activate vars * Consolidate tests! * Clean clean clean
1 parent 2fce67a commit a80fd70

7 files changed

Lines changed: 74 additions & 2 deletions

File tree

extensions/terminal-suggest/src/terminalSuggestMain.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ export function sanitizeProcessEnvironment(env: Record<string, string>, ...prese
520520
}, {});
521521
const keysToRemove = [
522522
/^ELECTRON_.$/,
523-
/^VSCODE_(?!(PORTABLE|SHELL_LOGIN|ENV_REPLACE|ENV_APPEND|ENV_PREPEND)).$/,
523+
/^VSCODE_(?!(PORTABLE|SHELL_LOGIN|ENV_REPLACE|ENV_APPEND|ENV_PREPEND)).+$/,
524524
/^SNAP(|_.*)$/,
525525
/^GDK_PIXBUF_.$/,
526526
];

src/vs/base/test/common/processes.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,20 @@ suite('Processes', () => {
2828
VSCODE_CODE_CACHE_PATH: 'x',
2929
VSCODE_NEW_VAR: 'x',
3030
GDK_PIXBUF_MODULE_FILE: 'x',
31-
GDK_PIXBUF_MODULEDIR: 'x'
31+
GDK_PIXBUF_MODULEDIR: 'x',
32+
VSCODE_PYTHON_BASH_ACTIVATE: 'source /path/to/venv/bin/activate',
33+
VSCODE_PYTHON_ZSH_ACTIVATE: 'source /path/to/venv/bin/activate',
34+
VSCODE_PYTHON_PWSH_ACTIVATE: '. /path/to/venv/Scripts/Activate.ps1',
35+
VSCODE_PYTHON_FISH_ACTIVATE: 'source /path/to/venv/bin/activate.fish',
3236
};
3337
processes.sanitizeProcessEnvironment(env);
3438
assert.strictEqual(env['FOO'], 'bar');
3539
assert.strictEqual(env['VSCODE_SHELL_LOGIN'], '1');
3640
assert.strictEqual(env['VSCODE_PORTABLE'], '3');
41+
assert.strictEqual(env['VSCODE_PYTHON_BASH_ACTIVATE'], undefined);
42+
assert.strictEqual(env['VSCODE_PYTHON_ZSH_ACTIVATE'], undefined);
43+
assert.strictEqual(env['VSCODE_PYTHON_PWSH_ACTIVATE'], undefined);
44+
assert.strictEqual(env['VSCODE_PYTHON_FISH_ACTIVATE'], undefined);
3745
assert.strictEqual(Object.keys(env).length, 3);
3846
});
3947
});

src/vs/platform/terminal/common/environmentVariableCollection.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const mutatorTypeToLabelMap: Map<EnvironmentVariableMutatorType, string> = new M
1313
[EnvironmentVariableMutatorType.Prepend, 'PREPEND'],
1414
[EnvironmentVariableMutatorType.Replace, 'REPLACE']
1515
]);
16+
const PYTHON_ACTIVATION_VARS_PATTERN = /^VSCODE_PYTHON_(PWSH|ZSH|BASH|FISH)_ACTIVATE/;
17+
const PYTHON_ENV_EXTENSION_ID = 'ms-python.vscode-python-envs';
1618

1719
export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVariableCollection {
1820
private readonly map: Map<string, IExtensionOwnedEnvironmentVariableMutator[]> = new Map();
@@ -28,6 +30,12 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa
2830
while (!next.done) {
2931
const mutator = next.value[1];
3032
const key = next.value[0];
33+
34+
if (this.blockPythonActivationVar(key, extensionIdentifier)) {
35+
next = it.next();
36+
continue;
37+
}
38+
3139
let entry = this.map.get(key);
3240
if (!entry) {
3341
entry = [];
@@ -70,6 +78,11 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa
7078
const actualVariable = isWindows ? lowerToActualVariableNames![variable.toLowerCase()] || variable : variable;
7179
for (const mutator of mutators) {
7280
const value = variableResolver ? await variableResolver(mutator.value) : mutator.value;
81+
82+
if (this.blockPythonActivationVar(mutator.variable, mutator.extensionIdentifier)) {
83+
continue;
84+
}
85+
7386
// Default: true
7487
if (mutator.options?.applyAtProcessCreation ?? true) {
7588
switch (mutator.type) {
@@ -97,6 +110,14 @@ export class MergedEnvironmentVariableCollection implements IMergedEnvironmentVa
97110
return value.replaceAll(':', '\\x3a');
98111
}
99112

113+
private blockPythonActivationVar(variable: string, extensionIdentifier: string): boolean {
114+
// Only Python env extension can modify Python activate env var.
115+
if (PYTHON_ACTIVATION_VARS_PATTERN.test(variable) && PYTHON_ENV_EXTENSION_ID !== extensionIdentifier) {
116+
return true;
117+
}
118+
return false;
119+
}
120+
100121
diff(other: IMergedEnvironmentVariableCollection, scope: EnvironmentVariableScope | undefined): IMergedEnvironmentVariableCollectionDiff | undefined {
101122
const added: Map<string, IExtensionOwnedEnvironmentVariableMutator[]> = new Map();
102123
const changed: Map<string, IExtensionOwnedEnvironmentVariableMutator[]> = new Map();

src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-bash.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ if [ -n "${VSCODE_ENV_APPEND:-}" ]; then
9191
builtin unset VSCODE_ENV_APPEND
9292
fi
9393

94+
# Register Python shell activate hooks
95+
if [ -n "$VSCODE_PYTHON_BASH_ACTIVATE" ] && [ "$TERM_PROGRAM" = "vscode" ]; then
96+
# Prevent crashing by negating exit code
97+
if ! builtin eval "$VSCODE_PYTHON_BASH_ACTIVATE"; then
98+
__vsc_activation_status=$?
99+
builtin printf '\x1b[0m\x1b[7m * \x1b[0;103m VS Code Python bash activation failed with exit code %d \x1b[0m' "$__vsc_activation_status"
100+
fi
101+
fi
102+
94103
__vsc_get_trap() {
95104
# 'trap -p DEBUG' outputs a shell command like `trap -- '…shellcode…' DEBUG`.
96105
# The terms are quoted literals, but are not guaranteed to be on a single line.

src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ if [ -n "${VSCODE_ENV_APPEND:-}" ]; then
6868
unset VSCODE_ENV_APPEND
6969
fi
7070

71+
# Register Python shell activate hooks
72+
if [ -n "$VSCODE_PYTHON_ZSH_ACTIVATE" ] && [ "$TERM_PROGRAM" = "vscode" ]; then
73+
# Prevent crashing by negating exit code
74+
if ! builtin eval "$VSCODE_PYTHON_ZSH_ACTIVATE"; then
75+
__vsc_activation_status=$?
76+
builtin printf '\x1b[0m\x1b[7m * \x1b[0;103m VS Code Python zsh activation failed with exit code %d \x1b[0m' "$__vsc_activation_status"
77+
fi
78+
fi
79+
7180
# Report prompt type
7281
if [ -n "$ZSH" ] && [ -n "$ZSH_VERSION" ] && (( ${+functions[omz]} )) ; then
7382
builtin printf '\e]633;P;PromptType=oh-my-zsh\a'

src/vs/workbench/contrib/terminal/common/scripts/shellIntegration.fish

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ function __vsc_apply_env_vars
7575
end
7676
end
7777

78+
# Register Python shell activate hooks
79+
if test -n "$VSCODE_PYTHON_FISH_ACTIVATE"; and test "$TERM_PROGRAM" = "vscode"
80+
# Fish does not crash on eval failure, so don't need negation.
81+
eval $VSCODE_PYTHON_FISH_ACTIVATE
82+
set __vsc_activation_status $status
83+
84+
if test $__vsc_activation_status -ne 0
85+
builtin printf '\x1b[0m\x1b[7m * \x1b[0;103m VS Code Python fish activation failed with exit code %d \x1b[0m \n' "$__vsc_activation_status"
86+
end
87+
end
88+
7889
# Handle the shell integration nonce
7990
if set -q VSCODE_NONCE
8091
set -l __vsc_nonce $VSCODE_NONCE

src/vs/workbench/contrib/terminal/common/scripts/shellIntegration.ps1

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,20 @@ if ($env:VSCODE_ENV_APPEND) {
6868
$env:VSCODE_ENV_APPEND = $null
6969
}
7070

71+
# Register Python shell activate hooks
72+
if ($env:VSCODE_PYTHON_PWSH_ACTIVATE -and $env:TERM_PROGRAM -eq 'vscode') {
73+
$activateScript = $env:VSCODE_PYTHON_PWSH_ACTIVATE
74+
Remove-Item Env:VSCODE_PYTHON_PWSH_ACTIVATE
75+
76+
try {
77+
Invoke-Expression $activateScript
78+
}
79+
catch {
80+
$activationError = $_
81+
Write-Host "`e[0m`e[7m * `e[0;103m VS Code Python powershell activation failed with exit code $($activationError.Exception.Message) `e[0m"
82+
}
83+
}
84+
7185
function Global:__VSCode-Escape-Value([string]$value) {
7286
# NOTE: In PowerShell v6.1+, this can be written `$value -replace '…', { … }` instead of `[regex]::Replace`.
7387
# Replace any non-alphanumeric characters.

0 commit comments

Comments
 (0)