Skip to content

python: if no python, install uv and maybe create venv#12904

Merged
isabelizimm merged 15 commits intomainfrom
iz/download-uv
Apr 22, 2026
Merged

python: if no python, install uv and maybe create venv#12904
isabelizimm merged 15 commits intomainfrom
iz/download-uv

Conversation

@isabelizimm
Copy link
Copy Markdown
Contributor

@isabelizimm isabelizimm commented Apr 8, 2026

  • New registerRuntimePickerContribution API allowing extensions to add custom items to the interpreter picker
  • Full installation flow: install uv if needed -> select Python version -> install Python -> optionally create workspace venv
  • Option automatically hidden once a non-system Python is available

Release Notes

New Features

Bug Fixes

  • N/A

QA Notes

@:win @:web

Be brave! Uninstall all non-System Pythons. For uv, it looks like this

uv cache clean
rm -r "$(uv python dir)"
rm -r "$(uv tool dir)"
rm ~/.local/bin/uv ~/.local/bin/uvx  
  • Go to the Select Interpreter dropdown. You should see an option to install Python with uv.
  • Select the option to install Python with uv. The quickpick should show ONLY supported Python versions (3.9-3.14), in the MAJOR.MINOR format
  • Choose your Python version. This should install uv and then the chosen Python.
  • If you are in a workspace, next, you have the option to create a venv. If you are not in a workspace, you should not be asked if you want to make a venv since we won't know where to place it.
  • If creating a venv, it should be created and automatically selected in the Console.
  • In venv/non-venv case, you should see your new Python (and maybe your new venv) in the interpreter dropdown.
  • Once you have this new Python, you should no longer see the option to install Python in the interpreter dropdown

For automated testing purposes, we can force the "Install Python" option to always be shown in the "Select Interpreter" dropdown with the setting python.INTERNAL_alwaysShowUvInstallOption equal to True.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

E2E Tests 🚀
This PR will run tests tagged with: @:critical @:win @:web

readme  valid tags

@rodrigosf672
Copy link
Copy Markdown
Member

Thank you for the QA Notes, @isabelizimm. Creating an issue for automated testing for similar process to which you have outlined in the notes. cc @midleman @testlabauto

QA Notes

@:win @:web

Be brave! Uninstall all non-System Pythons. For uv, it looks like this

uv cache clean
rm -r "$(uv python dir)"
rm -r "$(uv tool dir)"
rm ~/.local/bin/uv ~/.local/bin/uvx  
  • Go to the Select Interpreter dropdown. You should see an option to install Python with uv.
  • Select the option to install Python with uv. The quickpick should show ONLY supported Python versions (3.9-3.14), in the MAJOR.MINOR format
  • Choose your Python version. This should install uv and then the chosen Python.
  • If you are in a workspace, next, you have the option to create a venv. If you are not in a workspace, you should not be asked if you want to make a venv since we won't know where to place it.
  • If creating a venv, it should be created and automatically selected in the Console.
  • In venv/non-venv case, you should see your new Python (and maybe your new venv) in the interpreter dropdown.
  • Once you have this new Python, you should no longer see the option to install Python in the interpreter dropdown

For automated testing purposes, we can force the "Install Python" option to always be shown in the "Select Interpreter" dropdown with the setting python.INTERNAL_alwaysShowUvInstallOption equal to True.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a “Install Python via uv” path to Positron’s interpreter selection flow so users can bootstrap a supported Python install (and optionally a workspace venv) when no suitable Python is available.

Changes:

  • Adds a special quick pick entry in the runtime selector to trigger Python installation via uv.
  • Introduces a uvPythonInstaller helper to list supported Python versions from uv, install uv if needed, install a selected Python, and optionally create a venv in a workspace.
  • Updates the Python runtime manager/commands to support refresh + returning a selected runtime id, and adds unit tests for parsing/version filtering.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/vs/workbench/contrib/languageRuntime/browser/languageRuntimeActions.ts Adds a quick pick option to install Python via uv and then select the newly installed runtime.
extensions/positron-python/src/client/pythonEnvironments/common/environmentManagers/uvPythonInstaller.ts New implementation for listing/installing Python via uv and optionally creating a venv.
extensions/positron-python/src/client/pythonEnvironments/creation/createEnvApi.ts Registers the python.installPythonViaUv command and returns the installed runtime info to the caller.
extensions/positron-python/src/client/common/constants.ts Adds the python.installPythonViaUv command id constant.
extensions/positron-python/src/client/positron/manager.ts Updates runtime selection to return a runtime id and adds an interpreter refresh helper.
extensions/positron-python/src/client/pythonEnvironments/common/environmentManagers/uv.ts Exports shared regex/helpers used by the new installer.
extensions/positron-python/src/client/pythonEnvironments/creation/provider/uvCreationProvider.ts Exports createUvVenv() for reuse in the install flow.
extensions/positron-python/src/test/pythonEnvironments/common/environmentManagers/uvPythonInstaller.unit.test.ts Adds unit coverage for uv python list parsing/filtering/deduping/sorting behavior.
extensions/positron-python/src/test/configuration/interpreterSelector/commands/setInterpreter.unit.test.ts Adjusts mocks for updated return type from selectLanguageRuntimeFromPath().

Comment thread src/vs/workbench/contrib/languageRuntime/browser/languageRuntimeActions.ts Outdated
Comment thread src/vs/workbench/contrib/languageRuntime/browser/languageRuntimeActions.ts Outdated
canPickMany: false
// Check if we should show the "Install Python via uv" option
// Only check after discovery is complete to avoid showing the option prematurely
const allowPythonInstall = configurationService.getValue<boolean>('python.allowPythonInstall') ?? true;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a command that folks can turn off if they don't want to be prompted to install uv. Right now this is the R person escape hatch, but I do worry it's heavy-handed.

@isabelizimm isabelizimm marked this pull request as ready for review April 13, 2026 18:35
@isabelizimm
Copy link
Copy Markdown
Contributor Author

Okay, after chatting IRL we think it makes sense to make infra to allow languages to install themselves. Please hold on a review!

isabelizimm and others added 4 commits April 14, 2026 06:08
…andling

- Fix $unregisterRuntimePickerContribution to actually dispose the contribution
  by tracking disposables in a Map keyed by handle
- Extract duplicated installPythonViaUv result handling into shared helper
- Fetch picker contribution items in parallel using Promise.all()
- Add warning message when venv creation fails (falls back to base Python)
- Add security note to installUv documenting the official installation pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@isabelizimm
Copy link
Copy Markdown
Contributor Author

alright, i think this is ready again!

Copy link
Copy Markdown
Contributor

@austin3dickey austin3dickey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work, this will be so nice! Haven't tested this yet but here are some code review thoughts.

Comment thread extensions/positron-python/src/client/positron/manager.ts Outdated
// Try to register the runtime
let metadata = await this.registerLanguageRuntimeFromPath(pythonPath, recreateRuntime);

// If registration failed, the interpreter might be newly created - trigger a refresh and retry
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting - I wonder if this will help with one of the new-PET problems detailed in #12116 or #12327!

* Filters out pre-release versions and returns stable versions only.
* @returns Array of available Python versions, sorted by version descending
*/
export async function getAvailablePythonVersions(): Promise<UvAvailablePython[]> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have a lot of duplicate-ish code in uv.ts, uvCreationProvider.ts, and uvUtils.ts for dealing with python versions and installing python. Maybe you can reuse all or parts of those functions?

E.g. I'd think we'd want to use approximately the same code path if you're creating a new venv with the New Folder From Template flow vs. using the Python: Create Environment command vs. clicking the button in the interpreter picker. Though I get that might be tricker than I think it is, especially because I think there's some hardcoded python stuff in the core new folder service too.

Comment thread extensions/positron-python/src/client/pythonEnvironments/creation/createEnvApi.ts Outdated
Comment thread extensions/positron-python/src/client/pythonEnvironments/creation/createEnvApi.ts Outdated
Comment thread src/vs/workbench/api/browser/positron/mainThreadLanguageRuntime.ts Outdated

try {
// Use exec directly instead of installUvPython to avoid cache issues
// when uv was just installed in the same session
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, these caching issues might need a bit more love. Everything is working fantastically along the happy path making a venv inside a workspace. But when I do the flow outside a workspace,

  1. the new interpreter that starts up is labeled Unknown, not uv
  2. if I restart Positron it's not able to find that unknown interpreter and so it gives a scary "unable to start up; failed to resolve" error

I am wondering if both those issues would be solved if we somehow force Positron to re-check whether uv is installed? There's some caching on the UvUtils class that maybe we could invalidate upon successfully installing uv? Then theoretically if we refresh discovery it'll know the new interpreter is uv and maybe if the metadata lines up we won't see problem 2.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think there's a "python: clear cache and reload window" command, maybe we could hook into the cache-clear part of that?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried the flow again with uv already installed, and didn't see these problems. So I bet the "is uv installed" cache invalidation would solve them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah we didn't have good a no-workspace fallback. I updated it to make a venv at $HOME/.venv . Do you think that's too heavy handed? I debated adding it to the ~/.positron dir, but that isn't as straightforward for discovery and the cwd for the console is $HOME too

return [
{
id: 'install-python-uv',
label: '$(add) Install Python via uv',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use the lil Python icon instead of ➕ ? If that's too hard it's cool


try {
if (process.platform === 'win32') {
await exec('powershell', [
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested on Windows ARM, and everything generally worked, though it ended up installing an x64 python instead of arm64. So I got the warning popup that there was an architecture mismatch. Python was still able to run though I'd guess that certain compiled libraries wouldn't work.

I found this:

which has the comment

I believe you can set UV_PYTHON=arm64.

Maybe we should detect the arch and set that?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like uv python list needs the --all-arches flag too.

isabelizimm and others added 4 commits April 15, 2026 18:09
Co-authored-by: Austin Dickey <austin3spammy@gmail.com>
Signed-off-by: Isabel Zimmerman <54685329+isabelizimm@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@austin3dickey austin3dickey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, looks great and Mac works well for me! I still want to test on Windows and Web before approving if that's okay. Else you can merge.

return pythonPath;
}

traceError('Could not find installed Python path');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, everything is working on web!

On ARM Windows, I see this:

2026-04-21 10:50:44.507 [info] > uv python list --all-arches
2026-04-21 10:50:46.377 [info] Installing Python 3.14 via uv...
2026-04-21 10:50:46.392 [info] > uv python install --python-platform windows-arm64 3.14
2026-04-21 10:50:46.433 [info] Python 3.14 installed successfully
2026-04-21 10:50:46.440 [info] > uv python find 3.14
2026-04-21 10:50:46.746 [error] Could not find installed Python path

and it's not able to proceed.

I think it's because --python-platform isn't a thing:

PS C:\Users\austin> uv python install --python-platform windows-arm64 3.14
error: unexpected argument '--python-platform' found

  tip: a similar argument exists: '--python-fetch'

Usage: uv.exe python install [OPTIONS] [TARGETS]...

For more information, try '--help'.

So a couple things:

  1. Not sure why the logs say it was installed successfully
  2. I looked into it some more and the only way I could get it to work was doing uv python install cpython-3.14.4-windows-aarch64-none (that is, supply the full name including arch). Using an arg or an env var wasn't helping.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is cpython-3.14.4-windows-aarch64-none the output when you run uv python list? Trying to figure out how to snag that identifier without generating it ourselves 👀

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's the identifier! (The first column in uv python list --all-arches)

Comment on lines +92 to +93
const installTarget = identifier ?? version;
await exec('uv', ['python', 'install', installTarget], { throwOnStdErr: false });
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, here's what is happening for Windows now! We only pass the identifier on Windows ARM builds, so it will be picked up for that platform but otherwise just use the vanilla version

Copy link
Copy Markdown
Contributor

@austin3dickey austin3dickey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything works perfectly! Thanks for all your work on this, this is huge!

@isabelizimm isabelizimm merged commit 8d93e51 into main Apr 22, 2026
40 checks passed
@isabelizimm isabelizimm deleted the iz/download-uv branch April 22, 2026 14:14
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants