Skip to content

Commit 65c22e4

Browse files
authored
Provide options support for refreshInterpreters API. (#18316)
* Provide options support for refreshInterpreters API. * Fire event to indicate cache is getting cleared.
1 parent 2c75b7d commit 65c22e4

File tree

6 files changed

+32
-27
lines changed

6 files changed

+32
-27
lines changed

src/client/apiTypes.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ export interface ActiveInterpreterChangedParams {
108108
resource?: Uri;
109109
}
110110

111+
export interface RefreshInterpretersOptions {
112+
clearCache?: boolean;
113+
}
114+
111115
export interface IProposedExtensionAPI {
112116
environment: {
113117
/**
@@ -151,8 +155,11 @@ export interface IProposedExtensionAPI {
151155
* This API will re-trigger environment discovery. Extensions can wait on the returned
152156
* promise to get the updated interpreters list. If there is a refresh already going on
153157
* then it returns the promise for that refresh.
158+
* @param options : [optional]
159+
* * clearCache : When true, this will clear the cache before interpreter refresh
160+
* is triggered.
154161
*/
155-
refreshInterpreters(): Promise<string[] | undefined>;
162+
refreshInterpreters(options?: RefreshInterpretersOptions): Promise<string[] | undefined>;
156163
/**
157164
* Returns a promise for the ongoing refresh. Returns `undefined` if there are no active
158165
* refreshes going on.

src/client/proposedApi.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
InterpreterDetailsOptions,
99
InterpretersChangedParams,
1010
IProposedExtensionAPI,
11+
RefreshInterpretersOptions,
1112
} from './apiTypes';
1213
import { IConfigurationService, IInterpreterPathService, Resource } from './common/types';
1314
import { IComponentAdapter } from './interpreter/contracts';
@@ -97,8 +98,8 @@ export function buildProposedApi(
9798
setActiveInterpreter(interpreterPath: string, resource?: Resource): Promise<void> {
9899
return interpreterPathService.update(resource, ConfigurationTarget.Workspace, interpreterPath);
99100
},
100-
async refreshInterpreters(): Promise<string[] | undefined> {
101-
await discoveryApi.triggerRefresh(undefined);
101+
async refreshInterpreters(options?: RefreshInterpretersOptions): Promise<string[] | undefined> {
102+
await discoveryApi.triggerRefresh(options ? { clearCache: options.clearCache } : undefined);
102103
const paths = discoveryApi.getEnvs().map((e) => e.executable.filename);
103104
return Promise.resolve(paths);
104105
},

src/client/pythonEnvironments/base/locator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export interface IDiscoveryAPI {
182182
/**
183183
* Triggers a new refresh for query if there isn't any already running.
184184
*/
185-
triggerRefresh(query?: PythonLocatorQuery): Promise<void>;
185+
triggerRefresh(query?: PythonLocatorQuery & { clearCache?: boolean }): Promise<void>;
186186
/**
187187
* Get current list of known environments.
188188
*/

src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts

+14
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ export interface IEnvsCollectionCache {
5151
* validating cache.
5252
*/
5353
validateCache(): Promise<void>;
54+
55+
/**
56+
* Clears the in-memory cache. This can be used for hard refresh.
57+
*/
58+
clearCache(): Promise<void>;
5459
}
5560

5661
export type PythonEnvCompleteInfo = { hasCompleteInfo?: boolean } & PythonEnvInfo;
@@ -134,6 +139,15 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher<PythonEnvCollectionCha
134139
await this.persistentStorage.store(this.envs);
135140
}
136141
}
142+
143+
public clearCache(): Promise<void> {
144+
this.envs.forEach((e) => {
145+
this.fire({ old: e, new: undefined });
146+
});
147+
reportInterpretersChanged([{ path: undefined, type: 'clear-all' }]);
148+
this.envs = [];
149+
return Promise.resolve();
150+
}
137151
}
138152

139153
/**

src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts

+4-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import '../../../../common/extensions';
66
import { createDeferred } from '../../../../common/utils/async';
77
import { StopWatch } from '../../../../common/utils/stopWatch';
88
import { traceError } from '../../../../logging';
9-
import { reportInterpretersChanged } from '../../../../proposedApi';
109
import { sendTelemetryEvent } from '../../../../telemetry';
1110
import { EventName } from '../../../../telemetry/constants';
1211
import { PythonEnvInfo } from '../../info';
@@ -81,23 +80,20 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection
8180
return query ? cachedEnvs.filter(getQueryFilter(query)) : cachedEnvs;
8281
}
8382

84-
public triggerRefresh(query?: PythonLocatorQuery): Promise<void> {
83+
public triggerRefresh(query?: PythonLocatorQuery & { clearCache?: boolean }): Promise<void> {
8584
let refreshPromise = this.getRefreshPromiseForQuery(query);
8685
if (!refreshPromise) {
8786
refreshPromise = this.startRefresh(query);
8887
}
8988
return refreshPromise;
9089
}
9190

92-
private startRefresh(query: PythonLocatorQuery | undefined): Promise<void> {
91+
private startRefresh(query: (PythonLocatorQuery & { clearCache?: boolean }) | undefined): Promise<void> {
9392
const stopWatch = new StopWatch();
9493
const deferred = createDeferred<void>();
9594

96-
if (!query) {
97-
// `undefined` query means this is full refresh of environments.
98-
// Trigger an event indicating that we need to clear everything and start
99-
// fresh.
100-
reportInterpretersChanged([{ path: undefined, type: 'clear-all' }]);
95+
if (query?.clearCache) {
96+
this.cache.clearCache();
10197
}
10298
// Ensure we set this before we trigger the promise to accurately track when a refresh has started.
10399
this.refreshPromises.set(query, deferred.promise);

src/test/pythonEnvironments/base/locators/composite/envsCollectionService.unit.test.ts

+2-15
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ suite('Python envs locator - Environments Collection', async () => {
158158
}),
159159
);
160160

161-
sinon.assert.calledWithExactly(reportInterpretersChangedStub, [{ path: undefined, type: 'clear-all' }]);
162161
envs.forEach((e) => {
163162
sinon.assert.calledWithExactly(reportInterpretersChangedStub, [
164163
{
@@ -167,9 +166,7 @@ suite('Python envs locator - Environments Collection', async () => {
167166
},
168167
]);
169168
});
170-
171-
// One for each environment and one for global 'clear-all' event.
172-
sinon.assert.callCount(reportInterpretersChangedStub, envs.length + 1);
169+
sinon.assert.callCount(reportInterpretersChangedStub, envs.length);
173170
});
174171

175172
test('triggerRefresh() refreshes the collection and storage with any new environments', async () => {
@@ -204,7 +201,6 @@ suite('Python envs locator - Environments Collection', async () => {
204201
assertEnvsEqual(storage, expected);
205202

206203
const eventData = [
207-
{ path: undefined, type: 'clear-all' },
208204
{
209205
path: path.join(TEST_LAYOUT_ROOT, 'doesNotExist'),
210206
type: 'remove',
@@ -307,7 +303,6 @@ suite('Python envs locator - Environments Collection', async () => {
307303
assertEnvsEqual(envs, expected);
308304

309305
const eventData = [
310-
{ path: undefined, type: 'clear-all' },
311306
{
312307
path: path.join(TEST_LAYOUT_ROOT, 'doesNotExist'),
313308
type: 'remove',
@@ -404,7 +399,6 @@ suite('Python envs locator - Environments Collection', async () => {
404399
);
405400

406401
const eventData = [
407-
{ path: undefined, type: 'clear-all' },
408402
{
409403
path: path.join(TEST_LAYOUT_ROOT, 'doesNotExist'),
410404
type: 'remove',
@@ -447,7 +441,6 @@ suite('Python envs locator - Environments Collection', async () => {
447441
expect(isFired).to.equal(true);
448442

449443
const eventData = [
450-
{ path: undefined, type: 'clear-all' },
451444
{
452445
path: path.join(TEST_LAYOUT_ROOT, 'conda1', 'python.exe'),
453446
type: 'add',
@@ -614,12 +607,6 @@ suite('Python envs locator - Environments Collection', async () => {
614607
downstreamEvents.sort((a, b) => (a.type && b.type ? a.type?.localeCompare(b.type) : 0)),
615608
);
616609

617-
[
618-
{ path: undefined, type: 'clear-all' },
619-
{ path: undefined, type: 'clear-all' },
620-
].forEach((d) => {
621-
sinon.assert.calledWithExactly(reportInterpretersChangedStub, [d]);
622-
});
623-
sinon.assert.calledTwice(reportInterpretersChangedStub);
610+
sinon.assert.notCalled(reportInterpretersChangedStub);
624611
});
625612
});

0 commit comments

Comments
 (0)