From 19ac4f0f3181c8e6443e912933c84076a1892a8a Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 25 Sep 2026 10:08:10 -0700 Subject: [PATCH 1/3] release: Prevent virtualenv redirect from occupying .venv Backport #26167 to release/2026.6. virtualenv 21.12 creates a .venv redirect when the workflow sets up .virtualenv beside a pyproject.toml, blocking the separate stdlib venv test environment. Opt out of that side effect and report venv creation failures directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build.yml | 7 ++++--- .github/workflows/pr-check.yml | 14 ++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10bd0449de12..66530c11c042 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -311,7 +311,7 @@ jobs: if: matrix.test-suite == 'venv' run: | python -m pip install virtualenv - python -m virtualenv .virtualenv/ + python -m virtualenv --no-venv-redirect .virtualenv/ if ('${{ matrix.os }}' -match 'windows-latest') { & ".virtualenv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} virtualEnvPath } else { @@ -326,10 +326,11 @@ jobs: if: matrix.test-suite == 'venv' && startsWith(matrix.python, 3.) run: | python -m venv .venv + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } if ('${{ matrix.os }}' -match 'windows-latest') { - & ".venv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath + & "./.venv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath } else { - & ".venv/bin/python" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath + & "./.venv/bin/python" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath } - name: Prepare conda for venv tests diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 34869bfcd0cb..45079075899f 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -304,7 +304,7 @@ jobs: if: matrix.test-suite == 'venv' run: | python -m pip install virtualenv - python -m virtualenv .virtualenv/ + python -m virtualenv --no-venv-redirect .virtualenv/ if ('${{ matrix.os }}' -match 'windows-latest') { & ".virtualenv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} virtualEnvPath } else { @@ -319,10 +319,11 @@ jobs: if: matrix.test-suite == 'venv' && startsWith(matrix.python, 3.) run: | python -m venv .venv + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } if ('${{ matrix.os }}' -match 'windows-latest') { - & ".venv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath + & "./.venv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath } else { - & ".venv/bin/python" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath + & "./.venv/bin/python" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath } - name: Prepare conda for venv tests @@ -584,7 +585,7 @@ jobs: shell: pwsh run: | python -m pip install virtualenv - python -m virtualenv .virtualenv/ + python -m virtualenv --no-venv-redirect .virtualenv/ if ('${{ matrix.os }}' -match 'windows-latest') { & ".virtualenv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} virtualEnvPath } else { @@ -598,10 +599,11 @@ jobs: shell: pwsh run: | python -m venv .venv + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } if ('${{ matrix.os }}' -match 'windows-latest') { - & ".venv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath + & "./.venv/Scripts/python.exe" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath } else { - & ".venv/bin/python" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath + & "./.venv/bin/python" ./build/ci/addEnvPath.py ${{ env.PYTHON_VIRTUAL_ENVS_LOCATION }} venvPath } - name: Prepare conda for venv tests From 82a033730e448f3622d151093a614bc70a1331b7 Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 25 Sep 2026 13:41:03 -0700 Subject: [PATCH 2/3] release: Include locator output on finder test failure Expose the existing Python Locator log in the failing Windows unit-test assertion so the release CI run can distinguish an empty discovery from a process or refresh error without weakening the assertion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/test/pythonEnvironments/nativePythonFinder.unit.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/pythonEnvironments/nativePythonFinder.unit.test.ts b/src/test/pythonEnvironments/nativePythonFinder.unit.test.ts index b6182da8111f..597b99ecd0ea 100644 --- a/src/test/pythonEnvironments/nativePythonFinder.unit.test.ts +++ b/src/test/pythonEnvironments/nativePythonFinder.unit.test.ts @@ -21,10 +21,11 @@ suite('Native Python Finder', () => { let getConfigurationStub: sinon.SinonStub; let configMock: typemoq.IMock; let getWorkspaceFolderPathsStub: sinon.SinonStub; + const locatorOutput = new MockOutputChannel('locator'); setup(() => { createLogOutputChannelStub = sinon.stub(windowsApis, 'createLogOutputChannel'); - createLogOutputChannelStub.returns(new MockOutputChannel('locator')); + createLogOutputChannelStub.returns(locatorOutput); getWorkspaceFolderPathsStub = sinon.stub(workspaceApis, 'getWorkspaceFolderPaths'); getWorkspaceFolderPathsStub.returns([]); @@ -55,7 +56,7 @@ suite('Native Python Finder', () => { } // typically all test envs should have at least one environment - assert.isNotEmpty(envs); + assert.isNotEmpty(envs, `Python Locator output:\n${locatorOutput.output || '(none)'}`); }); test('Resolve should return python environments with version', async () => { From 72005150baf6df9eadba62fd5a5e376e277c4040 Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 25 Sep 2026 14:17:11 -0700 Subject: [PATCH 3/3] release: Sequence initial finder configure before refresh The constructor sent a configure request concurrently with the first refresh. On Windows Pet can process the refresh at generation 0 and then suppress its environment notifications when configure advances to generation 1. Let the first refresh perform and await configuration before sending its request. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../base/locators/common/nativePythonFinder.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts b/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts index ea0d63cd7552..7d0f7d103d76 100644 --- a/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts +++ b/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts @@ -120,7 +120,6 @@ class NativePythonFinderImpl extends DisposableBase implements NativePythonFinde ? getGlobalStorage(this.context, DONT_SHOW_SPAWN_ERROR_AGAIN, false) : ({ get: () => false, set: async () => {} } as IPersistentStorage); this.connection = this.start(); - void this.configure(); this.firstRefreshResults = this.refreshFirstTime(); }