Report an empty version for conda environments without Python - #1716
Report an empty version for conda environments without Python#1716Han (LH-and-FPGA) wants to merge 1 commit into
Conversation
`getCondaWithoutPython` described an interpreter-less conda prefix with `version: 'no-python'`. `version` is public API and consumers parse it as a PEP 440 version: `ms-python.python` throws `invalid version no-python` and consumes the change event with a bare `Array.forEach`, so every environment ordered after the offending one is dropped — one toolchain-only prefix hides all conda environments from the interpreter and Jupyter kernel pickers. Use `''` instead, which is what the rest of the repository already means by "unknown version" and the only unparseable value `parseVersion` degrades on rather than throwing. The `(no-python)` marker stays in the display strings, which are shown but never parsed. Also make `sortEnvironments` a total order: the `a.version ? 1 : -1` fallback returned 1 in both directions when comparing a real version against an unparseable one, leaving the sorted order implementation-defined. `getLatest` could never replace a seed whose own version did not parse.
|
@microsoft-github-policy-service agree |
|
🔒 Automated review in progress — Heejae Chang (@heejaechang) is auto-reviewing this PR. |
|
|
||
| export function isCondaEnvWithoutPython(environment: PythonEnvironment): boolean { | ||
| return environment.version === ''; | ||
| } |
There was a problem hiding this comment.
Warning · Non-blocking recommendation
version === '' also represents an unknown version generally, so it cannot reliably prove that Python is absent. Preserve a Conda-specific discriminator (or check executable availability), and cover an environment with unavailable version metadata that still has a runnable interpreter.
There was a problem hiding this comment.
Do I need to separate "no version" and "no interpreter" into two different flag?
Heejae Chang (heejaechang)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
|
Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified. |
Summary
A conda environment that has no Python interpreter makes all conda environments
disappear from the interpreter picker and the Jupyter kernel picker.
This happens with a prefix created as a toolchain rather than a Python environment,
e.g.
conda create -n cuda cuda-toolkit. Reproduced on Linux with 5 condaenvironments, one of them interpreter-less; only
basesurvived.Likely the same root cause as #1584 — that report's environment list shows a third
entry rendered as
(no-python), and it was closed asinfo-needed.Root cause
getCondaWithoutPythondescribes an interpreter-less environment with a placeholderin a field that consumers parse:
versionis declaredreadonly version: stringinsrc/api.ts, so a sentinelcompiles fine — but
ms-python.pythonparses it as a PEP 440 version:The empty string is the one unparseable value it accepts. Any other placeholder
throws.
Why one bad environment takes down the rest. This repository is careful —
condaUtils.tswraps each environment in its own try/catch during conversion. Butthe sentinel is valid data, so it passes that guard and is published in the batch
fired from
condaEnvManager.ts. The consumer has no per-item guard:Array.forEachcannot resume after a throw, so every environment ordered after theoffending one is silently dropped. Observed stack:
The fix
1. Don't publish a sentinel as a version (
condaUtils.ts,condaEnvManager.ts)version: 'no-python'→version: ''. This is already how the rest of the repositoryrepresents an unknown version:
src/features/interpreterSelection.ts—version: resolved.version ?? ''src/common/inlineScript/interpreter.ts—env.version.length === 0means not usableConda was the only one of the eight managers surfacing a sentinel. The
(no-python)marker stays in
displayName/shortDisplayName, which are displayed but neverparsed, so the UI is unchanged. The two internal
version === 'no-python'checks nowgo through an exported
isCondaEnvWithoutPythonpredicate.This also fixes a smaller bug:
pickPythonVersionbuilds its list with.map(e => e.version).filter(Boolean), and'no-python'is truthy, so "Select theversion of Python to install" offered
no-pythonas a choice.2. Make
sortEnvironmentsa total order (managers/common/utils.ts)Comparing a real version against an unparseable non-empty one returns
1in bothdirections, which breaks the antisymmetry
Array.prototype.sortrequires, so theresult is an implementation-defined permutation. Now: valid versions compare
descending, a known version sorts before an unknown one, and two unknowns fall back to
a string comparison.
getLatesthad a related gap — seeded withcandidates[0], both operands had to parsefor the seed to ever be replaced, so an unparseable seed always won.
Verification
Measured against the real
@renovatebot/pep440, on the reported environment set(
base 3.13.13, an interpreter-less prefix,git 3.14.6,lh 3.14.7,vllm 3.14.6):getLatestresultlhbaseonlyTests
npm run unittest: 1582 passing, 0 failing (1577 before this change).utils.sortEnvironments.unit.test.ts— descending order, unknown versions last,and stability across all input permutations.
condaUtils.noPythonEnv.unit.test.ts— an interpreter-less prefix is stilldiscovered, reports
version: '', and keeps its(no-python)display name.mainand pass with this change; the fourth is abaseline that passes on both.
'no-python'.src/api.tsis unchanged, so no API version bump or changelog entry is needed.