Skip to content

Commit c8d9e49

Browse files
Kartik Rajkarthiknadig
andauthored
Modified Select interpreter command & add a reset interpreter command (#10373)
* Modified `Select interpreter` command to support setting interpreter at workspace level * Added a command to reset value of Python interpreter * Code reviews * Update src/client/interpreter/configuration/interpreterSelector.ts Co-Authored-By: Karthik Nadig <[email protected]> Co-authored-by: Karthik Nadig <[email protected]>
1 parent a12c6bf commit c8d9e49

File tree

13 files changed

+523
-218
lines changed

13 files changed

+523
-218
lines changed

news/1 Enhancements/10372.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Modified `Select interpreter` command to support setting interpreter at workspace level.

news/1 Enhancements/10374.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added a command to reset value of Python interpreter.

package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"onCommand:python.switchOffInsidersChannel",
7474
"onCommand:python.switchToDailyChannel",
7575
"onCommand:python.switchToWeeklyChannel",
76+
"onCommand:python.resetPythonInterpreter",
7677
"onCommand:python.datascience.createnewnotebook",
7778
"onCommand:python.datascience.showhistorypane",
7879
"onCommand:python.datascience.importnotebook",
@@ -222,6 +223,11 @@
222223
"title": "%python.command.python.switchToWeeklyChannel.title%",
223224
"category": "Python"
224225
},
226+
{
227+
"command": "python.resetPythonInterpreter",
228+
"title": "%python.command.python.resetPythonInterpreter.title%",
229+
"category": "Python"
230+
},
225231
{
226232
"command": "python.refactorExtractVariable",
227233
"title": "%python.command.python.refactorExtractVariable.title%",
@@ -746,6 +752,11 @@
746752
"category": "Python",
747753
"when": "config.python.insidersChannel != 'weekly'"
748754
},
755+
{
756+
"command": "python.resetPythonInterpreter",
757+
"title": "%python.command.python.resetPythonInterpreter.title%",
758+
"category": "Python"
759+
},
749760
{
750761
"command": "python.viewOutput",
751762
"title": "%python.command.python.viewOutput.title%",

package.nls.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"python.command.python.switchOffInsidersChannel.title": "Switch to Default Channel",
1111
"python.command.python.switchToDailyChannel.title": "Switch to Insiders Daily Channel",
1212
"python.command.python.switchToWeeklyChannel.title": "Switch to Insiders Weekly Channel",
13+
"python.command.python.resetPythonInterpreter.title": "Reset Python Interpreter",
1314
"python.command.python.refactorExtractVariable.title": "Extract Variable",
1415
"python.command.python.refactorExtractMethod.title": "Extract Method",
1516
"python.command.python.viewOutput.title": "Show Output",
@@ -131,6 +132,7 @@
131132
"DataScience.connectingToJupyter": "Connecting to Jupyter server",
132133
"Experiments.inGroup": "User belongs to experiment group '{0}'",
133134
"Interpreters.RefreshingInterpreters": "Refreshing Python Interpreters",
135+
"Interpreters.entireWorkspace": "Entire workspace",
134136
"Interpreters.LoadingInterpreters": "Loading Python Interpreters",
135137
"Interpreters.condaInheritEnvMessage": "We noticed you're using a conda environment. If you are experiencing issues with this environment in the integrated terminal, we recommend that you let the Python extension change \"terminal.integrated.inheritEnv\" to false in your user settings.",
136138
"Logging.CurrentWorkingDirectory": "cwd:",

src/client/common/application/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type CommandsWithoutArgs = keyof ICommandNameWithoutArgumentTypeMapping;
2222
interface ICommandNameWithoutArgumentTypeMapping {
2323
[Commands.SwitchToInsidersDaily]: [];
2424
[Commands.SwitchToInsidersWeekly]: [];
25+
[Commands.ResetPythonInterpreter]: [];
2526
[Commands.SwitchOffInsidersChannel]: [];
2627
[Commands.Set_Interpreter]: [];
2728
[Commands.Set_ShebangInterpreter]: [];

src/client/common/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export namespace Commands {
6363
export const SwitchToInsidersDaily = 'python.switchToDailyChannel';
6464
export const SwitchToInsidersWeekly = 'python.switchToWeeklyChannel';
6565
export const PickLocalProcess = 'python.pickLocalProcess';
66+
export const ResetPythonInterpreter = 'python.resetPythonInterpreter';
6667
}
6768
export namespace Octicons {
6869
export const Test_Pass = '$(check)';

src/client/common/utils/localize.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export namespace Interpreters {
139139
'Interpreters.environmentPromptMessage',
140140
'We noticed a new virtual environment has been created. Do you want to select it for the workspace folder?'
141141
);
142+
export const entireWorkspace = localize('Interpreters.entireWorkspace', 'Entire workspace');
142143
export const selectInterpreterTip = localize(
143144
'Interpreters.selectInterpreterTip',
144145
'Tip: you can change the Python interpreter used by the Python extension by clicking on the Python version in the status bar'

src/client/interpreter/configuration/interpreterSelector.ts

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { inject, injectable } from 'inversify';
2-
import { ConfigurationTarget, Disposable, QuickPickOptions, Uri } from 'vscode';
2+
import * as path from 'path';
3+
import { ConfigurationTarget, Disposable, QuickPickItem, QuickPickOptions, Uri } from 'vscode';
34
import {
45
IApplicationShell,
56
ICommandManager,
@@ -8,7 +9,8 @@ import {
89
} from '../../common/application/types';
910
import { Commands } from '../../common/constants';
1011
import { IConfigurationService, IPathUtils, Resource } from '../../common/types';
11-
import { IInterpreterService, IShebangCodeLensProvider, PythonInterpreter, WorkspacePythonPath } from '../contracts';
12+
import { Interpreters } from '../../common/utils/localize';
13+
import { IInterpreterService, IShebangCodeLensProvider, PythonInterpreter } from '../contracts';
1214
import {
1315
IInterpreterComparer,
1416
IInterpreterQuickPickItem,
@@ -41,6 +43,9 @@ export class InterpreterSelector implements IInterpreterSelector {
4143
this.disposables.push(
4244
this.commandManager.registerCommand(Commands.Set_Interpreter, this.setInterpreter.bind(this))
4345
);
46+
this.disposables.push(
47+
this.commandManager.registerCommand(Commands.ResetPythonInterpreter, this.resetInterpreter.bind(this))
48+
);
4449
this.disposables.push(
4550
this.commandManager.registerCommand(Commands.Set_ShebangInterpreter, this.setShebangInterpreter.bind(this))
4651
);
@@ -51,6 +56,17 @@ export class InterpreterSelector implements IInterpreterSelector {
5156
interpreters.sort(this.interpreterComparer.compare.bind(this.interpreterComparer));
5257
return Promise.all(interpreters.map(item => this.suggestionToQuickPickItem(item, resource)));
5358
}
59+
60+
protected async resetInterpreter() {
61+
const targetConfig = await this.getConfigTarget();
62+
if (!targetConfig) {
63+
return;
64+
}
65+
const configTarget = targetConfig.configTarget;
66+
const wkspace = targetConfig.folderUri;
67+
68+
await this.pythonPathUpdaterService.updatePythonPath(undefined, configTarget, 'ui', wkspace);
69+
}
5470
protected async suggestionToQuickPickItem(
5571
suggestion: PythonInterpreter,
5672
workspaceUri?: Uri
@@ -67,19 +83,12 @@ export class InterpreterSelector implements IInterpreterSelector {
6783
}
6884

6985
protected async setInterpreter() {
70-
const setInterpreterGlobally =
71-
!Array.isArray(this.workspaceService.workspaceFolders) ||
72-
this.workspaceService.workspaceFolders.length === 0;
73-
let configTarget = ConfigurationTarget.Global;
74-
let wkspace: Uri | undefined;
75-
if (!setInterpreterGlobally) {
76-
const targetConfig = await this.getWorkspaceToSetPythonPath();
77-
if (!targetConfig) {
78-
return;
79-
}
80-
configTarget = targetConfig.configTarget;
81-
wkspace = targetConfig.folderUri;
86+
const targetConfig = await this.getConfigTarget();
87+
if (!targetConfig) {
88+
return;
8289
}
90+
const configTarget = targetConfig.configTarget;
91+
const wkspace = targetConfig.folderUri;
8392

8493
const suggestions = await this.getSuggestions(wkspace);
8594
const currentPythonPath = this.pathUtils.getDisplayName(
@@ -138,12 +147,21 @@ export class InterpreterSelector implements IInterpreterSelector {
138147
workspaceFolder.uri
139148
);
140149
}
141-
private async getWorkspaceToSetPythonPath(): Promise<WorkspacePythonPath | undefined> {
150+
private async getConfigTarget(): Promise<
151+
| {
152+
folderUri: Resource;
153+
configTarget: ConfigurationTarget;
154+
}
155+
| undefined
156+
> {
142157
if (
143158
!Array.isArray(this.workspaceService.workspaceFolders) ||
144159
this.workspaceService.workspaceFolders.length === 0
145160
) {
146-
return undefined;
161+
return {
162+
folderUri: undefined,
163+
configTarget: ConfigurationTarget.Global
164+
};
147165
}
148166
if (this.workspaceService.workspaceFolders.length === 1) {
149167
return {
@@ -153,11 +171,30 @@ export class InterpreterSelector implements IInterpreterSelector {
153171
}
154172

155173
// Ok we have multiple workspaces, get the user to pick a folder.
156-
const workspaceFolder = await this.applicationShell.showWorkspaceFolderPick({
174+
175+
type WorkspaceSelectionQuickPickItem = QuickPickItem & { uri: Uri };
176+
const quickPickItems: WorkspaceSelectionQuickPickItem[] = [
177+
...this.workspaceService.workspaceFolders.map(w => {
178+
({
179+
label: w.name,
180+
description: path.dirname(w.uri.fsPath),
181+
uri: w.uri
182+
})
183+
}),
184+
{
185+
label: Interpreters.entireWorkspace(),
186+
uri: this.workspaceService.workspaceFolders[0].uri
187+
}
188+
];
189+
190+
const selection = await this.applicationShell.showQuickPick(quickPickItems, {
157191
placeHolder: 'Select the workspace to set the interpreter'
158192
});
159-
return workspaceFolder
160-
? { folderUri: workspaceFolder.uri, configTarget: ConfigurationTarget.WorkspaceFolder }
193+
194+
return selection
195+
? selection.label === Interpreters.entireWorkspace()
196+
? { folderUri: selection.uri, configTarget: ConfigurationTarget.Workspace }
197+
: { folderUri: selection.uri, configTarget: ConfigurationTarget.WorkspaceFolder }
161198
: undefined;
162199
}
163200
}

src/client/interpreter/configuration/pythonPathUpdaterService.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class PythonPathUpdaterService implements IPythonPathUpdaterServiceManage
2424
this.executionFactory = serviceContainer.get<IPythonExecutionFactory>(IPythonExecutionFactory);
2525
}
2626
public async updatePythonPath(
27-
pythonPath: string,
27+
pythonPath: string | undefined,
2828
configTarget: ConfigurationTarget,
2929
trigger: 'ui' | 'shebang' | 'load',
3030
wkspace?: Uri
@@ -33,7 +33,7 @@ export class PythonPathUpdaterService implements IPythonPathUpdaterServiceManage
3333
const pythonPathUpdater = this.getPythonUpdaterService(configTarget, wkspace);
3434
let failed = false;
3535
try {
36-
await pythonPathUpdater.updatePythonPath(path.normalize(pythonPath));
36+
await pythonPathUpdater.updatePythonPath(pythonPath ? path.normalize(pythonPath) : undefined);
3737
} catch (reason) {
3838
failed = true;
3939
// tslint:disable-next-line:no-unsafe-any prefer-type-cast
@@ -50,13 +50,13 @@ export class PythonPathUpdaterService implements IPythonPathUpdaterServiceManage
5050
duration: number,
5151
failed: boolean,
5252
trigger: 'ui' | 'shebang' | 'load',
53-
pythonPath: string
53+
pythonPath: string | undefined
5454
) {
5555
const telemtryProperties: PythonInterpreterTelemetry = {
5656
failed,
5757
trigger
5858
};
59-
if (!failed) {
59+
if (!failed && pythonPath) {
6060
const processService = await this.executionFactory.create({ pythonPath });
6161
const infoPromise = processService
6262
.getInterpreterInformation()

src/client/interpreter/configuration/services/globalUpdaterService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IPythonPathUpdaterService } from '../types';
33

44
export class GlobalPythonPathUpdaterService implements IPythonPathUpdaterService {
55
constructor(private readonly workspaceService: IWorkspaceService) {}
6-
public async updatePythonPath(pythonPath: string): Promise<void> {
6+
public async updatePythonPath(pythonPath: string | undefined): Promise<void> {
77
const pythonConfig = this.workspaceService.getConfiguration('python');
88
const pythonPathValue = pythonConfig.inspect<string>('pythonPath');
99

src/client/interpreter/configuration/services/workspaceFolderUpdaterService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import { IPythonPathUpdaterService } from '../types';
55

66
export class WorkspaceFolderPythonPathUpdaterService implements IPythonPathUpdaterService {
77
constructor(private workspaceFolder: Uri, private readonly workspaceService: IWorkspaceService) {}
8-
public async updatePythonPath(pythonPath: string): Promise<void> {
8+
public async updatePythonPath(pythonPath: string | undefined): Promise<void> {
99
const pythonConfig = this.workspaceService.getConfiguration('python', this.workspaceFolder);
1010
const pythonPathValue = pythonConfig.inspect<string>('pythonPath');
1111

1212
if (pythonPathValue && pythonPathValue.workspaceFolderValue === pythonPath) {
1313
return;
1414
}
15-
if (pythonPath.startsWith(this.workspaceFolder.fsPath)) {
15+
if (pythonPath && pythonPath.startsWith(this.workspaceFolder.fsPath)) {
1616
pythonPath = path.relative(this.workspaceFolder.fsPath, pythonPath);
1717
}
1818
await pythonConfig.update('pythonPath', pythonPath, ConfigurationTarget.WorkspaceFolder);

src/client/interpreter/configuration/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Resource } from '../../common/types';
33
import { PythonInterpreter } from '../contracts';
44

55
export interface IPythonPathUpdaterService {
6-
updatePythonPath(pythonPath: string): Promise<void>;
6+
updatePythonPath(pythonPath: string | undefined): Promise<void>;
77
}
88

99
export const IPythonPathUpdaterServiceFactory = Symbol('IPythonPathUpdaterServiceFactory');
@@ -16,7 +16,7 @@ export interface IPythonPathUpdaterServiceFactory {
1616
export const IPythonPathUpdaterServiceManager = Symbol('IPythonPathUpdaterServiceManager');
1717
export interface IPythonPathUpdaterServiceManager {
1818
updatePythonPath(
19-
pythonPath: string,
19+
pythonPath: string | undefined,
2020
configTarget: ConfigurationTarget,
2121
trigger: 'ui' | 'shebang' | 'load',
2222
wkspace?: Uri

0 commit comments

Comments
 (0)