Skip to content

fix: stop resolve() from leaking foreign envs (e.g. hatch) into the venv collection#1507

Open
StellaHuang95 wants to merge 1 commit intomicrosoft:mainfrom
StellaHuang95:hatch
Open

fix: stop resolve() from leaking foreign envs (e.g. hatch) into the venv collection#1507
StellaHuang95 wants to merge 1 commit intomicrosoft:mainfrom
StellaHuang95:hatch

Conversation

@StellaHuang95
Copy link
Copy Markdown
Contributor

Context

@flying-sheep reported 3 related bugs, #1471, #1485 and #1491

The venvs ones both trace to the same root cause in VenvManager.resolve(). Hatch envs structurally look like venvs (they have a pyvenv.cfg), so PET classifies them as Venv and they pass through resolveVenvPythonEnvironmentPath. Until now, every successful resolve() call also mutated this.collection via addEnvironment(resolved, true). So whenever anything called resolve() for a hatch path — Python: Select Interpreter, Pylance startup, a test runner asking for execInfo, another extension querying the env — the hatch env got persisted under venv too.

The original side effect dates back to commit 9363bc1 (Oct 2024), when the extension only had system and venv managers and the author assumed any successful resolve() was a newly discovered venv worth caching. That assumption stopped being true once the API supported third-party managers.

What this PR does

One-line deletion in src/managers/builtin/venvManager.ts (plus a small whitespace touch-up):

 if (resolved) {
     if (resolved.envId.managerId === `${PYTHON_EXTENSION_ID}:venv`) {
-        // This is just like finding a new environment or creating a new one.
-        // Add it to collection, and trigger the added event.
-        this.addEnvironment(resolved, true);
-
         // We should only return the resolved env if it is a venv.
         return resolved;
     }
 }
 return undefined;

resolve() is now a pure query: "given a path, are you the manager for it?" It still returns the resolved env (every consumer of resolve() keeps working), it just stops mutating state.

What this PR does not fix (follow-ups)

Three layers of bug were identified; this PR ships Layer 1 only.

  • Layer 1 (this PR): resolve() side-effect leaks foreign envs into venv. Fixed.
  • Layer 2 — PET cannot tell hatch envs from regular venvs. PET's Venv kind is structural (it triggers on pyvenv.cfg alone), so cross-manager overlap is expected for any tool that produces pyvenv.cfg-shaped envs (hatch in path = ".venv" mode, tox, nox, custom scripts). Needs a PET-level fix; tracking issue to be filed upstream against microsoft/python-environment-tools.
  • Layer 3 — ruff and ty don't react to per-workspace env changes from this extension. Both subscribe only to api.environments.onDidChangeActiveEnvironmentPath (the legacy global-only event), not to our pythonEnvsApi.onDidChangeEnvironment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant