From 5ec37dabbd1db1ba2e37dbeb2aec4bf73c1f4fbd Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 13 Jun 2025 16:11:20 +1000 Subject: [PATCH 1/2] Hide progress messages when creating env or installing packages --- src/client/chat/createVirtualEnvTool.ts | 2 + src/client/chat/installPackagesTool.ts | 5 +- .../common/installer/moduleInstaller.ts | 2 +- src/client/common/installer/types.ts | 1 + .../provider/condaCreationProvider.ts | 83 +++++++++++-------- .../creation/provider/hideEnvCreation.ts | 21 +++++ .../creation/provider/venvCreationProvider.ts | 58 +++++++------ 7 files changed, 111 insertions(+), 61 deletions(-) create mode 100644 src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts diff --git a/src/client/chat/createVirtualEnvTool.ts b/src/client/chat/createVirtualEnvTool.ts index 42fa6ccfe45b..9bbcc466fe28 100644 --- a/src/client/chat/createVirtualEnvTool.ts +++ b/src/client/chat/createVirtualEnvTool.ts @@ -43,6 +43,7 @@ import { traceError, traceVerbose, traceWarn } from '../logging'; import { StopWatch } from '../common/utils/stopWatch'; import { useEnvExtension } from '../envExt/api.internal'; import { PythonEnvironment } from '../envExt/types'; +import { hideEnvCreation } from '../pythonEnvironments/creation/provider/hideEnvCreation'; interface ICreateVirtualEnvToolParams extends IResourceReference { packageList?: string[]; // Added only becausewe have ability to create a virtual env with list of packages same tool within the in Python Env extension. @@ -86,6 +87,7 @@ export class CreateVirtualEnvTool implements LanguageModelTool(IInterpreterPathService); const disposables = new DisposableStore(); try { + disposables.add(hideEnvCreation()); const interpreterChanged = new Promise((resolve) => { disposables.add(interpreterPathService.onDidChange(() => resolve())); }); diff --git a/src/client/chat/installPackagesTool.ts b/src/client/chat/installPackagesTool.ts index bd89dd8c26c7..e359fce110db 100644 --- a/src/client/chat/installPackagesTool.ts +++ b/src/client/chat/installPackagesTool.ts @@ -93,7 +93,10 @@ export class InstallPackagesTool implements LanguageModelTool(IApplicationShell); const options: ProgressOptions = { location: ProgressLocation.Notification, diff --git a/src/client/common/installer/types.ts b/src/client/common/installer/types.ts index 679b8b0ea668..a85017ff0092 100644 --- a/src/client/common/installer/types.ts +++ b/src/client/common/installer/types.ts @@ -83,4 +83,5 @@ export enum ModuleInstallFlags { export type InstallOptions = { installAsProcess?: boolean; + hideProgress?: boolean; }; diff --git a/src/client/pythonEnvironments/creation/provider/condaCreationProvider.ts b/src/client/pythonEnvironments/creation/provider/condaCreationProvider.ts index d923179fac73..a7e4e9a21cd1 100644 --- a/src/client/pythonEnvironments/creation/provider/condaCreationProvider.ts +++ b/src/client/pythonEnvironments/creation/provider/condaCreationProvider.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { CancellationToken, ProgressLocation, WorkspaceFolder } from 'vscode'; +import { CancellationToken, CancellationTokenSource, ProgressLocation, WorkspaceFolder } from 'vscode'; import * as path from 'path'; import { Commands, PVSC_EXTENSION_ID } from '../../../common/constants'; import { traceError, traceInfo, traceLog } from '../../../logging'; @@ -35,6 +35,8 @@ import { CreateEnvironmentResult, CreateEnvironmentProvider, } from '../proposed.createEnvApis'; +import { shouldDisplayEnvCreationProgress } from './hideEnvCreation'; +import { noop } from '../../../common/utils/misc'; function generateCommandArgs(version?: string, options?: CreateEnvironmentOptions): string[] { let addGitIgnore = true; @@ -261,6 +263,50 @@ async function createEnvironment(options?: CreateEnvironmentOptions): Promise { + progress.report({ + message: CreateEnv.statusStarting, + }); + + let envPath: string | undefined; + try { + sendTelemetryEvent(EventName.ENVIRONMENT_CREATING, undefined, { + environmentType: 'conda', + pythonVersion: version, + }); + if (workspace) { + envPath = await createCondaEnv( + workspace, + getExecutableCommand(conda), + generateCommandArgs(version, options), + progress, + token, + ); + + if (envPath) { + return { path: envPath, workspaceFolder: workspace }; + } + + throw new Error('Failed to create conda environment. See Output > Python for more info.'); + } else { + throw new Error('A workspace is needed to create conda environment'); + } + } catch (ex) { + traceError(ex); + showErrorMessageWithLogs(CreateEnv.Conda.errorCreatingEnvironment); + return { error: ex as Error }; + } + }; + + if (!shouldDisplayEnvCreationProgress()) { + const token = new CancellationTokenSource(); + try { + return await createEnvInternal({ report: noop }, token.token); + } finally { + token.dispose(); + } + } + return withProgress( { location: ProgressLocation.Notification, @@ -270,40 +316,7 @@ async function createEnvironment(options?: CreateEnvironmentOptions): Promise => { - progress.report({ - message: CreateEnv.statusStarting, - }); - - let envPath: string | undefined; - try { - sendTelemetryEvent(EventName.ENVIRONMENT_CREATING, undefined, { - environmentType: 'conda', - pythonVersion: version, - }); - if (workspace) { - envPath = await createCondaEnv( - workspace, - getExecutableCommand(conda), - generateCommandArgs(version, options), - progress, - token, - ); - - if (envPath) { - return { path: envPath, workspaceFolder: workspace }; - } - - throw new Error('Failed to create conda environment. See Output > Python for more info.'); - } else { - throw new Error('A workspace is needed to create conda environment'); - } - } catch (ex) { - traceError(ex); - showErrorMessageWithLogs(CreateEnv.Conda.errorCreatingEnvironment); - return { error: ex as Error }; - } - }, + ): Promise => createEnvInternal(progress, token), ); } diff --git a/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts b/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts new file mode 100644 index 000000000000..642575f4eaff --- /dev/null +++ b/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { Disposable } from 'vscode'; + +const envCreationTracker: Disposable[] = []; + +export function hideEnvCreation(): Disposable { + const disposable = new Disposable(() => { + const index = envCreationTracker.indexOf(disposable); + if (index > -1) { + envCreationTracker.splice(index, 1); + } + }); + envCreationTracker.push(disposable); + return disposable; +} + +export function shouldDisplayEnvCreationProgress(): boolean { + return envCreationTracker.length > 0; +} diff --git a/src/client/pythonEnvironments/creation/provider/venvCreationProvider.ts b/src/client/pythonEnvironments/creation/provider/venvCreationProvider.ts index 9f5d746d55ae..c5c82b85357f 100644 --- a/src/client/pythonEnvironments/creation/provider/venvCreationProvider.ts +++ b/src/client/pythonEnvironments/creation/provider/venvCreationProvider.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import * as os from 'os'; -import { CancellationToken, ProgressLocation, WorkspaceFolder } from 'vscode'; +import { CancellationToken, CancellationTokenSource, ProgressLocation, WorkspaceFolder } from 'vscode'; import { Commands, PVSC_EXTENSION_ID } from '../../../common/constants'; import { createVenvScript } from '../../../common/process/internal/scripts'; import { execObservable } from '../../../common/process/rawProcessApis'; @@ -31,6 +31,8 @@ import { CreateEnvironmentOptions, CreateEnvironmentResult, } from '../proposed.createEnvApis'; +import { shouldDisplayEnvCreationProgress } from './hideEnvCreation'; +import { noop } from '../../../common/utils/misc'; interface IVenvCommandArgs { argv: string[]; @@ -333,6 +335,36 @@ export class VenvCreationProvider implements CreateEnvironmentProvider { } const args = generateCommandArgs(installInfo, addGitIgnore); + const createEnvInternal = async (progress: CreateEnvironmentProgress, token: CancellationToken) => { + progress.report({ + message: CreateEnv.statusStarting, + }); + + let envPath: string | undefined; + try { + if (interpreter && workspace) { + envPath = await createVenv(workspace, interpreter, args, progress, token); + if (envPath) { + return { path: envPath, workspaceFolder: workspace }; + } + throw new Error('Failed to create virtual environment. See Output > Python for more info.'); + } + throw new Error('Failed to create virtual environment. Either interpreter or workspace is undefined.'); + } catch (ex) { + traceError(ex); + showErrorMessageWithLogs(CreateEnv.Venv.errorCreatingEnvironment); + return { error: ex as Error }; + } + }; + + if (!shouldDisplayEnvCreationProgress()) { + const token = new CancellationTokenSource(); + try { + return await createEnvInternal({ report: noop }, token.token); + } finally { + token.dispose(); + } + } return withProgress( { @@ -343,29 +375,7 @@ export class VenvCreationProvider implements CreateEnvironmentProvider { async ( progress: CreateEnvironmentProgress, token: CancellationToken, - ): Promise => { - progress.report({ - message: CreateEnv.statusStarting, - }); - - let envPath: string | undefined; - try { - if (interpreter && workspace) { - envPath = await createVenv(workspace, interpreter, args, progress, token); - if (envPath) { - return { path: envPath, workspaceFolder: workspace }; - } - throw new Error('Failed to create virtual environment. See Output > Python for more info.'); - } - throw new Error( - 'Failed to create virtual environment. Either interpreter or workspace is undefined.', - ); - } catch (ex) { - traceError(ex); - showErrorMessageWithLogs(CreateEnv.Venv.errorCreatingEnvironment); - return { error: ex as Error }; - } - }, + ): Promise => createEnvInternal(progress, token), ); } From 11249d30a756bd17ed70b825be18475c7ed795ae Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 13 Jun 2025 17:05:38 +1000 Subject: [PATCH 2/2] Updates --- .../pythonEnvironments/creation/provider/hideEnvCreation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts b/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts index 642575f4eaff..5c29a8d7128d 100644 --- a/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts +++ b/src/client/pythonEnvironments/creation/provider/hideEnvCreation.ts @@ -17,5 +17,5 @@ export function hideEnvCreation(): Disposable { } export function shouldDisplayEnvCreationProgress(): boolean { - return envCreationTracker.length > 0; + return envCreationTracker.length === 0; }