Skip to content

Commit cda8b00

Browse files
authored
fix: avoid generating multiple events for the same environment (#277)
1 parent cb4d48e commit cda8b00

File tree

3 files changed

+68
-40
lines changed

3 files changed

+68
-40
lines changed

src/features/envManagers.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,10 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
283283
}
284284
}
285285

286-
const oldEnv = this._previousEnvironments.get(project?.uri.toString() ?? 'global');
286+
const key = project ? project.uri.toString() : 'global';
287+
const oldEnv = this._previousEnvironments.get(key);
287288
if (oldEnv?.envId.id !== environment?.envId.id) {
288-
this._previousEnvironments.set(project?.uri.toString() ?? 'global', environment);
289+
this._previousEnvironments.set(key, environment);
289290
setImmediate(() =>
290291
this._onDidChangeEnvironmentFiltered.fire({ uri: project?.uri, new: environment, old: oldEnv }),
291292
);
@@ -320,9 +321,10 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
320321
}
321322

322323
const project = this.pm.get(uri);
323-
const oldEnv = this._previousEnvironments.get(project?.uri.toString() ?? 'global');
324+
const key = project ? project.uri.toString() : 'global';
325+
const oldEnv = this._previousEnvironments.get(key);
324326
if (oldEnv?.envId.id !== environment?.envId.id) {
325-
this._previousEnvironments.set(project?.uri.toString() ?? 'global', environment);
327+
this._previousEnvironments.set(key, environment);
326328
events.push({ uri: project?.uri, new: environment, old: oldEnv });
327329
}
328330
});
@@ -361,9 +363,10 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
361363
// Always get the new first, then compare with the old. This has minor impact on the ordering of
362364
// events. But it ensures that we always get the latest environment at the time of this call.
363365
const newEnv = await manager.get(uri);
364-
const oldEnv = this._previousEnvironments.get(project?.uri.toString() ?? 'global');
366+
const key = project ? project.uri.toString() : 'global';
367+
const oldEnv = this._previousEnvironments.get(key);
365368
if (oldEnv?.envId.id !== newEnv?.envId.id) {
366-
this._previousEnvironments.set(project?.uri.toString() ?? 'global', newEnv);
369+
this._previousEnvironments.set(key, newEnv);
367370
events.push({ uri: project?.uri, new: newEnv, old: oldEnv });
368371
}
369372
};
@@ -404,9 +407,10 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
404407
// Always get the new first, then compare with the old. This has minor impact on the ordering of
405408
// events. But it ensures that we always get the latest environment at the time of this call.
406409
const newEnv = await manager.get(scope);
407-
const oldEnv = this._previousEnvironments.get(project?.uri.toString() ?? 'global');
410+
const key = project ? project.uri.toString() : 'global';
411+
const oldEnv = this._previousEnvironments.get(key);
408412
if (oldEnv?.envId.id !== newEnv?.envId.id) {
409-
this._previousEnvironments.set(project?.uri.toString() ?? 'global', newEnv);
413+
this._previousEnvironments.set(key, newEnv);
410414
setImmediate(() =>
411415
this._onDidChangeEnvironmentFiltered.fire({ uri: project?.uri, new: newEnv, old: oldEnv }),
412416
);

src/managers/builtin/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function registerSystemPythonFeatures(
2727
);
2828

2929
const venvDebouncedRefresh = createSimpleDebounce(500, () => {
30-
venvManager.refresh(undefined);
30+
venvManager.watcherRefresh();
3131
});
3232
const watcher = createFileSystemWatcher('{**/pyenv.cfg,**/bin/python,**/python.exe}', false, true, false);
3333
disposables.push(

src/managers/builtin/venvManager.ts

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export class VenvManager implements EnvironmentManager {
4040
private collection: PythonEnvironment[] = [];
4141
private readonly fsPathToEnv: Map<string, PythonEnvironment> = new Map();
4242
private globalEnv: PythonEnvironment | undefined;
43+
private skipWatcherRefresh = false;
4344

4445
private readonly _onDidChangeEnvironment = new EventEmitter<DidChangeEnvironmentEventArgs>();
4546
public readonly onDidChangeEnvironment = this._onDidChangeEnvironment.event;
@@ -86,44 +87,55 @@ export class VenvManager implements EnvironmentManager {
8687
}
8788

8889
async create(scope: CreateEnvironmentScope): Promise<PythonEnvironment | undefined> {
89-
let isGlobal = scope === 'global';
90-
if (Array.isArray(scope) && scope.length > 1) {
91-
isGlobal = true;
92-
}
93-
let uri: Uri | undefined = undefined;
94-
if (isGlobal) {
95-
uri = await getGlobalVenvLocation();
96-
} else {
97-
uri = scope instanceof Uri ? scope : (scope as Uri[])[0];
98-
}
90+
try {
91+
this.skipWatcherRefresh = true;
92+
let isGlobal = scope === 'global';
93+
if (Array.isArray(scope) && scope.length > 1) {
94+
isGlobal = true;
95+
}
96+
let uri: Uri | undefined = undefined;
97+
if (isGlobal) {
98+
uri = await getGlobalVenvLocation();
99+
} else {
100+
uri = scope instanceof Uri ? scope : (scope as Uri[])[0];
101+
}
99102

100-
if (!uri) {
101-
return;
102-
}
103+
if (!uri) {
104+
return;
105+
}
103106

104-
const venvRoot: Uri = uri;
105-
const globals = await this.baseManager.getEnvironments('global');
106-
const environment = await createPythonVenv(this.nativeFinder, this.api, this.log, this, globals, venvRoot);
107-
if (environment) {
108-
this.addEnvironment(environment, true);
107+
const venvRoot: Uri = uri;
108+
const globals = await this.baseManager.getEnvironments('global');
109+
const environment = await createPythonVenv(this.nativeFinder, this.api, this.log, this, globals, venvRoot);
110+
if (environment) {
111+
this.addEnvironment(environment, true);
112+
}
113+
return environment;
114+
} finally {
115+
this.skipWatcherRefresh = false;
109116
}
110-
return environment;
111117
}
112118

113119
async remove(environment: PythonEnvironment): Promise<void> {
114-
await removeVenv(environment, this.log);
115-
this.updateCollection(environment);
116-
this._onDidChangeEnvironments.fire([{ environment, kind: EnvironmentChangeKind.remove }]);
120+
try {
121+
this.skipWatcherRefresh = true;
117122

118-
const changedUris = this.updateFsPathToEnv(environment);
123+
await removeVenv(environment, this.log);
124+
this.updateCollection(environment);
125+
this._onDidChangeEnvironments.fire([{ environment, kind: EnvironmentChangeKind.remove }]);
119126

120-
for (const uri of changedUris) {
121-
const newEnv = await this.get(uri);
122-
this._onDidChangeEnvironment.fire({ uri, old: environment, new: newEnv });
123-
}
127+
const changedUris = this.updateFsPathToEnv(environment);
128+
129+
for (const uri of changedUris) {
130+
const newEnv = await this.get(uri);
131+
this._onDidChangeEnvironment.fire({ uri, old: environment, new: newEnv });
132+
}
124133

125-
if (this.globalEnv?.envId.id === environment.envId.id) {
126-
await this.set(undefined, undefined);
134+
if (this.globalEnv?.envId.id === environment.envId.id) {
135+
await this.set(undefined, undefined);
136+
}
137+
} finally {
138+
this.skipWatcherRefresh = false;
127139
}
128140
}
129141

@@ -148,10 +160,22 @@ export class VenvManager implements EnvironmentManager {
148160
return this.internalRefresh(scope, true, VenvManagerStrings.venvRefreshing);
149161
}
150162

151-
private async internalRefresh(scope: RefreshEnvironmentsScope, hardRefresh: boolean, title: string): Promise<void> {
163+
async watcherRefresh(): Promise<void> {
164+
if (this.skipWatcherRefresh) {
165+
return;
166+
}
167+
return this.internalRefresh(undefined, false, VenvManagerStrings.venvRefreshing);
168+
}
169+
170+
private async internalRefresh(
171+
scope: RefreshEnvironmentsScope,
172+
hardRefresh: boolean,
173+
title: string,
174+
location: ProgressLocation = ProgressLocation.Window,
175+
): Promise<void> {
152176
await withProgress(
153177
{
154-
location: ProgressLocation.Window,
178+
location,
155179
title,
156180
},
157181
async () => {

0 commit comments

Comments
 (0)