Summary
The public PythonEnvironmentApi.onDidChangePythonProjects event never fires. API consumers that subscribe to it to react to projects being added/removed at runtime never receive a notification. The internal project list is updated correctly (so a consumer that re-queries getPythonProjects() later — e.g. after a restart — does see the change), but no live event is emitted.
Where
src/features/pythonApi.ts — PythonEnvironmentApiImpl:
The emitter is declared and exposed, but _onDidChangePythonProjects.fire(...) is never called anywhere in the class:
private readonly _onDidChangePythonProjects = new EventEmitter<DidChangePythonProjectsEventArgs>();
// ...
onDidChangePythonProjects: Event<DidChangePythonProjectsEventArgs> = this._onDidChangePythonProjects.event;
The constructor only forwards environment events — it pushes the emitter onto disposables (so it gets disposed) and subscribes to envManagers.onDidChangeActiveEnvironment → _onDidChangeEnvironment and envVarManager.onDidChangeEnvironmentVariables → _onDidChangeEnvironmentVariables. There is no subscription to projectManager.onDidChangeProjects.
Meanwhile the project manager does track and broadcast project changes internally (src/features/projectManager.ts, PythonProjectManagerImpl):
add(), remove(), updateProjects(), and loadProjects() all call this._onDidChangeProjects.fire(...).
- It exposes
public readonly onDidChangeProjects = this._onDidChangeProjects.event;.
And the API's addPythonProject() / removePythonProject() delegate to projectManager.add/remove, which updates the internal map and fires the internal onDidChangeProjects — but the public onDidChangePythonProjects is never fired.
Impact
Any API consumer relying on onDidChangePythonProjects to stay in sync with the active project set silently misses runtime changes (e.g. a new per-folder environment/project added via the UI). Workarounds require a full re-query or a restart of the consumer.
Concretely, this affects Pylance's per-folder interpreter support: when a user adds an environment/project for a subfolder, Pylance doesn't pick up the new (virtual) workspace folder until it is restarted, because Pylance subscribes to onDidChangePythonProjects and the event never fires.
Steps to reproduce
- Have an extension acquire the Python Environments API and subscribe to
onDidChangePythonProjects.
- Add a project/environment for a folder at runtime (UI or
addPythonProject).
- Observe:
getPythonProjects() now includes the new project, but the onDidChangePythonProjects callback never fired.
Expected
onDidChangePythonProjects should fire whenever the set of python projects changes (added/removed), consistent with its documented contract ("Event raised when python projects are added or removed").
Suggested fix
Forward the project manager's change event to the public API emitter in the PythonEnvironmentApiImpl constructor, e.g.:
this.projectManager.onDidChangeProjects((/* projects */) => {
this._onDidChangePythonProjects.fire(/* DidChangePythonProjectsEventArgs: added / removed */);
});
The project manager currently fires the full project array, so producing the added/removed shape of DidChangePythonProjectsEventArgs will require either tracking the previous set in the API layer, or updating the manager to emit the delta.
Environment
- Repo:
microsoft/vscode-python-environments (observed on main)
- Relevant files:
src/features/pythonApi.ts, src/features/projectManager.ts
Summary
The public
PythonEnvironmentApi.onDidChangePythonProjectsevent never fires. API consumers that subscribe to it to react to projects being added/removed at runtime never receive a notification. The internal project list is updated correctly (so a consumer that re-queriesgetPythonProjects()later — e.g. after a restart — does see the change), but no live event is emitted.Where
src/features/pythonApi.ts—PythonEnvironmentApiImpl:The emitter is declared and exposed, but
_onDidChangePythonProjects.fire(...)is never called anywhere in the class:The constructor only forwards environment events — it pushes the emitter onto
disposables(so it gets disposed) and subscribes toenvManagers.onDidChangeActiveEnvironment→_onDidChangeEnvironmentandenvVarManager.onDidChangeEnvironmentVariables→_onDidChangeEnvironmentVariables. There is no subscription toprojectManager.onDidChangeProjects.Meanwhile the project manager does track and broadcast project changes internally (
src/features/projectManager.ts,PythonProjectManagerImpl):add(),remove(),updateProjects(), andloadProjects()all callthis._onDidChangeProjects.fire(...).public readonly onDidChangeProjects = this._onDidChangeProjects.event;.And the API's
addPythonProject()/removePythonProject()delegate toprojectManager.add/remove, which updates the internal map and fires the internalonDidChangeProjects— but the publiconDidChangePythonProjectsis never fired.Impact
Any API consumer relying on
onDidChangePythonProjectsto stay in sync with the active project set silently misses runtime changes (e.g. a new per-folder environment/project added via the UI). Workarounds require a full re-query or a restart of the consumer.Concretely, this affects Pylance's per-folder interpreter support: when a user adds an environment/project for a subfolder, Pylance doesn't pick up the new (virtual) workspace folder until it is restarted, because Pylance subscribes to
onDidChangePythonProjectsand the event never fires.Steps to reproduce
onDidChangePythonProjects.addPythonProject).getPythonProjects()now includes the new project, but theonDidChangePythonProjectscallback never fired.Expected
onDidChangePythonProjectsshould fire whenever the set of python projects changes (added/removed), consistent with its documented contract ("Event raised when python projects are added or removed").Suggested fix
Forward the project manager's change event to the public API emitter in the
PythonEnvironmentApiImplconstructor, e.g.:The project manager currently fires the full project array, so producing the
added/removedshape ofDidChangePythonProjectsEventArgswill require either tracking the previous set in the API layer, or updating the manager to emit the delta.Environment
microsoft/vscode-python-environments(observed onmain)src/features/pythonApi.ts,src/features/projectManager.ts