Skip to content

Commit b3d2252

Browse files
author
Kartik Raj
authored
Added diagnostic asking users to delete pythonPath from their workspace settings (#11180)
* Added prompt * Revert string
1 parent dbdd5cf commit b3d2252

9 files changed

Lines changed: 552 additions & 2 deletions

File tree

news/1 Enhancements/11108.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added prompt asking users to delete `python.pythonPath` key from their workspace settings when in Deprecate PythonPath experiment.

package.nls.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@
232232
"DataScience.liveShareServiceFailure": "Failure starting '{0}' service during live share connection.",
233233
"DataScience.documentMismatch": "Cannot run cells, duplicate documents for {0} found.",
234234
"DataScience.pythonInteractiveCreateFailed": "Failure to create a 'Python Interactive' window. Try reinstalling the Python extension.",
235+
"diagnostics.removePythonPathSettingsJson": "The setting \"python.pythonPath\" defined in your workspace settings is now deprecated. Do you want us to delete it? This will only remove the \"python.pythonPath\" entry from your settings.json.",
236+
"diagnostics.removePythonPathCodeWorkspace": "The setting \"python.pythonPath\" defined in your workspace settings is now deprecated. Do you want us to delete it? This will only remove the \"python.pythonPath\" entry from your .code-workspace file.",
237+
"diagnostics.removePythonPathCodeWorkspaceAndSettingsJson": "The setting \"python.pythonPath\" defined in your workspace settings is now deprecated. Do you want us to delete it? This will only remove the \"python.pythonPath\" entry from your settings.json and .code-workspace file.",
235238
"diagnostics.warnSourceMaps": "Source map support is enabled in the Python Extension, this will adversely impact performance of the extension.",
236239
"diagnostics.disableSourceMaps": "Disable Source Map Support",
237240
"diagnostics.warnBeforeEnablingSourceMaps": "Enabling source map support in the Python Extension will adversely impact performance of the extension.",
@@ -243,7 +246,6 @@
243246
"diagnostics.consoleTypeDiagnostic": "Your launch.json file needs to be updated to change the console type string from \"none\" to \"internalConsole\", otherwise Python debugging may not work. Would you like to automatically update your launch.json file now?",
244247
"diagnostics.justMyCodeDiagnostic": "Configuration \"debugStdLib\" in launch.json is no longer supported. It's recommended to replace it with \"justMyCode\", which is the exact opposite of using \"debugStdLib\". Would you like to automatically update your launch.json file to do that?",
245248
"diagnostics.yesUpdateLaunch": "Yes, update launch.json",
246-
"diagnostics.bannerLabelNo": "No, I will do it later",
247249
"diagnostics.processId": "Attaching the debugger to a local process is an experimental feature. It will be available to all users soon.",
248250
"diagnostics.invalidTestSettings": "Your settings needs to be updated to change the setting \"python.unitTest.\" to \"python.testing.\", otherwise testing Python code using the extension may not work. Would you like to automatically update your settings now?",
249251
"DataScience.interruptKernel": "Interrupt IPython kernel",
@@ -252,6 +254,7 @@
252254
"DataScience.exportCancel": "Cancel",
253255
"Common.canceled": "Canceled",
254256
"Common.cancel": "Cancel",
257+
"Common.yesPlease": "Yes, please",
255258
"DataScience.importChangeDirectoryComment": "{0} Change working directory from the workspace root to the ipynb file location. Turn this addition off with the DataScience.changeDirOnImportExport setting",
256259
"DataScience.exportChangeDirectoryComment": "# Change directory to VSCode workspace root so that relative path loads work correctly. Turn this addition off with the DataScience.changeDirOnImportExport setting",
257260
"DataScience.interruptKernelStatus": "Interrupting IPython Kernel",

package.nls.zh-tw.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@
9292
"diagnostics.consoleTypeDiagnostic": "Your launch.json file needs to be updated to change the console type string from \"none\" to \"internalConsole\", otherwise Python debugging may not work. Would you like to automatically update your launch.json file now?",
9393
"diagnostics.justMyCodeDiagnostic": "Configuration \"debugStdLib\" in launch.json is no longer supported. It's recommended to replace it with \"justMyCode\", which is the exact opposite of using \"debugStdLib\". Would you like to automatically update your launch.json file to do that?",
9494
"diagnostics.yesUpdateLaunch": "是,更新 launch.json",
95-
"diagnostics.bannerLabelNo": "否,我稍候再做",
9695
"diagnostics.processId": "Attaching the debugger to a local process is an experimental feature. It will be available to all users soon.",
9796
"diagnostics.invalidTestSettings": "Your settings needs to be updated to change the setting \"python.unitTest.\" to \"python.testing.\", otherwise testing Python code using the extension may not work. Would you like to automatically update your settings now?",
9897
"Common.canceled": "已取消",
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
import { inject, named } from 'inversify';
7+
import { ConfigurationTarget, DiagnosticSeverity } from 'vscode';
8+
import { IWorkspaceService } from '../../../common/application/types';
9+
import { DeprecatePythonPath } from '../../../common/experimentGroups';
10+
import { IDisposableRegistry, IExperimentsManager, Resource } from '../../../common/types';
11+
import { Common, Diagnostics } from '../../../common/utils/localize';
12+
import { learnMoreOnInterpreterSecurityURI } from '../../../interpreter/autoSelection/constants';
13+
import { IServiceContainer } from '../../../ioc/types';
14+
import { BaseDiagnostic, BaseDiagnosticsService } from '../base';
15+
import { IDiagnosticsCommandFactory } from '../commands/types';
16+
import { DiagnosticCodes } from '../constants';
17+
import { DiagnosticCommandPromptHandlerServiceId, MessageCommandPrompt } from '../promptHandler';
18+
import { DiagnosticScope, IDiagnostic, IDiagnosticHandlerService } from '../types';
19+
20+
export class PythonPathDeprecatedDiagnostic extends BaseDiagnostic {
21+
constructor(message: string, resource: Resource) {
22+
super(
23+
DiagnosticCodes.PythonPathDeprecatedDiagnostic,
24+
message,
25+
DiagnosticSeverity.Information,
26+
DiagnosticScope.WorkspaceFolder,
27+
resource
28+
);
29+
}
30+
}
31+
32+
export const PythonPathDeprecatedDiagnosticServiceId = 'PythonPathDeprecatedDiagnosticServiceId';
33+
34+
export class PythonPathDeprecatedDiagnosticService extends BaseDiagnosticsService {
35+
private workspaceService: IWorkspaceService;
36+
constructor(
37+
@inject(IServiceContainer) serviceContainer: IServiceContainer,
38+
@inject(IDiagnosticHandlerService)
39+
@named(DiagnosticCommandPromptHandlerServiceId)
40+
protected readonly messageService: IDiagnosticHandlerService<MessageCommandPrompt>,
41+
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry
42+
) {
43+
super([DiagnosticCodes.PythonPathDeprecatedDiagnostic], serviceContainer, disposableRegistry, true);
44+
this.workspaceService = this.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
45+
}
46+
public async diagnose(resource: Resource): Promise<IDiagnostic[]> {
47+
const experiments = this.serviceContainer.get<IExperimentsManager>(IExperimentsManager);
48+
experiments.sendTelemetryIfInExperiment(DeprecatePythonPath.control);
49+
if (!experiments.inExperiment(DeprecatePythonPath.experiment)) {
50+
return [];
51+
}
52+
const setting = this.workspaceService.getConfiguration('python', resource).inspect<string>('pythonPath');
53+
if (!setting) {
54+
return [];
55+
}
56+
const isCodeWorkspaceSettingSet = this.workspaceService.workspaceFile && setting.workspaceValue !== undefined;
57+
const isSettingsJsonSettingSet = setting.workspaceFolderValue !== undefined;
58+
if (isCodeWorkspaceSettingSet && isSettingsJsonSettingSet) {
59+
return [
60+
new PythonPathDeprecatedDiagnostic(Diagnostics.removePythonPathCodeWorkspaceAndSettingsJson(), resource)
61+
];
62+
} else if (isSettingsJsonSettingSet) {
63+
return [new PythonPathDeprecatedDiagnostic(Diagnostics.removePythonPathSettingsJson(), resource)];
64+
} else if (isCodeWorkspaceSettingSet) {
65+
return [new PythonPathDeprecatedDiagnostic(Diagnostics.removePythonPathCodeWorkspace(), resource)];
66+
}
67+
return [];
68+
}
69+
70+
public async _removePythonPathFromWorkspaceSettings(resource: Resource) {
71+
const workspaceConfig = this.workspaceService.getConfiguration('python', resource);
72+
await Promise.all([
73+
workspaceConfig.update('pythonPath', undefined, ConfigurationTarget.Workspace),
74+
workspaceConfig.update('pythonPath', undefined, ConfigurationTarget.WorkspaceFolder)
75+
]);
76+
}
77+
78+
protected async onHandle(diagnostics: IDiagnostic[]): Promise<void> {
79+
if (diagnostics.length === 0 || !(await this.canHandle(diagnostics[0]))) {
80+
return;
81+
}
82+
const diagnostic = diagnostics[0];
83+
if (await this.filterService.shouldIgnoreDiagnostic(diagnostic.code)) {
84+
return;
85+
}
86+
const commandFactory = this.serviceContainer.get<IDiagnosticsCommandFactory>(IDiagnosticsCommandFactory);
87+
const options = [
88+
{
89+
prompt: Common.yesPlease(),
90+
command: {
91+
diagnostic,
92+
invoke: async (): Promise<void> => {
93+
return this._removePythonPathFromWorkspaceSettings(diagnostic.resource);
94+
}
95+
}
96+
},
97+
{
98+
prompt: Common.noIWillDoItLater()
99+
},
100+
{
101+
prompt: Common.moreInfo(),
102+
command: commandFactory.createCommand(diagnostic, {
103+
type: 'launch',
104+
options: learnMoreOnInterpreterSecurityURI
105+
})
106+
},
107+
{
108+
prompt: Common.doNotShowAgain(),
109+
command: commandFactory.createCommand(diagnostic, { type: 'ignore', options: DiagnosticScope.Global })
110+
}
111+
];
112+
113+
await this.messageService.handle(diagnostic, { commandPrompts: options });
114+
}
115+
}

src/client/application/diagnostics/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum DiagnosticCodes {
1414
EnvironmentActivationInPowerShellWithBatchFilesNotSupportedDiagnostic = 'EnvironmentActivationInPowerShellWithBatchFilesNotSupportedDiagnostic',
1515
NoCurrentlySelectedPythonInterpreterDiagnostic = 'InvalidPythonInterpreterDiagnostic',
1616
LSNotSupportedDiagnostic = 'LSNotSupportedDiagnostic',
17+
PythonPathDeprecatedDiagnostic = 'PythonPathDeprecatedDiagnostic',
1718
JustMyCodeDiagnostic = 'JustMyCodeDiagnostic',
1819
ConsoleTypeDiagnostic = 'ConsoleTypeDiagnostic'
1920
}

src/client/application/diagnostics/serviceRegistry.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ import {
2929
PowerShellActivationHackDiagnosticsServiceId
3030
} from './checks/powerShellActivation';
3131
import { InvalidPythonInterpreterService, InvalidPythonInterpreterServiceId } from './checks/pythonInterpreter';
32+
import {
33+
PythonPathDeprecatedDiagnosticService,
34+
PythonPathDeprecatedDiagnosticServiceId
35+
} from './checks/pythonPathDeprecated';
3236
import { DiagnosticsCommandFactory } from './commands/factory';
3337
import { IDiagnosticsCommandFactory } from './commands/types';
3438
import { DiagnosticFilterService } from './filter';
@@ -76,6 +80,11 @@ export function registerTypes(serviceManager: IServiceManager, languageServerTyp
7680
InvalidMacPythonInterpreterService,
7781
InvalidMacPythonInterpreterServiceId
7882
);
83+
serviceManager.addSingleton<IDiagnosticsService>(
84+
IDiagnosticsService,
85+
PythonPathDeprecatedDiagnosticService,
86+
PythonPathDeprecatedDiagnosticServiceId
87+
);
7988
serviceManager.addSingleton<IDiagnosticsCommandFactory>(IDiagnosticsCommandFactory, DiagnosticsCommandFactory);
8089
serviceManager.addSingleton<IApplicationDiagnostics>(IApplicationDiagnostics, ApplicationDiagnostics);
8190

src/client/common/utils/localize.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ export namespace Diagnostics {
2626
'diagnostics.lsNotSupported',
2727
'Your operating system does not meet the minimum requirements of the Python Language Server. Reverting to the alternative autocompletion provider, Jedi.'
2828
);
29+
export const removePythonPathSettingsJson = localize(
30+
'diagnostics.removePythonPathSettingsJson',
31+
'The setting "python.pythonPath" defined in your workspace settings is now deprecated. Do you want us to delete it? This will only remove the "python.pythonPath" entry from your settings.json.'
32+
);
33+
export const removePythonPathCodeWorkspace = localize(
34+
'diagnostics.removePythonPathCodeWorkspace',
35+
'The setting "python.pythonPath" defined in your workspace settings is now deprecated. Do you want us to delete it? This will only remove the "python.pythonPath" entry from your .code-workspace file.'
36+
);
37+
export const removePythonPathCodeWorkspaceAndSettingsJson = localize(
38+
'diagnostics.removePythonPathCodeWorkspaceAndSettingsJson',
39+
'The setting "python.pythonPath" defined in your workspace settings is now deprecated. Do you want us to delete it? This will only remove the "python.pythonPath" entry from your settings.json and .code-workspace file.'
40+
);
2941
export const invalidPythonPathInDebuggerSettings = localize(
3042
'diagnostics.invalidPythonPathInDebuggerSettings',
3143
'You need to select a Python interpreter before you start debugging.\n\nTip: click on "Select Python Interpreter" in the status bar.'
@@ -61,6 +73,7 @@ export namespace Diagnostics {
6173
export namespace Common {
6274
export const bannerLabelYes = localize('Common.bannerLabelYes', 'Yes');
6375
export const bannerLabelNo = localize('Common.bannerLabelNo', 'No');
76+
export const yesPlease = localize('Common.yesPlease', 'Yes, please');
6477
export const canceled = localize('Common.canceled', 'Canceled');
6578
export const cancel = localize('Common.cancel', 'Cancel');
6679
export const ok = localize('Common.ok', 'Ok');

0 commit comments

Comments
 (0)