Skip to content

Commit ba6ac95

Browse files
author
Kartik Raj
committed
Change resolveEnvironment API to invalidate cache for conda envs without python
1 parent 1668d06 commit ba6ac95

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

src/client/interpreter/interpreterService.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ProgressLocation,
1010
ProgressOptions,
1111
Uri,
12+
WorkspaceFolder,
1213
} from 'vscode';
1314
import '../common/extensions';
1415
import { IApplicationShell, IDocumentManager, IWorkspaceService } from '../common/application/types';
@@ -96,7 +97,13 @@ export class InterpreterService implements Disposable, IInterpreterService {
9697
public async refresh(resource?: Uri): Promise<void> {
9798
const interpreterDisplay = this.serviceContainer.get<IInterpreterDisplay>(IInterpreterDisplay);
9899
await interpreterDisplay.refresh(resource);
99-
this.ensureEnvironmentContainsPython(this.configService.getSettings(resource).pythonPath).ignoreErrors();
100+
const workspaceFolder = this.serviceContainer
101+
.get<IWorkspaceService>(IWorkspaceService)
102+
.getWorkspaceFolder(resource);
103+
this.ensureEnvironmentContainsPython(
104+
this.configService.getSettings(resource).pythonPath,
105+
workspaceFolder,
106+
).ignoreErrors();
100107
}
101108

102109
public initialize(): void {
@@ -227,18 +234,21 @@ export class InterpreterService implements Disposable, IInterpreterService {
227234
if (this._pythonPathSetting === '' || this._pythonPathSetting !== pySettings.pythonPath) {
228235
this._pythonPathSetting = pySettings.pythonPath;
229236
this.didChangeInterpreterEmitter.fire(resource);
237+
const workspaceFolder = this.serviceContainer
238+
.get<IWorkspaceService>(IWorkspaceService)
239+
.getWorkspaceFolder(resource);
230240
reportActiveInterpreterChanged({
231241
path: pySettings.pythonPath,
232-
resource: this.serviceContainer.get<IWorkspaceService>(IWorkspaceService).getWorkspaceFolder(resource),
242+
resource: workspaceFolder,
233243
});
234244
const interpreterDisplay = this.serviceContainer.get<IInterpreterDisplay>(IInterpreterDisplay);
235245
interpreterDisplay.refresh().catch((ex) => traceError('Python Extension: display.refresh', ex));
236-
await this.ensureEnvironmentContainsPython(this._pythonPathSetting);
246+
await this.ensureEnvironmentContainsPython(this._pythonPathSetting, workspaceFolder);
237247
}
238248
}
239249

240250
@cache(-1, true)
241-
private async ensureEnvironmentContainsPython(pythonPath: string) {
251+
private async ensureEnvironmentContainsPython(pythonPath: string, workspaceFolder: WorkspaceFolder | undefined) {
242252
const installer = this.serviceContainer.get<IInstaller>(IInstaller);
243253
if (!(await installer.isInstalled(Product.python))) {
244254
// If Python is not installed into the environment, install it.
@@ -251,7 +261,17 @@ export class InterpreterService implements Disposable, IInterpreterService {
251261
traceLog('Conda envs without Python are known to not work well; fixing conda environment...');
252262
const promise = installer.install(Product.python, await this.getInterpreterDetails(pythonPath));
253263
shell.withProgress(progressOptions, () => promise);
254-
promise.then(() => this.triggerRefresh().ignoreErrors());
264+
promise
265+
.then(async () => {
266+
// Fetch interpreter details so the cache is updated to include the newly installed Python.
267+
await this.getInterpreterDetails(pythonPath);
268+
this.didChangeInterpreterEmitter.fire(workspaceFolder?.uri);
269+
reportActiveInterpreterChanged({
270+
path: pythonPath,
271+
resource: workspaceFolder,
272+
});
273+
})
274+
.ignoreErrors();
255275
}
256276
}
257277
}

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import { Event } from 'vscode';
55
import { isTestExecution } from '../../../../common/constants';
66
import { traceInfo, traceVerbose } from '../../../../logging';
77
import { arePathsSame, getFileInfo, pathExists } from '../../../common/externalDependencies';
8-
import { PythonEnvInfo } from '../../info';
8+
import { PythonEnvInfo, PythonEnvKind } from '../../info';
99
import { areEnvsDeepEqual, areSameEnv, getEnvPath } from '../../info/env';
1010
import {
1111
BasicPythonEnvCollectionChangedEvent,
1212
PythonEnvCollectionChangedEvent,
1313
PythonEnvsWatcher,
1414
} from '../../watcher';
15+
import { getCondaInterpreterPath } from '../../../common/environmentManagers/conda';
1516

1617
export interface IEnvsCollectionCache {
1718
/**
@@ -146,15 +147,21 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher<PythonEnvCollectionCha
146147

147148
public addEnv(env: PythonEnvInfo, hasLatestInfo?: boolean): void {
148149
const found = this.envs.find((e) => areSameEnv(e, env));
150+
if (!found) {
151+
this.envs.push(env);
152+
this.fire({ new: env });
153+
} else if (hasLatestInfo) {
154+
const isValidated = this.validatedEnvs.has(env.id!);
155+
if (!isValidated) {
156+
// Update cache only if we have latest info and the env is not already validated.
157+
this.updateEnv(found, env, true);
158+
}
159+
}
149160
if (hasLatestInfo) {
150161
traceVerbose(`Flushing env to cache ${env.id}`);
151162
this.validatedEnvs.add(env.id!);
152163
this.flush(env).ignoreErrors(); // If we have latest info, flush it so it can be saved.
153164
}
154-
if (!found) {
155-
this.envs.push(env);
156-
this.fire({ new: env });
157-
}
158165
}
159166

160167
public updateEnv(oldValue: PythonEnvInfo, newValue: PythonEnvInfo | undefined, forceUpdate = false): void {
@@ -177,6 +184,17 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher<PythonEnvCollectionCha
177184
public async getLatestInfo(path: string): Promise<PythonEnvInfo | undefined> {
178185
// `path` can either be path to environment or executable path
179186
const env = this.envs.find((e) => arePathsSame(e.location, path)) ?? this.envs.find((e) => areSameEnv(e, path));
187+
if (
188+
env?.kind === PythonEnvKind.Conda &&
189+
getEnvPath(env.executable.filename, env.location).pathType === 'envFolderPath'
190+
) {
191+
if (await pathExists(getCondaInterpreterPath(env.location))) {
192+
// This is a conda env without python in cache which actually now has a valid python, so return
193+
// `undefined` and delete value from cache as cached value is not the latest anymore.
194+
this.validatedEnvs.delete(env.id!);
195+
return undefined;
196+
}
197+
}
180198
if (env) {
181199
if (this.validatedEnvs.has(env.id!)) {
182200
traceVerbose(`Found cached env for ${path}`);

0 commit comments

Comments
 (0)