From 98bd3b72daa1ab6a424bc9de1ff0c7d18fdf0eb6 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 26 Nov 2025 10:27:13 -0800 Subject: [PATCH 1/2] Fix: Validate existence of pipenv, poetry, and pyenv paths before usage --- src/managers/pipenv/pipenvUtils.ts | 26 ++++++++++++++------- src/managers/poetry/poetryUtils.ts | 36 +++++++++++++++++++----------- src/managers/pyenv/pyenvUtils.ts | 17 +++++++++----- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/managers/pipenv/pipenvUtils.ts b/src/managers/pipenv/pipenvUtils.ts index e490c73b..9554c0f4 100644 --- a/src/managers/pipenv/pipenvUtils.ts +++ b/src/managers/pipenv/pipenvUtils.ts @@ -54,22 +54,32 @@ function getPipenvPathFromSettings(): string | undefined { export async function getPipenv(native?: NativePythonFinder): Promise { if (pipenvPath) { - return pipenvPath; + if (await fs.exists(untildify(pipenvPath))) { + return untildify(pipenvPath); + } + pipenvPath = undefined; } const state = await getWorkspacePersistentState(); - pipenvPath = await state.get(PIPENV_PATH_KEY); - if (pipenvPath) { - traceInfo(`Using pipenv from persistent state: ${pipenvPath}`); - return pipenvPath; + const storedPath = await state.get(PIPENV_PATH_KEY); + if (storedPath) { + if (await fs.exists(untildify(storedPath))) { + pipenvPath = storedPath; + traceInfo(`Using pipenv from persistent state: ${pipenvPath}`); + return untildify(pipenvPath); + } + await state.set(PIPENV_PATH_KEY, undefined); } // try to get from settings const settingPath = getPipenvPathFromSettings(); if (settingPath) { - pipenvPath = settingPath; - traceInfo(`Using pipenv from settings: ${settingPath}`); - return pipenvPath; + if (await fs.exists(untildify(settingPath))) { + pipenvPath = settingPath; + traceInfo(`Using pipenv from settings: ${settingPath}`); + return untildify(pipenvPath); + } + traceInfo(`Pipenv path from settings does not exist: ${settingPath}`); } // Try to find pipenv in PATH diff --git a/src/managers/poetry/poetryUtils.ts b/src/managers/poetry/poetryUtils.ts index 50b1ecc6..a697a761 100644 --- a/src/managers/poetry/poetryUtils.ts +++ b/src/managers/poetry/poetryUtils.ts @@ -106,28 +106,38 @@ export async function setPoetryForWorkspaces(fsPath: string[], envPath: string | export async function getPoetry(native?: NativePythonFinder): Promise { if (poetryPath) { - return poetryPath; + if (await fs.exists(untildify(poetryPath))) { + return untildify(poetryPath); + } + poetryPath = undefined; } const state = await getWorkspacePersistentState(); - poetryPath = await state.get(POETRY_PATH_KEY); - if (poetryPath) { - traceInfo(`Using poetry from persistent state: ${poetryPath}`); - // Also retrieve the virtualenvs path if we haven't already - if (!poetryVirtualenvsPath) { - getPoetryVirtualenvsPath(untildify(poetryPath)).catch((e) => - traceError(`Error getting Poetry virtualenvs path: ${e}`), - ); + const storedPath = await state.get(POETRY_PATH_KEY); + if (storedPath) { + if (await fs.exists(untildify(storedPath))) { + poetryPath = storedPath; + traceInfo(`Using poetry from persistent state: ${poetryPath}`); + // Also retrieve the virtualenvs path if we haven't already + if (!poetryVirtualenvsPath) { + getPoetryVirtualenvsPath(untildify(poetryPath)).catch((e) => + traceError(`Error getting Poetry virtualenvs path: ${e}`), + ); + } + return untildify(poetryPath); } - return untildify(poetryPath); + await state.set(POETRY_PATH_KEY, undefined); } // try to get from settings const settingPath = getPoetryPathFromSettings(); if (settingPath) { - poetryPath = settingPath; - traceInfo(`Using poetry from settings: ${settingPath}`); - return poetryPath; + if (await fs.exists(untildify(settingPath))) { + poetryPath = settingPath; + traceInfo(`Using poetry from settings: ${settingPath}`); + return untildify(poetryPath); + } + traceInfo(`Poetry path from settings does not exist: ${settingPath}`); } // Check in standard PATH locations diff --git a/src/managers/pyenv/pyenvUtils.ts b/src/managers/pyenv/pyenvUtils.ts index 026d3f1a..079bf9d8 100644 --- a/src/managers/pyenv/pyenvUtils.ts +++ b/src/managers/pyenv/pyenvUtils.ts @@ -98,14 +98,21 @@ export async function setPyenvForWorkspaces(fsPath: string[], envPath: string | export async function getPyenv(native?: NativePythonFinder): Promise { if (pyenvPath) { - return pyenvPath; + if (await fs.exists(untildify(pyenvPath))) { + return untildify(pyenvPath); + } + pyenvPath = undefined; } const state = await getWorkspacePersistentState(); - pyenvPath = await state.get(PYENV_PATH_KEY); - if (pyenvPath) { - traceInfo(`Using pyenv from persistent state: ${pyenvPath}`); - return untildify(pyenvPath); + const storedPath = await state.get(PYENV_PATH_KEY); + if (storedPath) { + if (await fs.exists(untildify(storedPath))) { + pyenvPath = storedPath; + traceInfo(`Using pyenv from persistent state: ${pyenvPath}`); + return untildify(pyenvPath); + } + await state.set(PYENV_PATH_KEY, undefined); } const pyenvBin = isWindows() ? 'pyenv.exe' : 'pyenv'; From d4c5d6823066a2d65d6dc4266e100053aa48f5da Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Thu, 27 Nov 2025 18:42:03 -0800 Subject: [PATCH 2/2] fix: build --- src/managers/pipenv/pipenvUtils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/pipenv/pipenvUtils.ts b/src/managers/pipenv/pipenvUtils.ts index 9554c0f4..865ca8c4 100644 --- a/src/managers/pipenv/pipenvUtils.ts +++ b/src/managers/pipenv/pipenvUtils.ts @@ -1,5 +1,6 @@ // Utility functions for Pipenv environment management +import * as fs from 'fs-extra'; import * as path from 'path'; import { Uri } from 'vscode'; import which from 'which'; @@ -13,6 +14,7 @@ import { import { ENVS_EXTENSION_ID } from '../../common/constants'; import { traceError, traceInfo } from '../../common/logging'; import { getWorkspacePersistentState } from '../../common/persistentState'; +import { untildify } from '../../common/utils/pathUtils'; import { getSettingWorkspaceScope } from '../../features/settings/settingHelpers'; import { isNativeEnvInfo,