Skip to content

Lazy-register Conda manager#1600

Draft
Copilot wants to merge 3 commits into
mainfrom
copilot/lazy-register-conda-manager
Draft

Lazy-register Conda manager#1600
Copilot wants to merge 3 commits into
mainfrom
copilot/lazy-register-conda-manager

Conversation

Copilot AI commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Conda discovery is the dominant per-locator cost in PET on Windows and was paid on every refresh, including in sessions where the user never picks a conda env. Mirror the v1.28 lazy-registration pattern already applied to pipenv/poetry/pyenv: register unconditionally so the manager shows up in the picker, defer the actual discovery until first use.

Changes

  • src/managers/conda/main.tsregisterCondaFeatures no longer calls getConda(nativeFinder) or constructCondaSourcingStatus at activation. It unconditionally constructs and registers CondaEnvManager and CondaPackageManager. projectManager is forwarded into the env manager so it can notify on missing-default later.

  • src/managers/conda/condaEnvManager.tsinitialize() now performs the deferred work: a non-PET getConda() for toolSource = 'settings' | 'local', the existing refreshCondaEnvs(...) (which does the PET refresh), and a post-refresh getConda() to detect conda found via PET (toolSource = 'pet'). constructCondaSourcingStatus runs lazily here. Emits MANAGER_LAZY_INIT telemetry (result / envCount / toolSource / errorType) matching pipenv/poetry. Calls notifyMissingManagerIfDefault on tool_not_found (relocated from registerCondaFeatures). Constructor accepts an optional projectManager (last arg, matches pipenv/poetry; existing 3-arg test call sites unaffected).

  • docs/startup-flow.md — groups conda with pyenv/pipenv/poetry as unconditionally-registered, lazy-discovery managers.

Tests

Added 12 sinon-stubbed unit tests covering the registration flow and every failure path:

  • src/test/managers/conda/registerCondaFeatures.unit.test.ts — proves the unconditional-registration contract: env manager + package manager are always registered (4 disposables) and getConda / refreshCondaEnvs / constructCondaSourcingStatus / getCondaPathSetting are never called during activation. Registration still succeeds when conda is unavailable.
  • src/test/managers/conda/condaEnvManager.initialize.unit.test.ts — covers the lazy initialize() state machine: success paths for toolSource = local / settings / pet; tool_not_found with and without a projectManager (verifying notifyMissingManagerIfDefault is called exactly when expected); the error path (verifies initialize() never throws to its caller and emits errorType); graceful handling of constructCondaSourcingStatus failure; MANAGER_LAZY_INIT telemetry payload; idempotency under concurrent calls; and that constructing the manager does no discovery work.

Notes

Copilot AI changed the title [WIP] Implement lazy registration for Conda manager Lazy-register Conda manager Jun 21, 2026
Copilot AI requested a review from eleanorjboyd June 21, 2026 19:19
@eleanorjboyd

Copy link
Copy Markdown
Member

@copilot can you design a way to test this registration flow and the failure handling

Copilot AI commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

@copilot can you design a way to test this registration flow and the failure handling

Added two unit test files covering the registration flow and failure handling — sinon-stubbed, no VS Code host required, follow the patterns of the existing condaEnvManager.*.unit.test.ts suites.

src/test/managers/conda/registerCondaFeatures.unit.test.ts — proves the unconditional registration contract:

  • registers env manager + package manager (4 disposables) and resolves getPythonApi exactly once
  • asserts getConda, refreshCondaEnvs, constructCondaSourcingStatus, and getCondaPathSetting are never called during registerCondaFeatures (this is the regression guard against re-introducing eager discovery)
  • registration still succeeds when getConda would reject (i.e. conda is not installed)

src/test/managers/conda/condaEnvManager.initialize.unit.test.ts — covers the lazy initialize() state machine and every failure path:

case outcome
conda found locally result=success, toolSource=local, sourcing info constructed
conda from python.condaPath setting toolSource=settings
conda discovered by PET after refresh toolSource=pet (pre-refresh getConda throws, post-refresh resolves)
conda not found anywhere, with projectManager result=tool_not_found, notifyMissingManagerIfDefault('ms-python.python:conda', …) called once
conda not found, no projectManager tool_not_found but no notification (guards against the optional-arg path)
refreshCondaEnvs throws result=error, errorType populated by classifyError, never rethrows
constructCondaSourcingStatus throws swallowed — result stays success, sourcingInformation stays undefined
concurrent / repeat initialize() refresh + telemetry fire exactly once (deferred-guard)
constructing the manager no discovery work runs until initialize() is awaited

All 12 new tests pass (1209 total), and the full suite + lint are green. Latest commit: 8d5f8d4.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants