Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ import { cleanupStartupScripts } from './features/terminal/shellStartupSetupHand
import { TerminalActivationImpl } from './features/terminal/terminalActivationState';
import { TerminalEnvVarInjector } from './features/terminal/terminalEnvVarInjector';
import { TerminalManager, TerminalManagerImpl } from './features/terminal/terminalManager';
import { getEnvironmentForTerminal } from './features/terminal/utils';
import { getEnvironmentForTerminal, migrateLegacyTerminalActivationSetting } from './features/terminal/utils';
import { openSearchSettings } from './features/views/envManagerSearch';
import { EnvManagerView } from './features/views/envManagersView';
import { ProjectView } from './features/views/projectView';
Expand Down Expand Up @@ -184,6 +184,12 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
traceError(`[migration] migrateGlobalDefaultEnvManagerSetting threw: ${err}`);
}

try {
await migrateLegacyTerminalActivationSetting();
} catch (err) {
traceError(`[migration] migrateLegacyTerminalActivationSetting threw: ${err}`);
}

const statusBar = new PythonStatusBarImpl();
context.subscriptions.push(statusBar);

Expand Down
32 changes: 29 additions & 3 deletions src/features/terminal/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ export const ACT_TYPE_SHELL = 'shellStartup';
export const ACT_TYPE_COMMAND = 'command';
export const ACT_TYPE_OFF = 'off';
export type AutoActivationType = 'off' | 'command' | 'shellStartup';

/**
* Determines the auto-activation type for Python environments in terminals.
*
Expand All @@ -392,7 +393,7 @@ export type AutoActivationType = 'off' | 'command' | 'shellStartup';
* a. globalRemoteValue
* b. globalLocalValue
* c. globalValue
* 2. python.terminal.activateEnvironment setting (if false, returns 'off' & sets autoActivationType to 'off')
* 2. python.terminal.activateEnvironment setting (if false, returns 'off')
* 3. Default to 'command' if no setting is found
*
* @returns {AutoActivationType} The determined auto-activation type
Expand Down Expand Up @@ -420,15 +421,40 @@ export function getAutoActivationType(): AutoActivationType {
const pythonConfig = getConfiguration('python');
const pythonActivateSetting = pythonConfig.get<boolean | undefined>('terminal.activateEnvironment', undefined);
if (pythonActivateSetting === false) {
// Set autoActivationType to 'off' if python.terminal.activateEnvironment is false
pyEnvsConfig.update('terminal.autoActivationType', ACT_TYPE_OFF);
return ACT_TYPE_OFF;
}

// Default to 'command' if no settings are found or if pythonActivateSetting is true/undefined
return ACT_TYPE_COMMAND;
}

/**
* Migrates the disabled legacy terminal activation setting to User settings.
*
* The migration is skipped when `python-envs.terminal.autoActivationType` is already set.
* The returned promise rejects if the setting cannot be updated.
*/
export async function migrateLegacyTerminalActivationSetting(): Promise<void> {
const pyEnvsConfig = getConfiguration('python-envs');
const pyEnvsActivationType = pyEnvsConfig.inspect<AutoActivationType>('terminal.autoActivationType');

if (pyEnvsActivationType) {
const activationType = pyEnvsActivationType as Record<string, unknown>;
if (
('globalRemoteValue' in pyEnvsActivationType && activationType.globalRemoteValue !== undefined) ||
('globalLocalValue' in pyEnvsActivationType && activationType.globalLocalValue !== undefined) ||
pyEnvsActivationType.globalValue !== undefined
) {
return;
}
}

const pythonConfig = getConfiguration('python');
if (pythonConfig.get<boolean | undefined>('terminal.activateEnvironment', undefined) === false) {
await setAutoActivationType(ACT_TYPE_OFF);
}
}

export async function setAutoActivationType(value: AutoActivationType): Promise<void> {
const config = getConfiguration('python-envs');
return await config.update('terminal.autoActivationType', value, true);
Expand Down
22 changes: 17 additions & 5 deletions src/test/features/terminal/utils.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AutoActivationType,
getAutoActivationType,
getEnvironmentForTerminal,
migrateLegacyTerminalActivationSetting,
shouldActivateInCurrentTerminal,
shouldSkipTerminalActivation,
waitForShellIntegration,
Expand Down Expand Up @@ -484,19 +485,29 @@ suite('Terminal Utils - getAutoActivationType', () => {
});

suite('Legacy Python Setting Fallback', () => {
test('should return ACT_TYPE_OFF and update config when python.terminal.activateEnvironment is false', () => {
test('should migrate python.terminal.activateEnvironment false to User settings only once', async () => {
// Mock - no python-envs settings, python.terminal.activateEnvironment is false
pyEnvsConfig.inspect.withArgs('terminal.autoActivationType').returns(undefined);
pythonConfig.get.withArgs('terminal.activateEnvironment', undefined).returns(false);
pyEnvsConfig.update.rejects(new Error('Unable to update User settings'));

// Run
await assert.rejects(migrateLegacyTerminalActivationSetting(), /Unable to update User settings/);
const result = getAutoActivationType();
const repeatedResult = getAutoActivationType();

// Assert
assert.strictEqual(result, ACT_TYPE_OFF, 'Should return ACT_TYPE_OFF when legacy setting is false');
assert.ok(
pyEnvsConfig.update.calledWithExactly('terminal.autoActivationType', ACT_TYPE_OFF),
'Should update python-envs config to ACT_TYPE_OFF',
assert.strictEqual(
repeatedResult,
ACT_TYPE_OFF,
'Should continue returning ACT_TYPE_OFF after a failed migration',
);
sinon.assert.calledOnceWithExactly(
pyEnvsConfig.update,
'terminal.autoActivationType',
ACT_TYPE_OFF,
true,
);
});

Expand Down Expand Up @@ -572,7 +583,7 @@ suite('Terminal Utils - getAutoActivationType', () => {
);
});

test('should prioritize python-envs settings over legacy python settings', () => {
test('should prioritize python-envs settings over legacy python settings', async () => {
// Mock - python-envs has globalValue, python has conflicting setting
const mockInspectResult = {
globalValue: ACT_TYPE_SHELL,
Expand All @@ -581,6 +592,7 @@ suite('Terminal Utils - getAutoActivationType', () => {
pythonConfig.get.withArgs('terminal.activateEnvironment', undefined).returns(false);

// Run
await migrateLegacyTerminalActivationSetting();
const result = getAutoActivationType();

// Assert
Expand Down