Skip to content

Commit 3362dc3

Browse files
authored
enable turning off the variable provider (#24231)
along with microsoft/vscode#230349 let people disable the feature in case it causes perf issues
1 parent c60f0dd commit 3362dc3

File tree

4 files changed

+82
-3
lines changed

4 files changed

+82
-3
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,12 @@
680680
"experimental"
681681
]
682682
},
683+
"python.REPL.provideVariables": {
684+
"default": true,
685+
"description": "%python.REPL.provideVariables.description%",
686+
"scope": "resource",
687+
"type": "boolean"
688+
},
683689
"python.testing.autoTestDiscoverOnSaveEnabled": {
684690
"default": true,
685691
"description": "%python.testing.autoTestDiscoverOnSaveEnabled.description%",

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"python.pixiToolPath.description": "Path to the pixi executable.",
6666
"python.EnableREPLSmartSend.description": "Toggle Smart Send for the Python REPL. Smart Send enables sending the smallest runnable block of code to the REPL on Shift+Enter and moves the cursor accordingly.",
6767
"python.REPL.sendToNativeREPL.description": "Toggle to send code to Python REPL instead of the terminal on execution. Turning this on will change the behavior for both Smart Send and Run Selection/Line in the Context Menu.",
68+
"python.REPL.provideVariables.description": "Toggle to provide variables for the REPL variable view for the native REPL.",
6869
"python.tensorBoard.logDirectory.description": "Set this setting to your preferred TensorBoard log directory to skip log directory prompt when starting TensorBoard.",
6970
"python.tensorBoard.logDirectory.markdownDeprecationMessage": "Tensorboard support has been moved to the extension [Tensorboard extension](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.tensorboard). Instead use the setting `tensorBoard.logDirectory`.",
7071
"python.tensorBoard.logDirectory.deprecationMessage": "Tensorboard support has been moved to the extension Tensorboard extension. Instead use the setting `tensorBoard.logDirectory`.",

src/client/repl/variables/variablesProvider.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import {
1010
EventEmitter,
1111
Event,
1212
NotebookVariableProvider,
13+
Uri,
1314
} from 'vscode';
1415
import { VariableResultCache } from './variableResultCache';
1516
import { IVariableDescription } from './types';
1617
import { VariableRequester } from './variableRequester';
18+
import { getConfiguration } from '../../common/vscodeApis/workspaceApis';
1719

1820
export class VariablesProvider implements NotebookVariableProvider {
1921
private readonly variableResultCache = new VariableResultCache();
@@ -36,7 +38,9 @@ export class VariablesProvider implements NotebookVariableProvider {
3638
const notebook = this.getNotebookDocument();
3739
if (notebook) {
3840
this.executionCount += 1;
39-
this._onDidChangeVariables.fire(notebook);
41+
if (isEnabled(notebook.uri)) {
42+
this._onDidChangeVariables.fire(notebook);
43+
}
4044
}
4145
}
4246

@@ -48,7 +52,12 @@ export class VariablesProvider implements NotebookVariableProvider {
4852
token: CancellationToken,
4953
): AsyncIterable<VariablesResult> {
5054
const notebookDocument = this.getNotebookDocument();
51-
if (token.isCancellationRequested || !notebookDocument || notebookDocument !== notebook) {
55+
if (
56+
!isEnabled(notebook.uri) ||
57+
token.isCancellationRequested ||
58+
!notebookDocument ||
59+
notebookDocument !== notebook
60+
) {
5261
return;
5362
}
5463

@@ -144,3 +153,7 @@ function getVariableResultCacheKey(uri: string, parent: Variable | undefined, st
144153
}
145154
return `${uri}:${parentKey}`;
146155
}
156+
157+
function isEnabled(resource?: Uri) {
158+
return getConfiguration('python', resource).get('REPL.provideVariables');
159+
}

src/test/repl/variableProvider.test.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,29 @@
22
// Licensed under the MIT License.
33

44
import { assert } from 'chai';
5-
import { NotebookDocument, CancellationTokenSource, VariablesResult, Variable, EventEmitter } from 'vscode';
5+
import sinon from 'sinon';
6+
import {
7+
NotebookDocument,
8+
CancellationTokenSource,
9+
VariablesResult,
10+
Variable,
11+
EventEmitter,
12+
ConfigurationScope,
13+
WorkspaceConfiguration,
14+
} from 'vscode';
615
import * as TypeMoq from 'typemoq';
716
import { IVariableDescription } from '../../client/repl/variables/types';
817
import { VariablesProvider } from '../../client/repl/variables/variablesProvider';
918
import { VariableRequester } from '../../client/repl/variables/variableRequester';
19+
import * as workspaceApis from '../../client/common/vscodeApis/workspaceApis';
1020

1121
suite('ReplVariablesProvider', () => {
1222
let provider: VariablesProvider;
1323
let varRequester: TypeMoq.IMock<VariableRequester>;
1424
let notebook: TypeMoq.IMock<NotebookDocument>;
25+
let getConfigurationStub: sinon.SinonStub;
26+
let configMock: TypeMoq.IMock<WorkspaceConfiguration>;
27+
let enabled: boolean;
1528
const executionEventEmitter = new EventEmitter<void>();
1629
const cancellationToken = new CancellationTokenSource().token;
1730

@@ -68,9 +81,23 @@ suite('ReplVariablesProvider', () => {
6881
}
6982

7083
setup(() => {
84+
enabled = true;
7185
varRequester = TypeMoq.Mock.ofType<VariableRequester>();
7286
notebook = TypeMoq.Mock.ofType<NotebookDocument>();
7387
provider = new VariablesProvider(varRequester.object, () => notebook.object, executionEventEmitter.event);
88+
configMock = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
89+
configMock.setup((c) => c.get<boolean>('REPL.provideVariables')).returns(() => enabled);
90+
getConfigurationStub = sinon.stub(workspaceApis, 'getConfiguration');
91+
getConfigurationStub.callsFake((section?: string, _scope?: ConfigurationScope | null) => {
92+
if (section === 'python') {
93+
return configMock.object;
94+
}
95+
return undefined;
96+
});
97+
});
98+
99+
teardown(() => {
100+
sinon.restore();
74101
});
75102

76103
test('provideVariables without parent should yield variables', async () => {
@@ -84,6 +111,38 @@ suite('ReplVariablesProvider', () => {
84111
assert.equal(results[0].variable.expression, 'myObject');
85112
});
86113

114+
test('No variables are returned when variable provider is disabled', async () => {
115+
enabled = false;
116+
setVariablesForParent(undefined, [objectVariable]);
117+
118+
const results = await provideVariables(undefined);
119+
120+
assert.isEmpty(results);
121+
});
122+
123+
test('No change event from provider when disabled', async () => {
124+
enabled = false;
125+
let eventFired = false;
126+
provider.onDidChangeVariables(() => {
127+
eventFired = true;
128+
});
129+
130+
executionEventEmitter.fire();
131+
132+
assert.isFalse(eventFired, 'event should not have fired');
133+
});
134+
135+
test('Variables change event from provider should fire when execution happens', async () => {
136+
let eventFired = false;
137+
provider.onDidChangeVariables(() => {
138+
eventFired = true;
139+
});
140+
141+
executionEventEmitter.fire();
142+
143+
assert.isTrue(eventFired, 'event should have fired');
144+
});
145+
87146
test('provideVariables with a parent should call get children correctly', async () => {
88147
const listVariableItems = [0, 1, 2].map(createListItem);
89148
setVariablesForParent(undefined, [objectVariable]);

0 commit comments

Comments
 (0)