From 1723072bf209947f3f99f3cef96be5a6074a736c Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:33:32 -0700 Subject: [PATCH 1/5] add handling for notebook-cells as inputs to API --- src/features/pythonApi.ts | 90 ++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 11 deletions(-) diff --git a/src/features/pythonApi.ts b/src/features/pythonApi.ts index 092c8187..5bd7eba5 100644 --- a/src/features/pythonApi.ts +++ b/src/features/pythonApi.ts @@ -171,32 +171,84 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { await Promise.all(this.envManagers.managers.map((manager) => manager.refresh(scope))); return Promise.resolve(); } - const manager = this.envManagers.getEnvironmentManager(scope); + let currentScope: GetEnvironmentScope = scope; + if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { + currentScope = Uri.from({ + scheme: 'vscode-notebook', + path: scope.path, + authority: scope.authority, + }); + } + const manager = this.envManagers.getEnvironmentManager(currentScope); if (!manager) { - return Promise.reject(new Error(`No environment manager found for: ${scope.fsPath}`)); + return Promise.reject(new Error(`No environment manager found for: ${currentScope.fsPath}`)); } - return manager.refresh(scope); + return manager.refresh(currentScope); } async getEnvironments(scope: GetEnvironmentsScope): Promise { - if (scope === 'all' || scope === 'global') { - const promises = this.envManagers.managers.map((manager) => manager.getEnvironments(scope)); + let currentScope: GetEnvironmentsScope = scope; + if (currentScope instanceof Uri && currentScope.scheme === 'vscode-notebook-cell') { + currentScope = Uri.from({ + scheme: 'vscode-notebook', + path: currentScope.path, + authority: currentScope.authority, + }); + } + if (currentScope === 'all' || currentScope === 'global') { + const promises = this.envManagers.managers.map((manager) => manager.getEnvironments(currentScope)); const items = await Promise.all(promises); return items.flat(); } - const manager = this.envManagers.getEnvironmentManager(scope); + const manager = this.envManagers.getEnvironmentManager(currentScope); if (!manager) { return []; } - const items = await manager.getEnvironments(scope); + const items = await manager.getEnvironments(currentScope); return items; } onDidChangeEnvironments: Event = this._onDidChangeEnvironments.event; setEnvironment(scope: SetEnvironmentScope, environment?: PythonEnvironment): Promise { - return this.envManagers.setEnvironment(scope, environment); + let currentScope: SetEnvironmentScope = scope; + if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { + currentScope = Uri.from({ + scheme: 'vscode-notebook', + path: scope.path, + authority: scope.authority, + }); + } + + if (Array.isArray(scope) && scope.length > 0) { + // if scope is an array of Uri, go through each item and check if it is a notebook cell Uri + // if it is, convert it to notebook Uri and push all items to the currentScope + currentScope = []; + for (const s of scope) { + if (s instanceof Uri && s.scheme === 'vscode-notebook-cell') { + currentScope.push( + Uri.from({ + scheme: 'vscode-notebook', + path: s.path, + authority: s.authority, + }), + ); + } else { + currentScope.push(s); + } + } + } + + return this.envManagers.setEnvironment(currentScope, environment); } async getEnvironment(scope: GetEnvironmentScope): Promise { - return this.envManagers.getEnvironment(scope); + let currentScope: GetEnvironmentScope = scope; + if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { + currentScope = Uri.from({ + scheme: 'vscode-notebook', + path: scope.path, + authority: scope.authority, + }); + } + return this.envManagers.getEnvironment(currentScope); } onDidChangeEnvironment: Event = this._onDidChangeEnvironment.event; async resolveEnvironment(context: ResolveEnvironmentContext): Promise { @@ -267,7 +319,15 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { } onDidChangePythonProjects: Event = this._onDidChangePythonProjects.event; getPythonProject(uri: Uri): PythonProject | undefined { - return this.projectManager.get(uri); + let currentUri: GetEnvironmentScope = uri; + if (uri.scheme === 'vscode-notebook-cell') { + currentUri = Uri.from({ + scheme: 'vscode-notebook', + path: uri.path, + authority: uri.authority, + }); + } + return this.projectManager.get(currentUri); } registerPythonProjectCreator(creator: PythonProjectCreator): Disposable { return this.projectCreators.registerPythonProjectCreator(creator); @@ -310,7 +370,15 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { overrides?: ({ [key: string]: string | undefined } | Uri)[], baseEnvVar?: { [key: string]: string | undefined }, ): Promise<{ [key: string]: string | undefined }> { - return this.envVarManager.getEnvironmentVariables(uri, overrides, baseEnvVar); + let currentUri: GetEnvironmentScope = uri; + if (uri.scheme === 'vscode-notebook-cell') { + currentUri = Uri.from({ + scheme: 'vscode-notebook', + path: uri.path, + authority: uri.authority, + }); + } + return this.envVarManager.getEnvironmentVariables(currentUri, overrides, baseEnvVar); } } From b1a70a2e506c976a555eebdfc124bf7452c6d6ad Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 11 Apr 2025 11:58:39 -0700 Subject: [PATCH 2/5] remove duplication --- src/common/utils/pathUtils.ts | 12 +++++++++ src/features/pythonApi.ts | 47 ++++++++--------------------------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/common/utils/pathUtils.ts b/src/common/utils/pathUtils.ts index 09a3ef29..cf7aee1a 100644 --- a/src/common/utils/pathUtils.ts +++ b/src/common/utils/pathUtils.ts @@ -1,5 +1,17 @@ +import { Uri } from 'vscode'; import { isWindows } from '../../managers/common/utils'; +export function convertNotebookCellUriToNotebookUri(uri: Uri): Uri { + if (uri.scheme === 'vscode-notebook-cell') { + return Uri.from({ + scheme: 'vscode-notebook', + path: uri.path, + authority: uri.authority, + }); + } + return uri; +} + export function normalizePath(path: string): string { const path1 = path.replace(/\\/g, '/'); if (isWindows()) { diff --git a/src/features/pythonApi.ts b/src/features/pythonApi.ts index 5bd7eba5..a636a22c 100644 --- a/src/features/pythonApi.ts +++ b/src/features/pythonApi.ts @@ -47,6 +47,7 @@ import { runAsTask } from './execution/runAsTask'; import { runInTerminal } from './terminal/runInTerminal'; import { runInBackground } from './execution/runInBackground'; import { EnvVarManager } from './execution/envVariableManager'; +import { convertNotebookCellUriToNotebookUri } from '../common/utils/pathUtils'; class PythonEnvironmentApiImpl implements PythonEnvironmentApi { private readonly _onDidChangeEnvironments = new EventEmitter(); @@ -209,32 +210,16 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { } onDidChangeEnvironments: Event = this._onDidChangeEnvironments.event; setEnvironment(scope: SetEnvironmentScope, environment?: PythonEnvironment): Promise { - let currentScope: SetEnvironmentScope = scope; + let currentScope = scope; + if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { - currentScope = Uri.from({ - scheme: 'vscode-notebook', - path: scope.path, - authority: scope.authority, - }); + currentScope = convertNotebookCellUriToNotebookUri(scope); } if (Array.isArray(scope) && scope.length > 0) { - // if scope is an array of Uri, go through each item and check if it is a notebook cell Uri - // if it is, convert it to notebook Uri and push all items to the currentScope - currentScope = []; - for (const s of scope) { - if (s instanceof Uri && s.scheme === 'vscode-notebook-cell') { - currentScope.push( - Uri.from({ - scheme: 'vscode-notebook', - path: s.path, - authority: s.authority, - }), - ); - } else { - currentScope.push(s); - } - } + currentScope = scope.map((s) => + s instanceof Uri && s.scheme === 'vscode-notebook-cell' ? convertNotebookCellUriToNotebookUri(s) : s, + ); } return this.envManagers.setEnvironment(currentScope, environment); @@ -242,11 +227,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { async getEnvironment(scope: GetEnvironmentScope): Promise { let currentScope: GetEnvironmentScope = scope; if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { - currentScope = Uri.from({ - scheme: 'vscode-notebook', - path: scope.path, - authority: scope.authority, - }); + currentScope = convertNotebookCellUriToNotebookUri(scope); } return this.envManagers.getEnvironment(currentScope); } @@ -321,11 +302,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { getPythonProject(uri: Uri): PythonProject | undefined { let currentUri: GetEnvironmentScope = uri; if (uri.scheme === 'vscode-notebook-cell') { - currentUri = Uri.from({ - scheme: 'vscode-notebook', - path: uri.path, - authority: uri.authority, - }); + currentUri = convertNotebookCellUriToNotebookUri(uri); } return this.projectManager.get(currentUri); } @@ -372,11 +349,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { ): Promise<{ [key: string]: string | undefined }> { let currentUri: GetEnvironmentScope = uri; if (uri.scheme === 'vscode-notebook-cell') { - currentUri = Uri.from({ - scheme: 'vscode-notebook', - path: uri.path, - authority: uri.authority, - }); + currentUri = convertNotebookCellUriToNotebookUri(uri); } return this.envVarManager.getEnvironmentVariables(currentUri, overrides, baseEnvVar); } From b7c5b66357c567b04489f0216ac53f23dce1adec Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 11 Apr 2025 12:07:59 -0700 Subject: [PATCH 3/5] update util function --- src/common/utils/pathUtils.ts | 14 +++++++------- src/features/pythonApi.ts | 23 +++++------------------ 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/common/utils/pathUtils.ts b/src/common/utils/pathUtils.ts index cf7aee1a..579824a5 100644 --- a/src/common/utils/pathUtils.ts +++ b/src/common/utils/pathUtils.ts @@ -2,14 +2,14 @@ import { Uri } from 'vscode'; import { isWindows } from '../../managers/common/utils'; export function convertNotebookCellUriToNotebookUri(uri: Uri): Uri { - if (uri.scheme === 'vscode-notebook-cell') { - return Uri.from({ - scheme: 'vscode-notebook', - path: uri.path, - authority: uri.authority, - }); + if (uri.scheme !== 'vscode-notebook-cell') { + throw new Error('URI is not of scheme vscode-notebook-cell'); } - return uri; + return Uri.from({ + scheme: 'vscode-notebook', + path: uri.path, + authority: uri.authority, + }); } export function normalizePath(path: string): string { diff --git a/src/features/pythonApi.ts b/src/features/pythonApi.ts index a636a22c..d4ddca5c 100644 --- a/src/features/pythonApi.ts +++ b/src/features/pythonApi.ts @@ -174,11 +174,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { } let currentScope: GetEnvironmentScope = scope; if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { - currentScope = Uri.from({ - scheme: 'vscode-notebook', - path: scope.path, - authority: scope.authority, - }); + currentScope = convertNotebookCellUriToNotebookUri(scope); } const manager = this.envManagers.getEnvironmentManager(currentScope); if (!manager) { @@ -189,11 +185,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { async getEnvironments(scope: GetEnvironmentsScope): Promise { let currentScope: GetEnvironmentsScope = scope; if (currentScope instanceof Uri && currentScope.scheme === 'vscode-notebook-cell') { - currentScope = Uri.from({ - scheme: 'vscode-notebook', - path: currentScope.path, - authority: currentScope.authority, - }); + currentScope = convertNotebookCellUriToNotebookUri(currentScope); } if (currentScope === 'all' || currentScope === 'global') { const promises = this.envManagers.managers.map((manager) => manager.getEnvironments(currentScope)); @@ -300,10 +292,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { } onDidChangePythonProjects: Event = this._onDidChangePythonProjects.event; getPythonProject(uri: Uri): PythonProject | undefined { - let currentUri: GetEnvironmentScope = uri; - if (uri.scheme === 'vscode-notebook-cell') { - currentUri = convertNotebookCellUriToNotebookUri(uri); - } + let currentUri = uri.scheme === 'vscode-notebook-cell' ? convertNotebookCellUriToNotebookUri(uri) : uri; return this.projectManager.get(currentUri); } registerPythonProjectCreator(creator: PythonProjectCreator): Disposable { @@ -347,10 +336,8 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { overrides?: ({ [key: string]: string | undefined } | Uri)[], baseEnvVar?: { [key: string]: string | undefined }, ): Promise<{ [key: string]: string | undefined }> { - let currentUri: GetEnvironmentScope = uri; - if (uri.scheme === 'vscode-notebook-cell') { - currentUri = convertNotebookCellUriToNotebookUri(uri); - } + let currentUri: GetEnvironmentScope = + uri.scheme === 'vscode-notebook-cell' ? convertNotebookCellUriToNotebookUri(uri) : uri; return this.envVarManager.getEnvironmentVariables(currentUri, overrides, baseEnvVar); } } From 8664dcd7ea705d60728cda05bf1052ad0fb7bbe0 Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 11 Apr 2025 12:33:15 -0700 Subject: [PATCH 4/5] simplify checkUri further --- src/common/utils/pathUtils.ts | 23 ++++++++++++------- src/features/pythonApi.ts | 42 ++++++++--------------------------- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/src/common/utils/pathUtils.ts b/src/common/utils/pathUtils.ts index 579824a5..81b6152b 100644 --- a/src/common/utils/pathUtils.ts +++ b/src/common/utils/pathUtils.ts @@ -1,15 +1,22 @@ import { Uri } from 'vscode'; import { isWindows } from '../../managers/common/utils'; -export function convertNotebookCellUriToNotebookUri(uri: Uri): Uri { - if (uri.scheme !== 'vscode-notebook-cell') { - throw new Error('URI is not of scheme vscode-notebook-cell'); +export function checkUri(scope?: Uri | Uri[] | string): Uri | Uri[] | string | undefined { + if (scope instanceof Uri) { + if (scope.scheme === 'vscode-notebook-cell') { + return Uri.from({ + scheme: 'vscode-notebook', + path: scope.path, + authority: scope.authority, + }); + } } - return Uri.from({ - scheme: 'vscode-notebook', - path: uri.path, - authority: uri.authority, - }); + if (Array.isArray(scope)) { + return scope.map((item) => { + return checkUri(item) as Uri; + }); + } + return scope; } export function normalizePath(path: string): string { diff --git a/src/features/pythonApi.ts b/src/features/pythonApi.ts index d4ddca5c..319c2a72 100644 --- a/src/features/pythonApi.ts +++ b/src/features/pythonApi.ts @@ -47,7 +47,7 @@ import { runAsTask } from './execution/runAsTask'; import { runInTerminal } from './terminal/runInTerminal'; import { runInBackground } from './execution/runInBackground'; import { EnvVarManager } from './execution/envVariableManager'; -import { convertNotebookCellUriToNotebookUri } from '../common/utils/pathUtils'; +import { checkUri } from '../common/utils/pathUtils'; class PythonEnvironmentApiImpl implements PythonEnvironmentApi { private readonly _onDidChangeEnvironments = new EventEmitter(); @@ -168,14 +168,12 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { return manager.remove(environment); } async refreshEnvironments(scope: RefreshEnvironmentsScope): Promise { - if (scope === undefined) { + let currentScope = checkUri(scope) as RefreshEnvironmentsScope; + + if (currentScope === undefined) { await Promise.all(this.envManagers.managers.map((manager) => manager.refresh(scope))); return Promise.resolve(); } - let currentScope: GetEnvironmentScope = scope; - if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { - currentScope = convertNotebookCellUriToNotebookUri(scope); - } const manager = this.envManagers.getEnvironmentManager(currentScope); if (!manager) { return Promise.reject(new Error(`No environment manager found for: ${currentScope.fsPath}`)); @@ -183,10 +181,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { return manager.refresh(currentScope); } async getEnvironments(scope: GetEnvironmentsScope): Promise { - let currentScope: GetEnvironmentsScope = scope; - if (currentScope instanceof Uri && currentScope.scheme === 'vscode-notebook-cell') { - currentScope = convertNotebookCellUriToNotebookUri(currentScope); - } + let currentScope = checkUri(scope) as GetEnvironmentsScope; if (currentScope === 'all' || currentScope === 'global') { const promises = this.envManagers.managers.map((manager) => manager.getEnvironments(currentScope)); const items = await Promise.all(promises); @@ -202,26 +197,10 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { } onDidChangeEnvironments: Event = this._onDidChangeEnvironments.event; setEnvironment(scope: SetEnvironmentScope, environment?: PythonEnvironment): Promise { - let currentScope = scope; - - if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { - currentScope = convertNotebookCellUriToNotebookUri(scope); - } - - if (Array.isArray(scope) && scope.length > 0) { - currentScope = scope.map((s) => - s instanceof Uri && s.scheme === 'vscode-notebook-cell' ? convertNotebookCellUriToNotebookUri(s) : s, - ); - } - - return this.envManagers.setEnvironment(currentScope, environment); + return this.envManagers.setEnvironment(checkUri(scope) as SetEnvironmentScope, environment); } async getEnvironment(scope: GetEnvironmentScope): Promise { - let currentScope: GetEnvironmentScope = scope; - if (scope instanceof Uri && scope.scheme === 'vscode-notebook-cell') { - currentScope = convertNotebookCellUriToNotebookUri(scope); - } - return this.envManagers.getEnvironment(currentScope); + return this.envManagers.getEnvironment(checkUri(scope) as GetEnvironmentScope); } onDidChangeEnvironment: Event = this._onDidChangeEnvironment.event; async resolveEnvironment(context: ResolveEnvironmentContext): Promise { @@ -292,8 +271,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { } onDidChangePythonProjects: Event = this._onDidChangePythonProjects.event; getPythonProject(uri: Uri): PythonProject | undefined { - let currentUri = uri.scheme === 'vscode-notebook-cell' ? convertNotebookCellUriToNotebookUri(uri) : uri; - return this.projectManager.get(currentUri); + return this.projectManager.get(checkUri(uri) as Uri); } registerPythonProjectCreator(creator: PythonProjectCreator): Disposable { return this.projectCreators.registerPythonProjectCreator(creator); @@ -336,9 +314,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { overrides?: ({ [key: string]: string | undefined } | Uri)[], baseEnvVar?: { [key: string]: string | undefined }, ): Promise<{ [key: string]: string | undefined }> { - let currentUri: GetEnvironmentScope = - uri.scheme === 'vscode-notebook-cell' ? convertNotebookCellUriToNotebookUri(uri) : uri; - return this.envVarManager.getEnvironmentVariables(currentUri, overrides, baseEnvVar); + return this.envVarManager.getEnvironmentVariables(checkUri(uri) as Uri, overrides, baseEnvVar); } } From c4d36fd155bfcd635b239ebd9ae3311c288f3ee2 Mon Sep 17 00:00:00 2001 From: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com> Date: Fri, 11 Apr 2025 12:34:58 -0700 Subject: [PATCH 5/5] minor fix --- src/features/pythonApi.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/pythonApi.ts b/src/features/pythonApi.ts index 319c2a72..e712a4cd 100644 --- a/src/features/pythonApi.ts +++ b/src/features/pythonApi.ts @@ -168,10 +168,10 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { return manager.remove(environment); } async refreshEnvironments(scope: RefreshEnvironmentsScope): Promise { - let currentScope = checkUri(scope) as RefreshEnvironmentsScope; + const currentScope = checkUri(scope) as RefreshEnvironmentsScope; if (currentScope === undefined) { - await Promise.all(this.envManagers.managers.map((manager) => manager.refresh(scope))); + await Promise.all(this.envManagers.managers.map((manager) => manager.refresh(currentScope))); return Promise.resolve(); } const manager = this.envManagers.getEnvironmentManager(currentScope); @@ -181,7 +181,7 @@ class PythonEnvironmentApiImpl implements PythonEnvironmentApi { return manager.refresh(currentScope); } async getEnvironments(scope: GetEnvironmentsScope): Promise { - let currentScope = checkUri(scope) as GetEnvironmentsScope; + const currentScope = checkUri(scope) as GetEnvironmentsScope; if (currentScope === 'all' || currentScope === 'global') { const promises = this.envManagers.managers.map((manager) => manager.getEnvironments(currentScope)); const items = await Promise.all(promises);