Skip to content

Release 1.40: rebase release history onto main - #1933

Merged
Eduardo Villalpando Mello (edvilme) merged 31 commits into
release/1.40from
release-1.40-rebased
Oct 14, 2026
Merged

Eduardo Villalpando Mello (edvilme) merged 31 commits into
release/1.40from
release-1.40-rebased

Conversation

@edvilme

Copy link
Copy Markdown
Contributor

Summary

Bring every change from main through 9f1e63d152ead34491a4e3ddffd934a0fece839e into release/1.40, while retaining the stable extension version 1.40.0.

History

  • Rebase the existing release/1.40 history onto main; do not squash or selectively cherry-pick the main commits.
  • Preserve all 29 main-only commits with their original commit IDs.
  • Replay the two release-only version commits with their original authors and messages:
    • 11b8e83a -> 61aeb25b: bump extension version to 1.39.1.
    • e7d90fa0 -> e6a89ad2: bump extension version to 1.40.0.
  • Resolve only the version conflicts in package.json and package-lock.json.
  • The final tree is identical to the selected main commit except for the three extension-version fields, which are 1.40.0.

Use a merge commit when merging this PR to preserve the existing main commit IDs. Squash merging or GitHub's rebase-and-merge would not preserve that ancestry. The existing release branch has not been force-pushed.

Validation

  • npm run lint
  • npm run compile-tests
  • npm run unittest -- --reporter dot: 2,885 passing, 9 pending.
  • npm run package
  • git diff --check
  • Verified main is an ancestor of this branch, and git range-diff retains both release-only commits.
  • Verified the rebased tree matches the validated main-based 1.40.0 tree.

Release coordination

  • This PR includes all main changes, including new features and API changes, rather than only the previously proposed fixes.
  • main remains at 1.41.0; no follow-up development-version bump is currently necessary.
  • No release pipeline has been manually triggered and no publication has been authorized.
  • Before merging, confirm the active stable pipeline: the DevDiv stable definition triggers on release/* pushes and defaults publishing to enabled behind a manual validation gate.

dependabot Bot and others added 30 commits October 2, 2026 11:17
…1855)

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion)
from 1.1.18 to 1.1.21.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/8e81e187b6e9c6c723d16c042657c00acefc2483"><code>8e81e18</code></a>
1.1.21</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/ffdfa3e3806bed17c0874b8f1439b084de354a7e"><code>ffdfa3e</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/c6513ad31e08edb56dc414a629e39cba724b7548"><code>c6513ad</code></a>
1.1.20</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/1efee7c397c191da6287a78ec19512476a966a7b"><code>1efee7c</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/a34340a053abb475cc226aeb3f71887018e71bd0"><code>a34340a</code></a>
1.1.19</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/0bcbfc0a5928c3073d48f42999d1ce4fc1c42fbc"><code>0bcbfc0</code></a>
Merge commit from fork</li>
<li>See full diff in <a
href="https://github.com/juliangruber/brace-expansion/compare/v1.1.18...v1.1.21">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=brace-expansion&package-manager=npm_and_yarn&previous-version=1.1.18&new-version=1.1.21)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/microsoft/vscode-python-environments/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
With Python 3.15 releasing next week, we should drop support for 3.9 and
start testing 3.15
Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from
14.2.0 to 14.3.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/markdown-it/markdown-it/blob/14.3.2/CHANGELOG.md">markdown-it's
changelog</a>.</em></p>
<blockquote>
<h2>[14.3.2] - 2026-09-12</h2>
<h3>Security</h3>
<ul>
<li>Backported 15.0.2 fixes.</li>
</ul>
<h2>[14.3.1] - 2026-08-27</h2>
<h3>Security</h3>
<ul>
<li>Backported 15.0.1 fixes.</li>
</ul>
<h2>[14.3.0] - 2026-07-02</h2>
<h3>Changed</h3>
<ul>
<li>Reworked build pipeline &amp; tools.</li>
<li>Added source maps.</li>
<li>Bumped <code>linkify-it</code> to 5.0.2.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Preserve backslash-space hard line breaks, matching CommonMark 6.7,
<a
href="https://redirect.github.com/markdown-it/markdown-it/issues/1185">#1185</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/efb9993124c3eb229eea24dd659c91dcee7f6d60"><code>efb9993</code></a>
14.3.2 released</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/daf5a3c32303e5d9de01b12eeb725fb5990b8162"><code>daf5a3c</code></a>
Backported 15.0.2 fixes</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/a855f10b1b796ca42178952b4b83b9c8b677ddb8"><code>a855f10</code></a>
14.3.1 released</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/ad70f6b7cff64bee10e42a774147112480ca0d49"><code>ad70f6b</code></a>
Backported 15.0.1 fixes</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/b407f3b0667c9491cc52c6550736ee5a31721baa"><code>b407f3b</code></a>
Ignore generated API docs in lint</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/bf025adb983e90af426761a08cc76e4e41ab0239"><code>bf025ad</code></a>
Prepare package.json for v14 backports</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/2d9bbea7df2ab1a48caecfafc39cb8599f193d3c"><code>2d9bbea</code></a>
fix: recognize lowercase declarations as HTML blocks (CommonMark 4.6)
(<a
href="https://redirect.github.com/markdown-it/markdown-it/issues/1189">#1189</a>)</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/a311cfbeb7dcdb86d001a21facaf60190414ca4d"><code>a311cfb</code></a>
fix: keep literal backslash before space in link destination (CommonMark
6.3)...</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/ff0ee084fc6b0d10fac049fa562bc2925b5cc723"><code>ff0ee08</code></a>
14.3.0 released</li>
<li><a
href="https://github.com/markdown-it/markdown-it/commit/52e2749ab25aaf841bf74b50560929aa93b8e14d"><code>52e2749</code></a>
Bump linkify-it / vite deps</li>
<li>Additional commits viewable in <a
href="https://github.com/markdown-it/markdown-it/compare/14.2.0...14.3.2">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Isolate a saved virtual-environment resolution failure to its project
instead of abandoning selection restoration for the entire workspace.

Fixes #1853.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#1886) (#1889)

Deleting a virtual environment folder outside VS Code (for example `rm
-rf .venv`) now refreshes the venv manager, so the deleted interpreter
is no longer selected. Previously the status bar kept showing it until
reload.

- `registerSystemPythonFeatures`: a second watcher listens for deletions
only (`**/*`). VS Code reports a deleted folder as the folder alone, so
the existing `**/activate` watcher never fires for it.
- `VenvManager.hasEnvironmentAt`: the delete handler triggers the
existing debounced refresh only when the deleted path is, or contains, a
known venv; other deletions are ignored. The check is one set lookup
(about 2.6 µs per deletion whatever the number of venvs), so bulk
deletions such as clearing `__pycache__` stay cheap.
- Not changed: venvs outside the workspace folders are not watched, as
before.

## Before / after

Folder with `.venv` (Python 3.13.15); `.venv` deleted from outside VS
Code.

### Before

![Before: status bar still shows the deleted .venv after 30
s](https://github.com/karthiknadig/vscode-python-environments/blob/477b4de67fa2a58feac223abb6e378b23ca4a03a/venv-folder-deleted/before.gif?raw=true)

### After

![After: status bar switches to the global Python within ~3
s](https://github.com/karthiknadig/vscode-python-environments/blob/477b4de67fa2a58feac223abb6e378b23ca4a03a/venv-folder-deleted/after.gif?raw=true)

## Validation

| Check | Result |
|-------|--------|
| UI scenario on `main` @ 52f6ace | ❌ status bar still shows the deleted
`.venv` after 30 s |
| UI scenario with this PR | ✅ switches to Python 3.14.8 in ~3 s, 3/3 |
| `npm run lint`, `npm run compile-tests`, `npm run unittest` | ✅ 2545
passing (new tests in `main.unit.test.ts`) |

Fixes #1886

---
Created by Copilot

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
## Summary
- resolve `python.useEnvironmentsExtension` using workspace-folder,
workspace, then user precedence
- ignore contributed defaults when deciding whether explicit opt-out
applies

Fixes #1895

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

Prevent an older venv refresh from undoing a newer project interpreter
selection or publishing stale selection-change notifications.

Fixes #1859.

#### Example
A refresh can read selection A, wait for interpreter resolution, and
then overwrite selection B that the user successfully made during that
wait. Existing outer selection-cache guards do not protect the venv
manager's internal map.

## Implementation

1. Snapshot per-project selection revisions before discovery starts.
2. Track mutations from single/batch selections, clears, and removal of
mapped environments through a shared helper.
3. Preserve newer selections when clearing/restoring the project map,
and suppress stale queued selection events.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes #1871.

This prevents a broken first-run experience without introducing lasting
configuration or PATH side effects.

## Problem

When uv's install directory is not already on the extension host's PATH,
the official installer can succeed but the subsequent bare `uv
--version` lookup still fails. Python installation then stops at
`uvNotOnPath`.

Updating shell startup files does not update the already-running
extension host's environment. Resetting the availability cache alone
cannot fix this.

## Changes

- Retain the installed uv executable for the current extension-host
session, honoring the standalone installer's explicit, legacy,
unmanaged, XDG, and default destinations.
- Use that executable consistently for availability checks, Python
installation, installed/available Python version listing, and subsequent
shared uv operations.
- Preserve the executable across availability-cache resets and prevent
an older in-flight check from overwriting a newly reset cache.
- Leave process PATH and the integrated terminal's PATH unchanged.
- Add 23 regression cases covering the complete bootstrap handoff,
failures, inline-script version lookup, cache behavior, and
Windows/POSIX destination naming. Update the uv behavior documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

Fixes #1861.

Conda's automatic project selection currently assigns the sole
project-local environment to every project without a saved or inherited
selection, even when that environment belongs to another project. The
multiple-environment branch already checks ownership.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…1900)

# Add noninteractive, isolated Python environment tooling for agents

## Summary

Add a private, versioned `__pythonTools` capability to the existing flat
extension export so Python agent tools can configure environments,
inspect interpreters/packages, and install packages without requiring
extension-owned pickers or dialogs.

The companion Python-extension change consumes this capability. The
public API contract is unchanged, and host tool approval remains in
force.

## Motivation

Agent requests currently reuse interactive environment workflows, which
can pause for interpreter, manager, package, or environment-creation
choices. A selected global interpreter can also become the
package-installation target.

This change gives agents an explicit noninteractive path with isolation
by default, actionable errors, and scoped results, without recording why
an interpreter was selected.

## Behavior

- Automatic configuration reuses a usable isolated environment or
creates one for the project. A selected System/Pyenv base creates a venv
using that interpreter; Conda base creates a project Conda environment
with the same Python major/minor version.
- An explicit `pythonPath` still selects that exact existing
interpreter. Package tools reject global/base environments even when
selected explicitly.
- Queries do not create environments or change selection. Package
installation does not implicitly configure an environment.
- Configuration and installation require an open, trusted, local
workspace. Results identify the effective resource, environment, and
execution information.
- Root selections survive reload, including when
`python.defaultInterpreterPath` is configured. Nested targets persist
exact project entries without replacing root defaults.
- Existing Poetry/Pipenv project caches and enabled PEP 723 scripts have
noninteractive discovery/setup paths.
- Errors and partial creation results are returned explicitly.
Same-scope operations are serialized; cancellation and timeouts await
owned-process cleanup and report uncertainty instead of falsely claiming
that a process stopped.
- Failed human venv initialization invalidates partial discovery and
readiness state, so subsequent public lookups retry discovery instead of
remaining on a stale global fallback. Private discovery remains
independent of human onboarding.

## Human-flow compatibility

Built-in managers opt in through internal symbol capabilities and
explicit operation flags. Normal public selection, creation, package,
and execution entry points retain their interactive behavior, including
public quick-create's `.venv-N` suffixing.

This is not a claim that all shared code is untouched:

- Venv collection events can arrive earlier relative to base-manager
onboarding.
- Public Conda command failures no longer generate the extra unhandled
rejection caused by the old unused `finally()` promise.
- Agent selections, settings, and package changes intentionally remain
visible to subsequent human operations.

## Validation

- Full ESLint and TypeScript checks pass.
- Windows unit suite after rebasing onto current upstream `main`:
**2,752 passing, 7 pending**. Six new failure-path assertions failed
before the retry fix and now pass; successful initialization remains
cached. The new upstream venv deletion, unresolved-selection recovery,
refresh selection-race, uv bootstrap, and scoped Conda discovery tests
also pass with the combined implementation.
- Reviewer regression coverage verifies that private Conda execution
preserves shell metacharacters as one argument with shell execution
disabled, resolves Windows batch launchers to a real executable or fails
actionably, and scopes both package queries and installation
independently when two Poetry projects share one environment.
- Linux private/public boundary and owned-process suites with the retry
fix: **116 passing**.
- Real VS Code comparisons against the current base verified manual
selection, package install/remove, Run Python File, debugging, unittest
discovery/execution, switching back to global Python, and public
quick-create.
- Real-host agent verification covered fresh/global setup, selected-base
preservation, reload, multi-root, nested targets, Conda, Poetry/Pipenv,
PEP 723, cancellation, no-workspace behavior, and invalid input.
- Critical flows were repeated against freshly built production VSIX
contents. Installed files were compared with the packages rather than
inferred from unchanged version numbers.
- An additional real VS Code before/after retry check used the loaded
extension's actual venv manager, native discovery, a real newly created
venv, public selection and Run Python File. A one-shot post-discovery
base failure was injected only in the isolated test host. Both direct
initialization and public-get retries recovered without manual manager
refresh after the fix; the pre-fix build required refresh.

## Known findings before merge

- Ordinary project `.python-version` / `pyproject.toml` interpreter
constraints are not automatically resolved. Selected base interpreters
and `defaultInterpreterPath` are honored; PEP 723 constraints are
handled separately.
- macOS/remote E2E, arbitrary third-party integrations, and real-chat
model choices/approval combinations have not been exhaustively verified.

## Companion change

Python consumer PR:
[microsoft/vscode-python#26208](microsoft/vscode-python#26208).

The consumer checks the private version/method shape and retains a
compatibility route when the capability is unavailable.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
)

With no saved selection, a project now prefers its own `.venv` over a
venv nested in a subfolder. Previously the venv with the newest Python
anywhere under the project won, so a project with `.venv` (3.12) and
`tools/.venv` (3.13) ran on `tools/.venv`.

- `VenvManager.loadEnvMap`: among the project's environments, prefer one
whose prefix sits directly in the project folder, then fall back to the
previous order (version, then name).
- Broken environments are not preferred, so a broken root `.venv` does
not displace a working nested one (keeps the "broken last" ordering from
#1222).
- The picker's **Recommended** entry and interpreter auto-selection both
use this mapping, so both change.
- Conda, Poetry, and pyenv already prefer the environment closest to the
project; this aligns venv.
- Not changed: workspaces that already saved the nested venv keep it
until the user picks again; auto-selections are persisted like explicit
choices.

## Before / after

Fresh profile; workspace with `.venv` (Python 3.12.14) and `tools/.venv`
(Python 3.13.15).

### Before

![Before: root project auto-selects tools/.venv
(3.13.15)](https://github.com/karthiknadig/vscode-python-environments/blob/7a80f4b365f17b4cd44f884c01edbcb6434a46c8/prefer-project-root-venv/before.gif?raw=true)

### After

![After: root project auto-selects its own .venv
(3.12.14)](https://github.com/karthiknadig/vscode-python-environments/blob/7a80f4b365f17b4cd44f884c01edbcb6434a46c8/prefer-project-root-venv/after.gif?raw=true)

## Validation

| Check | Result |
|-------|--------|
| UI scenario on `main` @ 52f6ace | ❌ selects `tools\.venv (3.13.15)` |
| UI scenario with this PR | ✅ selects `.venv (3.12.14)`, 3/3 |
| `npm run lint`, `npm run compile-tests`, `npm run unittest` | ✅ 2545
passing (new: `venvManager.autoSelect.unit.test.ts`, 4 tests) |

Fixes #1878

---
Created by Copilot

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Eleanor Boyd <26030610+eleanorjboyd@users.noreply.github.com>
## Summary

- Keep the setup CodeLens available whenever a recognizable PEP 723
script block exists, including incomplete or malformed live edits.
- Keep `Script environment ready (Python X.Y.Z)` persistent for
validated, available script environments.
- Re-evaluate unsaved metadata edits immediately while preserving Ready
and exact-file routing for body-only edits.
- Prevent pending saved-metadata reads from restoring stale routing
after a live metadata edit.
- Validate malformed metadata when setup is invoked, preserving
diagnostics and avoiding invalid environment associations.
- Harden setup, save, cache-repair, and stale-operation behavior and
document the updated user flow.
- Add focused parser, routing, CodeLens, detector, setup, manager, and
real VS Code integration coverage.

## Validation

- `npm run lint`
- `npm run compile-tests`
- `npm run unittest` — 2,812 passing, 7 pending after rebasing onto the
latest `main`
- Production webpack build
- Inline VS Code integration — 8 passing
- Real-environment PEP 723 workflows — 21 passing
- Smoke suite — 31 passing
- Environment discovery E2E — 4 passing
- Manual Windows VS Code Insiders testbed matrix covering setup,
persistent Ready, live edits, Undo/Revert, malformed metadata,
diagnostics, quick fixes, Run File, Pylance routing, cache repair,
restart persistence, and feature-off behavior
- Static core, additional-use-case, quick-fix, and 8-KiB boundary
verification

## Notes

The tolerant block detector is presentation-only. Semantic parsing
remains authoritative for diagnostics, setup eligibility, environment
identity, persistence, and exact-file routing.

A separate full integration run completed with 57 passing and 8 pending
tests plus one existing environment-creation timeout. The timed-out
fixture selects the system manager, which cannot quick-create
headlessly; instrumentation confirmed it does not enter the PEP 723
path.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
In an empty VS Code window, changing the global interpreter leaves the
previous environment’s shell-startup instructions in place, so brand-new
terminals still activate it.

- **Activation:** Refresh the global terminal environment-variable
collection on URI-less selection changes when no workspace folders are
open. Apply the authoritative environment from the change event instead
of re-querying the API while it may still expose the previous selection;
clearing the selection removes stale instructions.
- **Concurrency:** Invalidate pending global initialization before
applying a newer selection so an older asynchronous refresh cannot
overwrite it.
- **Scope:** Leave folder-scoped activation and `command`/`off` modes
unchanged.
- **Coverage:** Cover A→B selection while the API still returns A,
clearing, folder isolation, disabled modes, and pending initialization
races.

<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #1864

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
## Summary

- temporarily skip the live inline-script CodeLens integration suite on
Windows
- retain integration coverage on macOS and Linux
- link the skip to #1911 so it can be re-enabled after the Windows
cleanup race is fixed

Related to #1911.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Creating a project `.env` file could clear the terminal’s scoped
variable collection, removing shell-startup activation even when
environment-file injection was disabled.

- **Event handling:** Refresh environment-file variables on create,
edit, and delete events instead of clearing the entire workspace scope.
- **File selection:** Continue using the project `.env` when a
configured environment file is removed, preserving variables from files
that remain.
- **Regression coverage:** Cover injection enabled and disabled,
variable updates and removal, and deletion when another environment file
remains.

- **Concurrency:** Ignore stale asynchronous refreshes when a newer
environment-file event has already completed. Tests now synchronize
directly with refresh completion and cover out-of-order results.\n\n<!--
START COPILOT CODING AGENT SUFFIX -->

- Fixes #1863

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
## Summary

- retry transient Windows filesystem locks when removing the inline
CodeLens integration workspace
- keep cleanup failures visible after a bounded retry window
- document the Windows integration-test cleanup pattern

## Validation

- `npm run lint`
- `npm run compile-tests`
- `npm run unittest` (`2812 passing`, `7 pending`)
- `npm run compile`
- targeted CodeLens integration suite passed once, then 10 consecutive
Windows stress runs passed with no leftover temporary workspaces
- deterministic Windows probe reproduced `EBUSY` without retries and
verified the bounded retry removes the held directory
- full integration run passed the CodeLens suite; an unrelated
environment-creation test timed out

Fixes #1911

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
## Summary

- Keep GitHub Actions dependency updates grouped into a single
Dependabot PR
- Increase the default cooldown from 7 to 14 days

The delay follows the supply-chain hardening pattern used by
python/cpython-devcontainers and avoids the highest-risk window
immediately after a new dependency release.

## Validation

- Parsed the YAML configuration successfully
- Verified the GitHub Actions entry uses a wildcard group
- Verified `cooldown.default-days: 14`
- `git diff --check`

Copilot-Session: ce6aeb0a-6210-4716-8a84-2f3e7555625f
…1879)

Python interpreters installed with `uv python install` were listed as
virtual environments, so on a machine whose only Python came from uv the
extension reported "No Python found", selected nothing, and could not
create a venv. They are now listed under **Global** as `Python 3.x
(uv)`.

PET reports uv-managed installations with kind `Uv`, the same kind it
uses for uv-created venvs; the extension routed every `Uv` environment
to the venv manager (#1775 fixed only the activation symptom).

- Add `isUvManagedPythonInstall`: a `Uv` environment whose prefix has no
`pyvenv.cfg` is a base interpreter, not a venv.
- Global manager (`refreshPythons`) lists those interpreters and labels
them `(uv)`.
- venv manager (`findVirtualEnvironments`,
`resolveVenvPythonEnvironmentPath`) leaves them to the Global manager;
uv venvs and uv workspaces are unchanged.
- `SysPythonManager.loadEnvMap` reuses the existing entry when a saved
path resolves to an interpreter that is already listed, instead of
adding a duplicate. Without this, a saved selection of uv's
`~/.local/bin/python.exe` launcher showed the interpreter three times
once PET maps launchers to the uv install
(microsoft/python-environment-tools#567).
- Use the `window.apis` `withProgress` wrapper in `SysPythonManager` so
the refresh path can be unit tested.
- The default interpreter (used when nothing is selected) still prefers
Pythons not managed by uv; uv builds are used by default only when no
other Python is installed. uv marks its installations
`EXTERNALLY-MANAGED` (PEP 668), so without this a newer uv build
replaced an existing python.org/Store Python as the default and package
installs into it failed.
- Not changed: package installs into a uv-managed interpreter are still
refused by its `EXTERNALLY-MANAGED` marker, as before.

## Before / after

Machine whose only Python is CPython 3.13.15 from `uv python install`
(uv's bin directory not on `PATH`); same scenario both runs.

### Before

![Before: "No Python found" prompt, uv interpreter under venv, venv
creation fails with "No base Python
found"](https://github.com/karthiknadig/vscode-python-environments/blob/ad37309f5f204605eae321b9b9649c35c2a055bd/uv-managed-python-global/before.gif?raw=true)

### After

![After: Python 3.13.15 (uv) under Global, auto-selected, Quick Create
builds
.venv](https://github.com/karthiknadig/vscode-python-environments/blob/ad37309f5f204605eae321b9b9649c35c2a055bd/uv-managed-python-global/after.gif?raw=true)

## Validation

| Check | Result |
|-------|--------|
| UI scenario on `main` @ 52f6ace | ❌ "No Python found" prompt ×2,
Global empty, interpreter under venv, "No base Python found" |
| UI scenario with this PR | ✅ passes 3/3 |
| Saved launcher selection + PET launcher fix | before: 3 Global
entries; after: 1 |
| Default interpreter with Install Manager 3.14.8 + uv 3.15.0rc2, no
venv | `main`: 3.14.8; this PR: 3.14.8 (before the uv preference commit
it picked uv 3.15.0rc2) |
| `npm run lint`, `npm run compile-tests`, `npm run unittest` | ✅ 2552
passing (new: `uvManagedPythonInstall.unit.test.ts`,
`sysPythonManager.savedSelection.unit.test.ts`) |

Fixes #1877

---
Created by Copilot

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Eleanor Boyd <26030610+eleanorjboyd@users.noreply.github.com>
…ixes #1884) (#1888)

`python.defaultInterpreterPath` set to a command name such as `python3`
is now looked up on `PATH` instead of being joined to the workspace
folder, and the default value `python` is treated as not configured, as
in the Python extension. Previously both showed "Default interpreter
path '…' could not be resolved" at startup and the setting was ignored.

- `toAbsoluteInterpreterPath`: a value without a path separator is
looked up on `PATH` first; other relative paths still resolve against
the workspace folder (#1603).
- `findCommandOnPath`: considers only absolute `PATH` entries and, on
Windows, only `.com`/`.exe` files, since batch-file shims (for example
pyenv-win's) cannot be started without a shell. It accepts App Execution
Aliases (`WindowsApps\python3.exe`), which exist but cannot be `stat`ed,
so `which` misses them.
- `python`, the setting's default, skips priority 3 without a warning,
so auto-discovery still prefers a workspace `.venv`. This matches the
Python extension's `DEFAULT_INTERPRETER_SETTING` handling.
- Not changed: absolute paths and `${workspaceFolder}` values; values
that cannot be resolved still warn.
- When the command resolves to a global interpreter that is not the
newest one installed, the status bar and Run use it only once #1887 is
merged (#1885).

## Before / after

Fresh profile, folder without a venv, user setting
`"python.defaultInterpreterPath": "python3"` (`python3` on `PATH` is
Python 3.14.8).

### Before

![Before: "could not be resolved" warning; the setting is
ignored](https://github.com/karthiknadig/vscode-python-environments/blob/814e9be7cb27036fb8d3e3957ff1d586dc6cbbf9/default-interpreter-command/before.gif?raw=true)

### After

![After: no warning; python3 from PATH is
used](https://github.com/karthiknadig/vscode-python-environments/blob/814e9be7cb27036fb8d3e3957ff1d586dc6cbbf9/default-interpreter-command/after.gif?raw=true)

## Validation

| Check | Result |
|-------|--------|
| UI scenario on `main` @ 52f6ace, `"python3"` | ❌ warning; `source:
autoDiscovery` |
| UI scenario with this PR, `"python3"` | ✅ no warning; `source:
defaultInterpreterPath`, 3/3 |
| UI scenario, `"python"` | `main`: ❌ warning; this PR: ✅ no warning,
`source: autoDiscovery` |
| `npm run lint`, `npm run compile-tests`, `npm run unittest` | ✅ 2546
passing (5 new tests in `interpreterSelection.unit.test.ts`, suite "bare
command names") |

Fixes #1884

---
Created by Copilot

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Eleanor Boyd <26030610+eleanorjboyd@users.noreply.github.com>
## Summary

- Refresh the PEP 723 CodeLens from live text-document changes when an
inline block appears, disappears, or is edited.
- Avoid unnecessary CodeLens refreshes for edits confined to the script
body.
- Include every `.py` casing, including `.PY`, in bulk inline-script
setup discovery.
- Re-enable the Windows CodeLens integration suite after
#1911 was fixed.

## User scenarios fixed

- **S08:** Bulk setup now finds uppercase and mixed-case Python file
extensions.
- **S10:** Dirty inline metadata edits immediately request a CodeLens
recomputation instead of waiting for a save or later routing event.
- **S11:** Adding PEP 723 metadata to an unsaved ordinary Python file
immediately surfaces the setup CodeLens.

## Validation

- `npm run lint`
- `npm run compile-tests`
- `npm run unittest` — 2,830 passing, 7 pending
- `npm run smoke-test` — 30 passing, 1 pending
- `npm run e2e-test` — 4 passing
- `npm run integration-test` — all 9 live inline-script CodeLens tests
passed on Windows; the full suite had 58 passing, 8 pending, and one
unrelated environment-creation timeout
- Manual S08 verification confirmed `h03_UPPERCASE.PY` appears in the
bulk setup picker
- S10/S11 were verified in a real VS Code extension host through
CodeLens refresh events and provider output; visible UI automation was
avoided after focus restoration caused VS Code to cancel its debounced
rendered-lens refresh

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Added utility method `_getPackageAvailableVersionsCommand` to return the
appropriate `PackageManagerCommand` to use when calling the version
lookup functionality.
This abstracts the selection logic and makes feature discoverability
easier.

This attempts to introduce no behavioral changes.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
## Summary

- show interpreter setting warnings without blocking initial environment
selection
- keep the settings-change listener available while a warning remains
unanswered
- log failures from detached notification work
- preserve warning deduplication and the **Open Settings** action

Fixes #1890

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
Contributes to #1837
As part of the efforts to streamline the API and simplify feature
detection (#1874), environment managers should have a mechanism to
advertise their versions. `PackageManager`'s already do this with a
`async getVersion()` method.
…1929)

## Summary
- Make the inline-script late-build discovery test deterministic using
fake timers and completion signals. Exercise the production 1s/5s/30s
retry schedule, finish filesystem setup before advancing the final
timer, and assert discovery does not happen early.
- Capture Linux CI startup diagnostics through a shared Xvfb action used
by PR and push workflows: launcher stdout/stderr, X server stderr,
verbose VS Code logs, and a marker written when the extension-host test
runner reaches global setup.
- Upload diagnostics only for failed launches, with
suite/Python-version/run-attempt-specific names and seven-day retention.
Document how to distinguish startup failures from tests that actually
started.

Motivated by failures on #1920 and #1921. This does not claim to fix the
Linux VS Code startup hang; it preserves the evidence needed to diagnose
it. No new retries, timeout increases, profile isolation, or production
behavior changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…1920)

The project-view environment selector lacks direct path entry when
discovery misses an interpreter. This adds **Enter Interpreter Path...**
so users can type or paste a known executable path.

- **Selection:** Reuses the existing interpreter resolution, progress,
and error handling; preserves project-scoped assignment.
- **Compatibility:** Keeps Browse and discovered-environment selection
unchanged. Cancelled, blank, or invalid input leaves the current
selection untouched.

<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #1919

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#1921)

Selecting a virtual environment by interpreter path updates the active
interpreter but leaves the environment manager list stale until manual
refresh.

- **Synchronization:** Call the existing `addEnvironment(resolved,
true)` helper in `VenvManager.resolve()` to register the environment and
notify the UI, preserving deduplication.
- **Regression coverage:** Cover immediate list updates, selection,
repeated interpreter/folder resolution, and rejection of unresolved or
non-venv paths.

<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #1918

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
Fixes #1832.

Depends on #1872, which retains a newly installed uv executable for the
current extension-host session.

## Problem

Creating a **Global** environment on a machine without uv failed with
**Failed to fetch available Python versions**. The flow attempted `uv
python list` before reaching the existing uv installation path.

## User experience

When uv is missing, Global environment creation now explains why it is
required and offers:

- **Install uv** — installs uv, then continues directly to the Python
version picker using #1872's retained executable.
- **Other installation options** — opens the official [Install a Python
interpreter](https://code.visualstudio.com/docs/python/python-tutorial#_install-a-python-interpreter)
guide.
- **Cancel** — cancels quietly without showing a misleading
version-fetch error.

If uv installation fails, the error offers **View Logs**. When uv is
already available, the version picker opens without an additional
prompt.

This prevents a broken first-run experience without introducing lasting
configuration or PATH side effects.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ment variables (#1865)

If `<project>/.env` was a directory, for example a virtual environment
named `.env`, `getEnvironmentVariables()` tried to read it as a file and
threw `EntryIsADirectory`. That broke terminal env injection and
Pylance. The same happened when `python.envFile` pointed at a directory.
The cause was the `fs-extra` `pathExists` check, which also returns true
for directories.

### Changes

- **`envVariableManager.ts`**: both `pathExists` checks are replaced
with a private `isEnvFile` helper, which accepts only regular files:
  ```ts
  async function isEnvFile(filePath: string): Promise<boolean> {
      try {
          return (await fsapi.stat(filePath)).isFile();
      } catch (error) {
          const code = (error as NodeJS.ErrnoException).code;
          if (code === 'ENOENT' || code === 'ENOTDIR') {
              return false;
          }
          throw error;
      }
  }
  ```
- It uses `stat`, not `lstat`, so symlinks to regular files still load.
Symlinks to directories are skipped.
- Errors other than `ENOENT`/`ENOTDIR` (for example, `EACCES`) are still
raised, not hidden.
  - `parseEnvFile` is never called on a skipped path.
- **Tests** (`envVariableManager.unit.test.ts`): these call
`getEnvironmentVariables` directly and cover:
  - a directory at either path
  - a valid file next to a directory
  - two regular files loading in the existing order
- symlinks to a file or a directory, using real temp-dir symlinks that
are skipped if the platform can't create them
  - missing paths and `ENOTDIR` being skipped, and `EACCES` being raised

### Not changed

- **Precedence:** the order documented in `docs/README.md` stays the
same: base → `python.envFile` → project `.env` → overrides. This PR does
**not** implement the issue's separate request to have `python.envFile`
suppress project `.env` discovery.
- **Other behavior:** path selection, deduplication, merging, and URI
overrides are untouched.
- **Race:** this is a check before the read, so a path that changes type
between the `stat` and the read can still fail.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: edvilme <5952839+edvilme@users.noreply.github.com>
Co-authored-by: Eduardo Villalpando Mello <eduardovil@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary

- correct the extension version from 1.39.1 to 1.40.0 for the
release/1.40 branch
- update the package lockfile to match

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@edvilme Eduardo Villalpando Mello (edvilme) added the debt Code quality issues label Oct 14, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@eleanorjboyd

Eleanor Boyd (eleanorjboyd) commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

I think the commit bump main to 1.40 then 1.41 ([https://github.com//pull/1902) is here too so you may need another commit to revert this back to 1.40

NVM! I see you got that! thx

@heejaechang

Copy link
Copy Markdown

🔒 Automated review in progress — Heejae Chang (@heejaechang) is auto-reviewing this PR.

log?: LogOutputChannel,
token?: CancellationToken,
timeoutMs?: number,
includeStderr = false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Issue · Please address or respond

📍 src/common/utils/processRunner.ts:114
The API parameters rule requires cancellation tokens last, but timeoutMs and includeStderr follow token as positional parameters. Move the token last or use the rule-permitted trailing options bag, updating callers; this rule violation must be fixed before merge.

[verified]

promise: PromiseLike<T>,
token: CancellationToken,
timeoutMs: number | null = 30_000,
): Promise<T> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Issue · Please address or respond

📍 src/internal/pythonToolSupport.ts:128
waitForToolRead places the positional timeoutMs after token, violating the API parameters token-last rule. Reorder the parameters or use the permitted options-bag form and update callers; this is a required conformance fix.

[verified]

timeout?: number,
executable = 'uv',
executable = uvExecutable,
toolExecution = false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Issue · Please address or respond

📍 src/managers/builtin/helpers.ts:116
The modified runUV and runPython signatures leave cancellation tokens before subsequent positional settings, contrary to the API parameters rule. Move tokens last or consolidate those settings into the permitted options-bag form, updating both helpers and their callers before merge.

[verified]

private disposables: Disposable[] = [];
// Track which .env variables we've set for each workspace to avoid clearing shell activation variables
private envVarKeys: Map<string, Set<string>> = new Map();
private refreshGenerations: Map<string, number> = new Map();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Issue · Please address or respond

📍 src/features/terminal/terminalEnvVarInjector.ts:32
Mark the newly added refreshGenerations field readonly to satisfy Readonly by default. Mutating the map does not require reassigning the field, so its current declaration is a must-fix rule violation.

[verified]

@heejaechang

Copy link
Copy Markdown

Result: ⚠️ needs-more-tests

Verification details

Verification: Isolated verification observed failures whose relationship to this PR could not be determined: Compilation, private Python tools, process ownership, and extension API; this review is not fully verified.

Summary: Offline dependency installation, TypeScript compilation, lint, and production packaging passed. Targeted suites reported 1,419 passing tests, 6 pending, and 1 failure. The POSIX descendant-cleanup test received ProcessTerminationError instead of CancellationError; PID 1 was sleep and an orphaned Node zombie remained, suggesting container-sensitive behavior without proving attribution. All three extension-version fields were 1.40.0. Electron integration tests and release ancestry remain unverified, so this is not a clean verification.

Test runs: 5 passed, 1 failed, 1 not run

  • ❌ Failed | relationship unknown | Compilation, private Python tools, process ownership, and extension API | npm run compile-tests && node ./node_modules/mocha/bin/mocha.js --no-config --require source-map-support/register --require ./out/test/unittests.js --ui tdd --timeout 180000 --reporter dot 'out/test/internal/*.unit.test.js' out/test/extensionApi.unit.test.js
  • ⚠️ Not run | Electron integration coverage, including live inline-script CodeLens | npm run integration-test
  • ✅ Passed | Inline-script parsing, routing, editor UX, and startup diagnostics | node ./node_modules/mocha/bin/mocha.js --no-config --require source-map-support/register --require ./out/test/unittests.js --ui tdd --timeout 180000 --reporter dot 'out/test/common/inlineScript/.unit.test.js' 'out/test/features/inlineScript/.unit.test.js' out/test/diagnostics.unit.test.js
  • ✅ Passed | Changed built-in environment and package manager regressions | node ./node_modules/mocha/bin/mocha.js --no-config --require source-map-support/register --require ./out/test/unittests.js --ui tdd --timeout 180000 --reporter dot out/test/managers/builtin/helpers.isUvInstalled.unit.test.js out/test/managers/builtin/inlineScript/envManager.unit.test.js out/test/managers/builtin/main.unit.test.js out/test/managers/builtin/pipPackageManager.unit.test.js out/test/managers/builtin/pipUtils.unit.test.js out/test/managers/builtin/sysPythonManager.savedSelection.unit.test.js out/test/managers/builtin/uvManagedPythonInstall.unit.test.js out/test/managers/builtin/uvPythonInstaller.unit.test.js out/test/managers/builtin/venvManager.autoSelect.unit.test.js out/test/managers/builtin/venvManager.resolve.unit.test.js out/test/managers/builtin/venvManager.selection.unit.test.js out/test/managers/builtin/venvManager.selectionRace.unit.test.js out/test/managers/builtin/venvUtils.createWithProgress.unit.test.js out/test/managers/conda/commands.unit.test.js out/test/managers/conda/condaEnvManager.projectIsolation.unit.test.js out/test/managers/conda/condaUtils.toolExecution.unit.test.js out/test/managers/pipenv/pipenvUtils.getPipenv.unit.test.js out/test/managers/pyenv/pyenvUtils.unit.test.js
  • ✅ Passed | Lint, production package, changed feature regressions, and version checks | npm run lint && npm run package && node ./node_modules/mocha/bin/mocha.js --no-config --require source-map-support/register --require ./out/test/unittests.js --ui tdd --timeout 180000 --reporter dot out/test/common/environmentPicker.unit.test.js out/test/common/pythonPath.unit.test.js out/test/features/envCommands.unit.test.js out/test/features/envManagers.unit.test.js out/test/features/execution/envVariableManager.unit.test.js out/test/features/interpreterSelection.unit.test.js out/test/features/settings/settingHelpers.activation.unit.test.js out/test/features/settings/settingHelpers.unit.test.js out/test/features/terminal/shellStartupActivationVariablesManager.unit.test.js out/test/features/terminalEnvVarInjector.unit.test.js && node -e 'const assert=require("assert"),fs=require("fs"); const p=require("./package.json"),l=require("./package-lock.json"); assert.deepStrictEqual([p.version,l.version,l.packages[""].version],["1.40.0","1.40.0","1.40.0"]);console.log("PASS: all three extension version fields are 1.40.0");console.log("PID 1:",fs.readFileSync("/proc/1/comm","utf8").trim()); for(const pid of fs.readdirSync("/proc").filter(x=>/^\d+$/.test(x))){try{const s=fs.readFileSync("/proc/"+pid+"/stat","utf8"),m=s.match(/^\d+ ((.*)) (\S) (\d+)/);if(m&&m[2]==="Z") console.log("Zombie:",pid,"command="+m[1],"ppid="+m[3]);}catch{}}'
  • ✅ Passed | Dependency, runner, and repository discovery | pwd; printf '\nPROFILE=%s\n' "$AUTOMATION_SANDBOX_PROFILE"; node --version; npm --version; git rev-parse HEAD; git log -5 --format='%h %s'; git status --short; node -e 'const p=require("./package.json");console.log(JSON.stringify({version:p.version,scripts:p.scripts},null,2)); for(const f of ["node_modules/mocha/bin/mocha.js","node_modules/typescript/bin/tsc","out/test",".mocharc.js",".mocharc.json","tsconfig.json"]){console.log(f,require("fs").existsSync(f))}'; git diff --stat 9f1e63d152ead34491a4e3ddffd934a0fece839e HEAD; git diff-tree --no-commit-id --name-status -r HEAD; ls src/test/internal src/test/common/inlineScript src/test/features/inlineScript
  • ✅ Passed | Offline dependency preparation | npm ci --offline --ignore-scripts
❌ Compilation, private Python tools, process ownership, and extension API diagnostic output
TypeScript compilation completed.
122 passing (7s)
1 failing
Python tool process ownership
real POSIX exited parent with a live child retaining pipes cannot report an early successful cleanup:
AssertionError: Expected CancellationError. Received ProcessTerminationError.
Unable to stop /usr/local/bin/node; it may still be modifying the environment. Process cleanup did not complete within 5000ms.
at src/test/internal/processRunner.unit.test.ts:273:17
⚠️ Electron integration coverage, including live inline-script CodeLens diagnostic output
Electron tests requiring a downloaded VS Code instance are unsupported in this offline verification environment.

@heejaechang Heejae Chang (heejaechang) added the review-auto:changes-requested Automated review: posted blocking findings to address. label Oct 14, 2026
@edvilme
Eduardo Villalpando Mello (edvilme) merged commit 6059669 into release/1.40 Oct 14, 2026
99 of 100 checks passed
@edvilme
Eduardo Villalpando Mello (edvilme) deleted the release-1.40-rebased branch October 14, 2026 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

debt Code quality issues review-auto:changes-requested Automated review: posted blocking findings to address.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants