Commit ccd8daf
authored
Part of
microsoft#1454
## Bug
`CondaEnvManager.set()` only fires `_onDidChangeEnvironment` in the
`Uri[]` (multi-project) branch. The `scope === undefined` (global) and
`scope instanceof Uri` (single project) branches persist the selection
and update internal maps, but never fire the change event.
The `venvManager.ts` correctly fires the event in all three branches
(lines 413, 444, 477), so this is an inconsistency specific to the conda
manager.
## Why it's a bug
There are code paths that call `manager.set()` **directly**, bypassing
the orchestrator's `setEnvironment()`:
1. **`envCommands.ts:220`** — After creating a conda environment in the
"global" (no workspace) context, calls `manager.set(undefined, env)`
directly.
2. **`extension.ts:344`** — When removing a project, calls
`manager.set(uri, undefined)` directly.
3. **`envManagers.ts:404` and `:434`** — Batch operations that call
`manager.set()` directly for individual items.
When these code paths run, the orchestrator's `setEnvironment()` is
never involved, so it never fires its own
`_onDidChangeEnvironmentFiltered` event. The **only** way listeners can
be notified is through the manager-level `_onDidChangeEnvironment` —
which conda doesn't fire.
### Event chain that breaks
```
manager.set(undefined, env) // called directly, not through orchestrator
→ conda persists to disk ✅
→ conda updates in-memory state ✅
→ conda fires _onDidChangeEnvironment ❌ (BUG)
envManagers._onDidChangeEnvironment // relayed from manager event → never fires
→ extension.ts:511 updateViewsAndStatus ❌
→ projectView.ts:62 tree refresh ❌
pythonApi._onDidChangeEnvironment // driven by _onDidChangeEnvironmentFiltered → never fires
→ shellStartupActivationVariablesManager ❌ (terminal activation not updated)
→ 3rd party extensions ❌
```
### What the orchestrator masks
When the user selects an environment through the normal UI picker, the
orchestrator's `setEnvironment()` calls `manager.set()` and then fires
`_onDidChangeEnvironmentFiltered` independently. This masks the missing
manager event for that specific flow. But the direct-call paths above
are not masked.
## Repro steps
**Primary repro (global create flow):**
1. Open VS Code with **no workspace folder open**.
2. Run "Python: Create Environment" from the command palette.
3. Select Conda, choose a name and Python version.
4. The environment is created successfully and `manager.set(undefined,
env)` is called at `envCommands.ts:220`.
5. **Bug:** The status bar still shows the old/no environment. The
project view doesn't update. Terminal activation doesn't change. The UI
appears frozen even though the environment was created and set
internally.
**Secondary repro (project removal):**
1. Open a multi-root workspace with a Python project using a conda
environment.
2. Remove the project from the workspace.
3. `manager.set(uri, undefined)` is called at `extension.ts:344` to
clear the environment.
4. **Bug:** Listeners don't know the environment was cleared — stale
state remains in views and terminal activation.
## Fix
1. **Global scope (`scope === undefined`)**: Capture the "before" state,
update `this.globalEnv`, persist, then fire `_onDidChangeEnvironment` if
the environment actually changed.
2. **Single Uri scope (`scope instanceof Uri`)**: Capture the "before"
state from the map before updating, then fire `_onDidChangeEnvironment`
if the environment actually changed.
Both branches now follow the same pattern as the `Uri[]` branch and the
`venvManager.ts` implementation.
Before:
https://github.com/user-attachments/assets/5ec01adc-caeb-4db6-9620-deb0662b92f8
After:
https://github.com/user-attachments/assets/08baeceb-e9b7-45d4-9e5c-83792641fda6
## Why this fix is correct
- Events are only fired when the environment actually changes
(`before?.envId.id !== checkedEnv?.envId.id`), preventing spurious
notifications.
- The in-memory `globalEnv` update ensures `get(undefined)` returns the
correct value immediately after `set()`.
- No change to the `Uri[]` branch, which was already working correctly.
- The change is purely additive — existing behavior is preserved,
missing behavior is added.
- For the normal picker flow (through the orchestrator), the manager
event is now fired in addition to the orchestrator's event. This is
consistent with venvManager and harmless — listeners that receive both
just get a redundant but correct notification.
## Tests added
- `condaEnvManager.setEvents.unit.test.ts`: 5 test cases covering:
- Global scope fires event
- Global scope does not fire event when unchanged
- Single Uri scope fires event
- Single Uri scope does not fire event when unchanged
- Clearing an environment (set to undefined) fires event
1 parent 6ec9f33 commit ccd8daf
2 files changed
Lines changed: 158 additions & 0 deletions
File tree
- src
- managers/conda
- test/managers/conda
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| 314 | + | |
| 315 | + | |
314 | 316 | | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
315 | 320 | | |
316 | 321 | | |
317 | 322 | | |
| |||
327 | 332 | | |
328 | 333 | | |
329 | 334 | | |
| 335 | + | |
330 | 336 | | |
331 | 337 | | |
332 | 338 | | |
333 | 339 | | |
334 | 340 | | |
335 | 341 | | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
336 | 345 | | |
337 | 346 | | |
338 | 347 | | |
| |||
Lines changed: 149 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
0 commit comments