From 7262cbc2d9d0d4937e3550547761f9b9ca6e08d0 Mon Sep 17 00:00:00 2001 From: Arnaud Schoonjans Date: Tue, 12 Dec 2023 10:33:48 +0100 Subject: [PATCH 1/2] Add workaround for bug in getExecutionDetails() method of the python extension --- src/python_extension.ts | 41 ++++++++++++++++++++++++++++++++++++++--- src/test/runTest.ts | 2 +- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/python_extension.ts b/src/python_extension.ts index 6519ba732..6456943c5 100644 --- a/src/python_extension.ts +++ b/src/python_extension.ts @@ -4,6 +4,7 @@ import { StatusBarAlignment, ThemeColor, window, workspace, TextDocument, Worksp import { IExtensionApi, Resource } from './types'; import { fileOrDirectoryExists, log, getOuterMostWorkspaceFolder, logMap} from './utils'; import { getLanguageMap, getLastActiveFolder} from './extension'; +import * as fs from "fs"; export const PYTHONEXTENSIONID = "ms-python.python"; @@ -31,13 +32,45 @@ export class PythonExtension { * @returns {string} A string representing the path to the Python interpreter. */ get pythonPath(): string { - return this.executionDetails.execCommand[0]; + return PythonExtension.getPathPythonBinary(this.executionDetails.execCommand[0]); } get virtualEnvName(): string | null { return this.pythonPathToEnvName(this.pythonPath); } + + /** + * Due to bug https://github.com/microsoft/vscode-python/issues/22617, the `this.pythonApi.settings.getExecutionDetails()` method + * might return the path to the root of the venv instead of the path to the python binary in that venv. This method exists to work + * around that issue. + */ + private static getPathPythonBinary(execCommand: string): string { + if(PythonExtension.isFile(execCommand)){ + return execCommand; + } + for(const pythonSuffix of ["python3", "python"]){ + const execCommandWithSuffix = execCommand + "/bin/" + pythonSuffix; + if(PythonExtension.isFile(execCommandWithSuffix)){ + return execCommandWithSuffix + } + } + throw new Error(`Failed to find python binary ${execCommand}`); + } + + + /** + * @returns {boolean} True iff the given path references a file (or symbolic link to file). + */ + private static isFile(path: string): boolean { + try{ + const stat = fs.statSync(path); + return stat.isFile(); + } catch(err){ + return false; + } + } + pythonPathToEnvName(path: string) : string { /** * Match the virtual environment name using a regular expression to transform @@ -141,7 +174,8 @@ export class PythonExtension { getPathForResource(resource) { try{ - return this.pythonApi.settings.getExecutionDetails(resource).execCommand[0]; + const execDetails = this.pythonApi.settings.getExecutionDetails(resource); + return PythonExtension.getPathPythonBinary(execDetails.execCommand[0]); } catch (error){ console.error(`Failed to getPathForResource :` + error.name + error.message); } @@ -160,8 +194,9 @@ export class PythonExtension { if(this.executionDetails.execCommand[0] !== newExecutionDetails.execCommand[0]){ this.executionDetails = newExecutionDetails; + const newPathPythonBinary = PythonExtension.getPathPythonBinary(newExecutionDetails.execCommand[0]); for (const callback of this.callBacksOnchange) { - callback(newExecutionDetails.execCommand[0], outermost); + callback(newPathPythonBinary, outermost); } } } diff --git a/src/test/runTest.ts b/src/test/runTest.ts index 86b3af76b..4561563e5 100644 --- a/src/test/runTest.ts +++ b/src/test/runTest.ts @@ -40,7 +40,7 @@ async function main() { const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); const cliPath = resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath, "linux-x64"); - cp.spawnSync(cliPath, ['--install-extension', 'ms-python.python'], { + cp.spawnSync(cliPath, ['--install-extension', 'ms-python.python', '--force'], { encoding: 'utf-8', stdio: 'inherit' }); From e5a5bda8bf52ee4f1c280fc49ad885a5ef174277 Mon Sep 17 00:00:00 2001 From: Arnaud Schoonjans Date: Tue, 12 Dec 2023 10:37:28 +0100 Subject: [PATCH 2/2] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 062006962..d2da8f49b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # v 1.5.0 (?) Changes in this release: - Drop support for iso4/iso5 +- Add workaround for bug in the python extension where `getExecutionDetails().execCommand[0]` returns the path to the root of the venv instead of the path to the python binary in that venv. # v 1.4.0 (2023-06-06) Changes in this release: