Skip to content

Commit d95f454

Browse files
Kartik Rajkarthiknadig
andauthored
Deprecate PythonPath - Part 1 (#11011)
* 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 <kanadig@microsoft.com> Co-authored-by: Karthik Nadig <kanadig@microsoft.com> * Implemented new interpreter storage supporting multiroot workspaces (#10325) * Added python.defaultInterpreterPath setting * Created persistent storage infrastructure * Added vscode.workspace.workspaceFile API * Implemented inspect interpreter path * Implement config service updater for pythonPath * Correct build errors * Change extension to use new infrastructure * Store service container in a global variable * Update settings in the new way src/test/common * Correct cyclic dependency between IExperimentsManager and IConfigurationService * Detect change in new interpreter storage and act accordingly * Added reset python interpreters command * Cache the auto selected interpreter * Log python interpreter in the output channel * Fix autoselection and speed up the interpreter change process * Reset experiments * Reset python interpreters for workspace * Remove reset interpreter command from this PR * Added news entry * Update getWorkspaceFolderIdentifier * Code reviews * Dispose handler * More code reviews * Resolve merge conflicts * Fix issues * Some more fixes * More fixes * Do not assume ACTIVATED_SERVICE_CONTAINER is defined * Fix running tests * Fix cacheUtils.ts and test/common.ts * Correct cacheResourceSpecificInterpreterData decorator * Added tests for decorator-like implementation in enviroment provider * Code reviews * Fix interpreter service unit tests * Fix interpreter display unit tests * Fix mac interpreter unit tests * Fix interpreter selector unit tests * Fix configSettings pythonPath unit tests * Fix configSettings unit tests * Rebase with master * Fix installer.test.ts tests * Fix moduleInstaller.test.ts tests * Fix pythonPathUpdater.test.ts tests * Fix pythonProc.simple.multiroot.test.ts tests * Fix data science functional tests * Fix smoke tests * Use user friendly path in the output channel * Use symbols directly * Fix bug with configSettings.ts * Fix venv tests * Run all tests with the new interpreter storage" * Restore YAML pipeline * Fix absolute path resolver * Run all tests with old interpreter storage * Reduce run time of venv tests * Run only mac multiroot * Remove experiment from experiments.json * Added tests for Interpreter path service * saa * Ensure we use `CI_PYTHON_PATH` when running tests with the new interpreter storage * Reset global interpreter path as well * Added tests for mac interpreter diagnostic * Added tests for src\client\interpreter\autoSelection\rules\settings.ts * Added tests for src\client\interpreter\configuration\pythonPathUpdaterServiceFactory.ts * Added tests for src\client\interpreter\autoSelection\rules\workspaceEnv.ts * Added tests for src\client\interpreter\interpreterService.ts * Added tests for src\client\common\configuration\service.ts * Added tests for src\client\startupTelemetry.ts * Correct tests * Module installer tests * Code reviews * More code reviews * Fix lint error * Prompt when an "unsafe" workspace python environment is to be autoselected (#10430) * Implement prompt when an unsafe workspace python environment is to be autoselected * Code reviews * Refactor pythonPath stuff into a private method * Use variable instead of hardcoding 'python' string * Added tests for src\client\interpreter\autoSelection\interpreterSecurity\interpreterSecurityCommands.ts * Don't register command in the constructor * Refactored code * Updated tests * Code reviews * Moved bannerLabelYes/No to Common() namespace * Update content for news entry * Corrected activation manager tests * Fix single workspace CI tests * Fix multiroot tests + Code reviews * Rename Interpreter Security clear command * Fix tests * Added intellisense for pythonpath experiment * Fix multiroot tests * Rename `Reset interpreter` command to `Clear workspace interpreter setting * Fix bug with interpreter security storage * Correct prettier errors * Edit news entries appropriately * Git rebase * Code reviews Co-authored-by: Karthik Nadig <kanadig@microsoft.com>
1 parent 77bf701 commit d95f454

104 files changed

Lines changed: 5385 additions & 1774 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

experiments.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@
160160
"salt": "EnableIPyWidgets",
161161
"min": 0,
162162
"max": 0
163+
},
164+
{
165+
"name": "DeprecatePythonPath - experiment",
166+
"salt": "DeprecatePythonPath",
167+
"min": 0,
168+
"max": 0
169+
},
170+
{
171+
"name": "DeprecatePythonPath - control",
172+
"salt": "DeprecatePythonPath",
173+
"min": 100,
174+
"max": 100
163175
}
164-
165176
]

news/1 Enhancements/10325.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use new interpreter storage supporting multiroot workspaces when in Deprecate PythonPath experiment.

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 `Clear Workspace Interpreter Setting` to clear value of Python interpreter from workspace settings.

news/1 Enhancements/10879.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prompt when an "untrusted" workspace Python environment is to be auto selected when in Deprecate PythonPath experiment.

news/1 Enhancements/10912.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added a command `Reset stored info for untrusted Interpreters` to reset "untrusted" interpreters storage when in Deprecate PythonPath experiment.

news/1 Enhancements/11021.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added a user setting `python.defaultInterpreterPath` to set up the default interpreter path when in Deprecate PythonPath experiment.

package.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@
7474
"onCommand:python.switchOffInsidersChannel",
7575
"onCommand:python.switchToDailyChannel",
7676
"onCommand:python.switchToWeeklyChannel",
77+
"onCommand:python.clearWorkspaceInterpreter",
78+
"onCommand:python.resetInterpreterSecurityStorage",
7779
"onCommand:python.datascience.createnewnotebook",
7880
"onCommand:python.datascience.showhistorypane",
7981
"onCommand:python.datascience.importnotebook",
@@ -224,6 +226,16 @@
224226
"title": "%python.command.python.switchToWeeklyChannel.title%",
225227
"category": "Python"
226228
},
229+
{
230+
"command": "python.clearWorkspaceInterpreter",
231+
"title": "%python.command.python.clearWorkspaceInterpreter.title%",
232+
"category": "Python"
233+
},
234+
{
235+
"command": "python.resetInterpreterSecurityStorage",
236+
"title": "%python.command.python.resetInterpreterSecurityStorage.title%",
237+
"category": "Python"
238+
},
227239
{
228240
"command": "python.refactorExtractVariable",
229241
"title": "%python.command.python.refactorExtractVariable.title%",
@@ -753,6 +765,16 @@
753765
"category": "Python",
754766
"when": "config.python.insidersChannel != 'weekly'"
755767
},
768+
{
769+
"command": "python.clearWorkspaceInterpreter",
770+
"title": "%python.command.python.clearWorkspaceInterpreter.title%",
771+
"category": "Python"
772+
},
773+
{
774+
"command": "python.resetInterpreterSecurityStorage",
775+
"title": "%python.command.python.resetInterpreterSecurityStorage.title%",
776+
"category": "Python"
777+
},
756778
{
757779
"command": "python.viewOutput",
758780
"title": "%python.command.python.viewOutput.title%",
@@ -1554,6 +1576,12 @@
15541576
"description": "Enables/disables A/B tests.",
15551577
"scope": "machine"
15561578
},
1579+
"python.defaultInterpreterPath": {
1580+
"type": "string",
1581+
"default": "python",
1582+
"description": "Path to Python, you can use a custom version of Python by modifying this setting to include the full path.",
1583+
"scope": "machine"
1584+
},
15571585
"python.experiments.optInto": {
15581586
"type": "array",
15591587
"default": [],
@@ -1571,6 +1599,7 @@
15711599
"UseTerminalToGetActivatedEnvVars - experiment",
15721600
"CollectLSRequestTiming - experiment",
15731601
"CollectNodeLSRequestTiming - experiment",
1602+
"DeprecatePythonPath - experiment",
15741603
"All"
15751604
]
15761605
},
@@ -1594,6 +1623,7 @@
15941623
"UseTerminalToGetActivatedEnvVars - experiment",
15951624
"CollectLSRequestTiming - experiment",
15961625
"CollectNodeLSRequestTiming - experiment",
1626+
"DeprecatePythonPath - experiment",
15971627
"All"
15981628
]
15991629
},

package.nls.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
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.clearWorkspaceInterpreter.title": "Clear Workspace Interpreter Setting",
14+
"python.command.python.resetInterpreterSecurityStorage.title": "Reset Stored Info for Untrusted Interpreters",
1315
"python.command.python.refactorExtractVariable.title": "Extract Variable",
1416
"python.command.python.refactorExtractMethod.title": "Extract Method",
1517
"python.command.python.viewOutput.title": "Show Output",
@@ -131,14 +133,20 @@
131133
"DataScience.connectingToJupyter": "Connecting to Jupyter server",
132134
"Experiments.inGroup": "User belongs to experiment group '{0}'",
133135
"Interpreters.RefreshingInterpreters": "Refreshing Python Interpreters",
136+
"Interpreters.entireWorkspace": "Entire workspace",
137+
"Interpreters.pythonInterpreterPath": "Python interpreter path: {0}",
134138
"Interpreters.LoadingInterpreters": "Loading Python Interpreters",
139+
"Interpreters.unsafeInterpreterMessage": "We found a Python environment in this workspace. Do you want to select it to start up the features in the Python extension? Only accept if you trust this environment.",
135140
"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.",
136141
"Logging.CurrentWorkingDirectory": "cwd:",
142+
"Common.bannerLabelYes": "Yes",
143+
"Common.bannerLabelNo": "No",
137144
"Common.doNotShowAgain": "Do not show again",
138145
"Common.reload": "Reload",
139146
"Common.moreInfo": "More Info",
140147
"Common.and": "and",
141148
"Common.install": "Install",
149+
"Common.learnMore": "Learn more",
142150
"OutputChannelNames.languageServer": "Python Language Server",
143151
"OutputChannelNames.python": "Python",
144152
"OutputChannelNames.pythonTest": "Python Test Log",
@@ -166,8 +174,6 @@
166174
"DataScienceSurveyBanner.bannerLabelYes": "Yes, take survey now",
167175
"DataScienceSurveyBanner.bannerLabelNo": "No, thanks",
168176
"InteractiveShiftEnterBanner.bannerMessage": "Would you like to run code in the 'Python Interactive' window (an IPython console) for 'shift-enter'? Select 'No' to continue to run code in the Python Terminal. This can be changed later in settings.",
169-
"InteractiveShiftEnterBanner.bannerLabelYes": "Yes",
170-
"InteractiveShiftEnterBanner.bannerLabelNo": "No",
171177
"DataScience.restartingKernelStatus": "Restarting IPython Kernel",
172178
"DataScience.executingCode": "Executing Cell",
173179
"DataScience.collapseAll": "Collapse all cell inputs",

src/client/activation/activationManager.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@ import { inject, injectable, multiInject } from 'inversify';
77
import { TextDocument } from 'vscode';
88
import { IApplicationDiagnostics } from '../application/types';
99
import { IActiveResourceService, IDocumentManager, IWorkspaceService } from '../common/application/types';
10-
import { PYTHON_LANGUAGE } from '../common/constants';
10+
import { DEFAULT_INTERPRETER_SETTING, PYTHON_LANGUAGE } from '../common/constants';
11+
import { DeprecatePythonPath } from '../common/experimentGroups';
1112
import { traceDecorators } from '../common/logger';
1213
import { IFileSystem } from '../common/platform/types';
13-
import { IDisposable, Resource } from '../common/types';
14-
import { IInterpreterAutoSelectionService } from '../interpreter/autoSelection/types';
14+
import { IDisposable, IExperimentsManager, IInterpreterPathService, Resource } from '../common/types';
15+
import { createDeferred, Deferred } from '../common/utils/async';
16+
import { IInterpreterAutoSelectionService, IInterpreterSecurityService } from '../interpreter/autoSelection/types';
1517
import { IInterpreterService } from '../interpreter/contracts';
1618
import { sendActivationTelemetry } from '../telemetry/envFileTelemetry';
1719
import { IExtensionActivationManager, IExtensionActivationService, IExtensionSingleActivationService } from './types';
1820

1921
@injectable()
2022
export class ExtensionActivationManager implements IExtensionActivationManager {
2123
public readonly activatedWorkspaces = new Set<string>();
24+
protected readonly isInterpreterSetForWorkspacePromises = new Map<string, Deferred<void>>();
2225
private readonly disposables: IDisposable[] = [];
2326
private docOpenedHandler?: IDisposable;
2427
constructor(
@@ -31,7 +34,10 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
3134
@inject(IApplicationDiagnostics) private readonly appDiagnostics: IApplicationDiagnostics,
3235
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,
3336
@inject(IFileSystem) private readonly fileSystem: IFileSystem,
34-
@inject(IActiveResourceService) private readonly activeResourceService: IActiveResourceService
37+
@inject(IActiveResourceService) private readonly activeResourceService: IActiveResourceService,
38+
@inject(IExperimentsManager) private readonly experiments: IExperimentsManager,
39+
@inject(IInterpreterPathService) private readonly interpreterPathService: IInterpreterPathService,
40+
@inject(IInterpreterSecurityService) private readonly interpreterSecurityService: IInterpreterSecurityService
3541
) {}
3642

3743
public dispose() {
@@ -66,6 +72,7 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
6672
await sendActivationTelemetry(this.fileSystem, this.workspaceService, resource);
6773

6874
await this.autoSelection.autoSelectInterpreter(resource);
75+
await this.evaluateAutoSelectedInterpreterSafety(resource);
6976
await Promise.all(this.activationServices.map((item) => item.activate(resource)));
7077
await this.appDiagnostics.performPreStartupHealthCheck(resource);
7178
}
@@ -88,8 +95,38 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
8895
const folder = this.workspaceService.getWorkspaceFolder(doc.uri);
8996
this.activateWorkspace(folder ? folder.uri : undefined).ignoreErrors();
9097
}
98+
99+
public async evaluateAutoSelectedInterpreterSafety(resource: Resource) {
100+
if (this.experiments.inExperiment(DeprecatePythonPath.experiment)) {
101+
const workspaceKey = this.getWorkspaceKey(resource);
102+
const interpreterSettingValue = this.interpreterPathService.get(resource);
103+
if (interpreterSettingValue.length === 0 || interpreterSettingValue === DEFAULT_INTERPRETER_SETTING) {
104+
// Setting is not set, extension will use the autoselected value. Make sure it's safe.
105+
const interpreter = this.autoSelection.getAutoSelectedInterpreter(resource);
106+
if (interpreter) {
107+
const isInterpreterSetForWorkspace = createDeferred<void>();
108+
this.isInterpreterSetForWorkspacePromises.set(workspaceKey, isInterpreterSetForWorkspace);
109+
await Promise.race([
110+
isInterpreterSetForWorkspace.promise,
111+
this.interpreterSecurityService.evaluateAndRecordInterpreterSafety(interpreter, resource)
112+
]);
113+
}
114+
} else {
115+
// Resolve any concurrent calls waiting on the promise
116+
if (this.isInterpreterSetForWorkspacePromises.has(workspaceKey)) {
117+
this.isInterpreterSetForWorkspacePromises.get(workspaceKey)!.resolve();
118+
this.isInterpreterSetForWorkspacePromises.delete(workspaceKey);
119+
}
120+
}
121+
}
122+
this.experiments.sendTelemetryIfInExperiment(DeprecatePythonPath.control);
123+
}
124+
91125
protected addHandlers() {
92126
this.disposables.push(this.workspaceService.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged, this));
127+
this.disposables.push(
128+
this.interpreterPathService.onDidChange((i) => this.evaluateAutoSelectedInterpreterSafety(i.uri))
129+
);
93130
}
94131
protected addRemoveDocOpenedHandlers() {
95132
if (this.hasMultipleWorkspaces()) {

0 commit comments

Comments
 (0)