Skip to content

Better handle activateEnvInCurrentTerminal from Python extension#1318

Draft
anthonykim1 wants to merge 3 commits intomainfrom
anthonykim1/RespectActivateInCurrentEnv
Draft

Better handle activateEnvInCurrentTerminal from Python extension#1318
anthonykim1 wants to merge 3 commits intomainfrom
anthonykim1/RespectActivateInCurrentEnv

Conversation

@anthonykim1
Copy link
Contributor

@anthonykim1 anthonykim1 commented Mar 4, 2026

Resolves: #1300

Behaviors after this PR:

Note that the default false and explicit true behaves the same.

explicitFalse.mov
explicittrueorrDefault.mov

@anthonykim1 anthonykim1 self-assigned this Mar 4, 2026
@anthonykim1 anthonykim1 added area-activation Issue related to activation. Root cause can be from interpreter selection or activation in terminal debt labels Mar 4, 2026
@anthonykim1 anthonykim1 marked this pull request as ready for review March 4, 2026 23:25
@vs-code-engineering vs-code-engineering bot added this to the 1.111.0 milestone Mar 4, 2026
@anthonykim1 anthonykim1 modified the milestones: 1.111.0, 1.112.0 Mar 4, 2026
@anthonykim1 anthonykim1 closed this Mar 5, 2026
@anthonykim1 anthonykim1 reopened this Mar 5, 2026
@eleanorjboyd eleanorjboyd requested a review from Copilot March 6, 2026 21:31
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves how the extension honors the Python extension’s legacy terminal activation setting (python.terminal.activateEnvInCurrentTerminal) when initializing terminal activation for terminals that already exist at extension load time, aligning behavior with issue #1300.

Changes:

  • Add shouldActivateInCurrentTerminal() to interpret python.terminal.activateEnvInCurrentTerminal using inspect() so defaults can be distinguished from user-explicit values.
  • Update TerminalManagerImpl.initialize() to skip activating pre-existing terminals when that setting is explicitly disabled.
  • Add unit tests covering the new helper and the initialize-time skip behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/features/terminal/utils.ts Adds shouldActivateInCurrentTerminal() helper to evaluate the legacy Python setting via inspect().
src/features/terminal/terminalManager.ts Skips activation for pre-existing terminals during initialize when the legacy setting is explicitly disabled.
src/test/features/terminal/utils.unit.test.ts Adds unit tests for shouldActivateInCurrentTerminal().
src/test/features/terminal/terminalManager.unit.test.ts Adds unit tests for initialize behavior gated by shouldActivateInCurrentTerminal().
Comments suppressed due to low confidence (1)

src/features/terminal/utils.ts:283

  • This inspect() call is created without a scope/resource (getConfiguration('python') with no Uri). In VS Code, workspaceFolderValue will be undefined unless configuration is scoped to a specific resource, so the workspace-folder precedence described here won’t be honored in multi-root workspaces. Consider accepting a Uri/scope parameter (e.g., derived from terminal CWD/workspace folder) and calling getConfiguration('python', scope) so workspaceFolderValue can be evaluated.
    const pythonConfig = getConfiguration('python');
    const inspected = pythonConfig.inspect<boolean>('terminal.activateEnvInCurrentTerminal');


You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +413 to +423
const skipPreExistingTerminals = !shouldActivateInCurrentTerminal() && terminals().length > 0;
if (skipPreExistingTerminals) {
traceVerbose(
'python.terminal.activateEnvInCurrentTerminal is explicitly disabled, skipping activation for pre-existing terminals',
);
}

if (actType === ACT_TYPE_COMMAND) {
await Promise.all(terminals().map(async (t) => this.activateUsingCommand(api, t)));
if (!skipPreExistingTerminals) {
await Promise.all(terminals().map(async (t) => this.activateUsingCommand(api, t)));
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialize() calls terminals() multiple times (including while computing skipPreExistingTerminals and later when iterating). Capture a single snapshot (e.g., const existing = terminals();) and use it throughout initialize() so behavior is consistent and avoids repeated lookups while async work is in-flight.

Copilot uses AI. Check for mistakes.
Comment on lines +385 to +399
test('should return true when no explicit values are set (all undefined)', () => {
pythonConfig.inspect.withArgs('terminal.activateEnvInCurrentTerminal').returns({
key: 'terminal.activateEnvInCurrentTerminal',
defaultValue: false,
globalValue: undefined,
workspaceValue: undefined,
workspaceFolderValue: undefined,
});

assert.strictEqual(
shouldActivateInCurrentTerminal(),
true,
'Should return true when only defaultValue is set (not user-explicit)',
);
});
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests don’t cover the key precedence case where a higher-precedence explicit true should override a lower-precedence explicit false (e.g., workspaceValue: true with globalValue: false). Adding this case would catch incorrect precedence handling in shouldActivateInCurrentTerminal().

Copilot uses AI. Check for mistakes.
Comment on lines +495 to +503
test('initialize activates all pre-existing terminals when shouldActivateInCurrentTerminal returns true', async () => {
const terminal1 = createMockTerminal('terminal1');
const terminal2 = createMockTerminal('terminal2');
const env = createMockEnvironment();

mockGetAutoActivationType.returns(terminalUtils.ACT_TYPE_COMMAND);
mockShouldActivateInCurrentTerminal.returns(true);
mockTerminals.returns([terminal1, terminal2]);
mockGetEnvironmentForTerminal.resolves(env);
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialize() behavior was changed for both ACT_TYPE_COMMAND and ACT_TYPE_SHELL, but tests only exercise the command path. Add coverage for ACT_TYPE_SHELL to ensure activation fallback is also skipped (or performed) correctly when shouldActivateInCurrentTerminal() is false/true.

Copilot uses AI. Check for mistakes.
Comment on lines +292 to +306
if (inspected.workspaceFolderValue === false) {
return false;
}
if (inspected.workspaceValue === false) {
return false;
}
if ('globalRemoteValue' in inspected && inspectValue.globalRemoteValue === false) {
return false;
}
if ('globalLocalValue' in inspected && inspectValue.globalLocalValue === false) {
return false;
}
if (inspected.globalValue === false) {
return false;
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldActivateInCurrentTerminal() does not apply VS Code settings precedence correctly: a lower-precedence globalValue === false will force false even when a higher-precedence scope (workspace/workspaceFolder) explicitly sets true. Instead, follow the same pattern as getShellIntegrationEnabledCache(): return the first defined boolean in precedence order (workspaceFolderValue > workspaceValue > globalRemoteValue > globalLocalValue > globalValue), and default to true only when none are defined.

This issue also appears on line 281 of the same file.

Copilot uses AI. Check for mistakes.
public async initialize(api: PythonEnvironmentApi): Promise<void> {
const actType = getAutoActivationType();

// When activateEnvInCurrentTerminal is explicitly false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karthiknadig can you confirm the meaning of activateEnvInCurrentTerminal here- does that mean all that are currently open or the one the user is in?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I remember it is one which VSCode says is the focused terminal.

We should confirm this by seeing what Python ext specifically looks at.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is indeed focused terminal.
The thing is Python extension did not activate any terminal is activateEnvInCurrentTerminal is false.

Environment tries to activate ALL terminal by default, and with this PR (see the gif), we won't activate current (focused AND previous terminals in background) to more smoothly match Python ext behavior.

@anthonykim1 anthonykim1 marked this pull request as draft March 7, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-activation Issue related to activation. Root cause can be from interpreter selection or activation in terminal debt

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ensure that extension inherits core python activation settings

4 participants