You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
overhaul interpreter selection prioritization code to align with desired UX (#1155)
## Summary
Implements a robust priority chain for interpreter selection that
respects user-configured settings, fixes multi-root workspace issues,
and prevents unwanted settings.json modifications on startup.
## Changes
New Priority Chain (in order):
1. `pythonProjects[] `- Project-specific settings (highest priority)
2. `defaultEnvManager` - User-configured only (not fallback values)
3. `python.defaultInterpreterPath `- Legacy setting support
4. Auto-discovery - Local venv → System Python (lowest priority)
### Key Fixes:
- Settings now take priority over cached environments
- `python.defaultInterpreterPath` is now respected when no explicit
`defaultEnvManager` is configured
- No automatic `settings.json` writes on workspace open (only on
explicit user actions)
- User notification when configured settings can't be applied (with
"Open Settings" action)
### How Cache Fits In
The cache stores previously resolved environments to avoid re-running
discovery on every request.
**Important: User-configured settings always take priority over cache.
The cache is only used as a fallback when:**
No user explicitly configured any of the above settings, AND
An environment was previously resolved for that scope
On workspace open, the full priority chain runs fresh for each folder.
Cache is populated but not written to settings.json unless the user
explicitly selects an interpreter.
Fixes#1145Fixes#833Fixes#1124
### Testing
29 unit tests covering priority chain, config change listener,
multi-root workspaces, and caching behavio
- Avoid showing the same error message multiple times in a session; track state with a module-level variable.
28
+
- Use clear, actionable error messages and offer relevant buttons (e.g., "Open settings", "Close").
29
29
30
30
## Documentation
31
31
32
-
- Add clear docstrings to public functions, describing their purpose, parameters, and behavior.
32
+
- Add clear docstrings to public functions, describing their purpose, parameters, and behavior.
33
+
34
+
## Cross-Platform Path Handling
35
+
36
+
**CRITICAL**: This extension runs on Windows, macOS, and Linux. NEVER hardcode POSIX-style paths.
37
+
38
+
- Use `path.join()` or `path.resolve()` instead of string concatenation with `/`
39
+
- Use `Uri.file(path).fsPath` when comparing paths (Windows uses `\`, POSIX uses `/`)
40
+
- When asserting path equality, compare `fsPath` to `fsPath`, not raw strings
41
+
42
+
## Learnings
43
+
44
+
- When using `getConfiguration().inspect()`, always pass a scope/Uri to `getConfiguration(section, scope)` — otherwise `workspaceFolderValue` will be `undefined` because VS Code doesn't know which folder to inspect (1)
45
+
-**path.normalize() vs path.resolve()**: On Windows, `path.normalize('\test')` keeps it as `\test`, but `path.resolve('\test')` adds the current drive → `C:\test`. When comparing paths, use `path.resolve()` on BOTH sides or they won't match (2)
- 🔸 **Data validation** - invalid inputs, type mismatches
312
329
313
330
#### Real-World Scenarios
314
331
315
-
-✅ **Fresh install** - clean slate
316
-
-✅ **Existing user** - migration scenarios
317
-
-✅ **Power user** - complex configurations
318
-
-🔸 **Error recovery** - graceful degradation
332
+
- ✅ **Fresh install** - clean slate
333
+
- ✅ **Existing user** - migration scenarios
334
+
- ✅ **Power user** - complex configurations
335
+
- 🔸 **Error recovery** - graceful degradation
319
336
320
337
### Example Test Plan Structure
321
338
@@ -324,30 +341,30 @@ function generateTestScenarios(analysis: FunctionAnalysis): TestScenario[] {
324
341
325
342
### 1. Configuration Migration Tests
326
343
327
-
-No legacy settings exist
328
-
-Legacy settings already migrated
329
-
-Fresh migration needed
330
-
-Partial migration required
331
-
-Migration failures
344
+
- No legacy settings exist
345
+
- Legacy settings already migrated
346
+
- Fresh migration needed
347
+
- Partial migration required
348
+
- Migration failures
332
349
333
350
### 2. Configuration Source Tests
334
351
335
-
-Global search paths
336
-
-Workspace search paths
337
-
-Settings precedence
338
-
-Configuration errors
352
+
- Global search paths
353
+
- Workspace search paths
354
+
- Settings precedence
355
+
- Configuration errors
339
356
340
357
### 3. Path Resolution Tests
341
358
342
-
-Absolute vs relative paths
343
-
-Workspace folder resolution
344
-
-Path validation and filtering
359
+
- Absolute vs relative paths
360
+
- Workspace folder resolution
361
+
- Path validation and filtering
345
362
346
363
### 4. Integration Scenarios
347
364
348
-
-Combined configurations
349
-
-Deduplication logic
350
-
-Error handling flows
365
+
- Combined configurations
366
+
- Deduplication logic
367
+
- Error handling flows
351
368
```
352
369
353
370
## 🔧 Step 4: Set Up Your Test Infrastructure
@@ -514,47 +531,47 @@ envConfig.inspect
514
531
515
532
### Configuration Tests
516
533
517
-
-Test different setting combinations
518
-
-Test setting precedence (workspace > user > default)
519
-
-Test configuration errors and recovery
520
-
-Always use dynamic path construction with Node.js `path` module when testing functions that resolve paths against workspace folders to ensure cross-platform compatibility
534
+
- Test different setting combinations
535
+
- Test setting precedence (workspace > user > default)
536
+
- Test configuration errors and recovery
537
+
- Always use dynamic path construction with Node.js `path` module when testing functions that resolve paths against workspace folders to ensure cross-platform compatibility
-[ ]**Fast execution** - tests run quickly with proper mocking
550
567
551
568
### Common Anti-Patterns to Avoid
552
569
553
-
-❌ Testing implementation details instead of behavior
554
-
-❌ Brittle assertions that break on cosmetic changes
555
-
-❌ Order-dependent tests that fail due to processing changes
556
-
-❌ Tests that don't clean up mocks properly
557
-
-❌ Overly complex test setup that's hard to understand
570
+
- ❌ Testing implementation details instead of behavior
571
+
- ❌ Brittle assertions that break on cosmetic changes
572
+
- ❌ Order-dependent tests that fail due to processing changes
573
+
- ❌ Tests that don't clean up mocks properly
574
+
- ❌ Overly complex test setup that's hard to understand
558
575
559
576
## 🔄 Reviewing and Improving Existing Tests
560
577
@@ -567,13 +584,17 @@ envConfig.inspect
567
584
568
585
### Common Fixes
569
586
570
-
-Over-complex mocks → Minimal mocks with only needed methods
571
-
-Brittle assertions → Behavior-focused with error messages
572
-
-Vague test names → Clear scenario descriptions (transform "should return X when Y" into "should [expected behavior] when [scenario context]")
573
-
-Missing structure → Mock → Run → Assert pattern
574
-
-Untestable Node.js APIs → Create proxy abstraction functions (use function overloads to preserve intelligent typing while making functions mockable)
587
+
- Over-complex mocks → Minimal mocks with only needed methods
588
+
- Brittle assertions → Behavior-focused with error messages
589
+
- Vague test names → Clear scenario descriptions (transform "should return X when Y" into "should [expected behavior] when [scenario context]")
590
+
- Missing structure → Mock → Run → Assert pattern
591
+
- Untestable Node.js APIs → Create proxy abstraction functions (use function overloads to preserve intelligent typing while making functions mockable)
575
592
576
593
## 🧠 Agent Learnings
577
-
- Avoid testing exact error messages or log output - assert only that errors are thrown or rejection occurs to prevent brittle tests (1)
578
-
- Create shared mock helpers (e.g., `createMockLogOutputChannel()`) instead of duplicating mock setup across multiple test files (1)
579
594
595
+
- Avoid testing exact error messages or log output - assert only that errors are thrown or rejection occurs to prevent brittle tests (1)
596
+
- Create shared mock helpers (e.g., `createMockLogOutputChannel()`) instead of duplicating mock setup across multiple test files (1)
597
+
- Always compile tests (`npm run compile-tests`) before running them after adding new test cases - test counts will be wrong if running against stale compiled output (1)
598
+
- Never create "documentation tests" that just `assert.ok(true)` — if mocking limitations prevent testing, either test a different layer that IS mockable, or skip the test entirely with a clear explanation (1)
599
+
-**REPEATED**: When stubbing vscode APIs in tests via wrapper modules (e.g., `workspaceApis`), the production code must also use those wrappers — sinon cannot stub properties directly on the vscode namespace like `workspace.workspaceFolders`, so both production and test code must reference the same stubbable wrapper functions (3)
600
+
-**REPEATED**: Use OS-agnostic path handling in tests: use `'.'` for relative paths in configs (NOT `/test/workspace`), compare `fsPath` to `Uri.file(expected).fsPath` (NOT raw strings). This breaks on Windows every time! (5)
0 commit comments