microsoft / microsoft/vscode-python-environments

Terminal activation emits `source <prefix>/bin/activate` for uv-managed toolchains that have no activate script

Ouverte
#1,775 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

triage-needed
Langage dominant
TypeScript
Étoiles
138
Forks
62
Merge moyen
1 j 4 h
PR mergées (30 j)
35

Description

## Environment

| | |
|---|---|
| Extension | `ms-python.vscode-python-envs` **1.36.0** (also present in **1.37.2026090401**, published 2026-09-04) |
| VS Code | 1.137.0 |
| OS | macOS 15.6 (arm64) |
| Shell | zsh |
| Environment manager | `uv` (plus `ms-python.python:system` for comparison) |

## Steps to reproduce

1. `uv python install 3.13` — installs a toolchain to `~/.local/share/uv/python/cpython-3.13.9-macos-aarch64-none/`.
2. Open a folder in VS Code whose selected interpreter is that toolchain:
`Ctrl/Cmd+Shift+P` → **Python: Select Interpreter** → **Enter interpreter path…** →
`~/.local/share/uv/python/cpython-3.13.9-macos-aarch64-none/bin/python`
3. Open an integrated terminal.

## Actual behavior

```
source /Users//.local/share/uv/python/cpython-3.13.9-macos-aarch64-none/bin/activate
source: no such file or directory: /Users//.local/share/uv/python/cpython-3.13.9-macos-aarch64-none/bin/activate
```

The toolchain's `bin/` contains `python3.13`, `python`, `pip`, `idle3` — there is no `activate`.
A `uv python install` toolchain is a base interpreter, not a virtual environment, so the failure
is not a broken install: the activation command itself should never have been emitted.

Once persisted, the same command is emitted on **every** new terminal in that folder and
survives restarts — this is not a one-off.

Python Environments log for the same window:

```
[interpreterSelection] deven367: cpython-3.13.9-macos-aarch64-none (3.13.9) (source: autoDiscovery)
Terminal is activated: /Users//.local/share/uv/python/cpython-3.13.9-macos-aarch64-none/bin/python
```

(The extension also auto-discovered and selected this toolchain for a folder with no
environment at all, with no user selection — same outcome.)

## Expected behavior

No activation command is emitted for an environment that cannot be activated; either the
toolchain is reported as non-activatable (like `system` environments, which correctly emit
nothing), or the activation command is gated on the activation script existing.

## Cause

`getShellActivationCommands(dir)` sets the sh/bash/zsh/gitbash (`and "unknown"`) activation
entries **unconditionally**, while fish/csh/xsh/nu are gated on `pathExists`:

```js
t.getShellActivationCommands = async function (e) {
const t = new Map(), n = new Map();
return isWindows()
? t.set("unknown", [{ executable: join(e, "activate") }])
: t.set("unknown", [{ executable: "source", args: [join(e, "activate")] }]), // no pathExists
t.set(SH, [{ executable: "source", args: [join(e, "activate")] }]), // no pathExists
t.set(BASH, [{ executable: "source", args: [join(e, "activate")] }]), // no pathExists
t.set(GITBASH, [{ executable: "source", args: [v(join(e, "activate"))] }]), // no pathExists
t.set(ZSH, [{ executable: "source", args: [join(e, "activate")] }]), // no pathExists
...
await pathExists(join(e, "activate.csh")) && t.set(CSH, ...); // gated
await pathExists(join(e, "activate.fish")) && t.set(FISH, ...); // gated
await pathExists(join(e, "activate.xsh")) && t.set(XSH, ...); // gated
await pathExists(join(e, "activate.nu")) && t.set(NU, ...); // gated
return { shellActivation: t, shellDeactivation: n };
};
```

It is called with `dirname(executable)`, i.e. `/bin`:

```js
const a = dirname(e.executable),
{ shellActivation: o, shellDeactivation: s } = await getShellActivationCommands(a);
```

So for any prefix without `bin/activate`, a failing command is produced instead of an
environment with no activation. `isActivatableEnvironment()` then returns `true`, because it
only checks that `shellActivation` is non-empty:

```js
t.isActivatableEnvironment = function (e) {
return !!e.execInfo?.activation || !!e.execInfo?.shellActivation;
};
```

The uv manager registers these toolchains through the venv path — the log shows
`Found venv environment: cpython-3.13.9-macos-aarch64-none (3.13.9)` for a directory that has
no `pyvenv.cfg` and no `activate`. `system` environments, which carry no `shellActivation`,
behave correctly and emit nothing.

## Suggested fix

- Gate the sh/bash/zsh/gitbash/unknown entries on `pathExists(join(dir, "activate"))`, matching
the existing fish/csh/xsh/nu checks, so a prefix without an activation script yields an
effectively non-activatable environment.
- Optionally, additionally report `uv python install` toolchains as non-activatable (they have
no `pyvenv.cfg`), so they are not offered as activatable venv environments.

## Workaround

Pin the folder to the system manager, which emits no activation command:

```json
"python-envs.pythonProjects": [
{ "path": "", "envManager": "ms-python.python:system" }
]
```

or select a real `.venv` / system interpreter instead of the uv toolchain.

## Additional context

Reproduced by selecting the interpreter through **Python: Select Interpreter → Enter interpreter
path…** in the GUI, and independently by restoring the persisted
`ms-python.vscode-python-envs:venv:WORKSPACE_SELECTED` entry the picker writes.

Unrelated observation from the same session, in case it is useful: activating the extension
wrote `"python-envs.defaultEnvManager": "ms-python.python:venv"` into the workspace
`settings.json` (`~/.vscode/settings.json`) by itself.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par localiser getShellActivationCommands et isActivatableEnvironment, puis suivez l’appel dirname(executable) pour les interpréteurs gérés par uv. Reproduisez le problème avec une toolchain uv python install et vérifiez que les environnements dépourvus de bin/activate n’émettent aucune commande d’activation, tandis que les véritables environnements virtuels continuent de s’activer correctement.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python, typescript, vscode
Domaine
developer-experience, devtools, tooling
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
Active
Clarté
Clairement spécifiée
Accessibilité débutants
76/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.