Skip to content

Commit 7cf7ec4

Browse files
authored
Changes to kernel picker (#9113)
* Changes to display of kernel picker * Fix tests * Fixes
1 parent 946778b commit 7cf7ec4

File tree

8 files changed

+55
-41
lines changed

8 files changed

+55
-41
lines changed

src/client/datascience/datascience.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { hasCells } from './cellFactory';
2222
import { Commands, EditorContexts, Settings, Telemetry } from './constants';
2323
import { createRemoteConnectionInfo } from './jupyter/jupyterUtils';
2424
import { KernelSelector, KernelSpecInterpreter } from './jupyter/kernels/kernelSelector';
25-
import { ICodeWatcher, IConnection, IDataScience, IDataScienceCodeLensProvider, IDataScienceCommandListener, IJupyterSessionManagerFactory, INotebookEditorProvider } from './types';
25+
import { ICodeWatcher, IConnection, IDataScience, IDataScienceCodeLensProvider, IDataScienceCommandListener, IJupyterKernel, IJupyterKernelSpec, IJupyterSessionManagerFactory, INotebookEditorProvider } from './types';
2626

2727
interface ISelectUriQuickPickItem extends vscode.QuickPickItem {
2828
newChoice: boolean;
@@ -227,14 +227,14 @@ export class DataScience implements IDataScience {
227227
}
228228

229229
@captureTelemetry(Telemetry.SelectLocalJupyterKernel)
230-
public async selectLocalJupyterKernel(): Promise<KernelSpecInterpreter> {
231-
return this.kernelSelector.selectLocalKernel();
230+
public async selectLocalJupyterKernel(currentKernel?: IJupyterKernelSpec | IJupyterKernel & Partial<IJupyterKernelSpec>): Promise<KernelSpecInterpreter> {
231+
return this.kernelSelector.selectLocalKernel(undefined, undefined, currentKernel);
232232
}
233233

234234
@captureTelemetry(Telemetry.SelectRemoteJupyuterKernel)
235-
public async selectRemoteJupyterKernel(connInfo: IConnection): Promise<KernelSpecInterpreter> {
235+
public async selectRemoteJupyterKernel(connInfo: IConnection, currentKernel?: IJupyterKernelSpec | IJupyterKernel & Partial<IJupyterKernelSpec>): Promise<KernelSpecInterpreter> {
236236
const session = await this.jupyterSessionManagerFactory.create(connInfo);
237-
return this.kernelSelector.selectRemoteKernel(session);
237+
return this.kernelSelector.selectRemoteKernel(session, undefined, currentKernel);
238238
}
239239

240240
public async debugCell(file: string, startLine: number, startChar: number, endLine: number, endChar: number): Promise<void> {

src/client/datascience/interactive-common/interactiveBase.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,12 +1290,12 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
12901290
let kernel: KernelSpecInterpreter | undefined;
12911291

12921292
if (settings.datascience.jupyterServerURI.toLowerCase() === Settings.JupyterServerLocalLaunch) {
1293-
kernel = await this.dataScience.selectLocalJupyterKernel();
1293+
kernel = await this.dataScience.selectLocalJupyterKernel(this.notebook?.getKernelSpec());
12941294
} else if (this.notebook) {
12951295
const connInfo = this.notebook.server.getConnectionInfo();
1296-
1296+
const currentKernel = this.notebook.getKernelSpec();
12971297
if (connInfo) {
1298-
kernel = await this.dataScience.selectRemoteJupyterKernel(connInfo);
1298+
kernel = await this.dataScience.selectRemoteJupyterKernel(connInfo, currentKernel);
12991299
}
13001300
}
13011301

src/client/datascience/jupyter/jupyterServer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ export class JupyterServerBase implements INotebookServer {
6060
// Try creating a session just to ensure we're connected. Callers of this function check to make sure jupyter
6161
// is running and connectable.
6262
let session: IJupyterSession | undefined;
63-
// tslint:disable-next-line: no-any
64-
session = await this.sessionManager.startNew(launchInfo.kernelSpec as any, cancelToken);
63+
session = await this.sessionManager.startNew(launchInfo.kernelSpec, cancelToken);
6564
const idleTimeout = this.configService.getSettings().datascience.jupyterLaunchTimeout;
6665
// The wait for idle should throw if we can't connect.
6766
await session.waitForIdle(idleTimeout);

src/client/datascience/jupyter/kernels/kernelSelections.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { inject, injectable } from 'inversify';
77
import { CancellationToken } from 'vscode';
88
import { PYTHON_LANGUAGE } from '../../../common/constants';
99
import { IFileSystem } from '../../../common/platform/types';
10+
import { IPathUtils } from '../../../common/types';
1011
import * as localize from '../../../common/utils/localize';
1112
import { IInterpreterSelector } from '../../../interpreter/configuration/types';
1213
import { IJupyterKernel, IJupyterKernelSpec, IJupyterSessionManager } from '../../types';
@@ -22,9 +23,11 @@ import { IKernelSelectionListProvider, IKernelSpecQuickPickItem } from './types'
2223
* @param {IJupyterKernelSpec} kernelSpec
2324
* @returns {IKernelSpecQuickPickItem}
2425
*/
25-
function getQuickPickItemForKernelSpec(kernelSpec: IJupyterKernelSpec): IKernelSpecQuickPickItem {
26+
function getQuickPickItemForKernelSpec(kernelSpec: IJupyterKernelSpec, pathUtils: IPathUtils): IKernelSpecQuickPickItem {
2627
return {
2728
label: kernelSpec.display_name,
29+
// If we have a matching interpreter, then display that path in the dropdown else path of the kernelspec.
30+
detail: pathUtils.getDisplayName(kernelSpec.metadata?.interpreter?.path || kernelSpec.path),
2831
selection: { kernelModel: undefined, kernelSpec: kernelSpec, interpreter: undefined }
2932
};
3033
}
@@ -35,9 +38,12 @@ function getQuickPickItemForKernelSpec(kernelSpec: IJupyterKernelSpec): IKernelS
3538
* @param {(IJupyterKernel & Partial<IJupyterKernelSpec>)} kernel
3639
* @returns {IKernelSpecQuickPickItem}
3740
*/
38-
function getQuickPickItemForActiveKernel(kernel: IJupyterKernel & Partial<IJupyterKernelSpec>): IKernelSpecQuickPickItem {
41+
function getQuickPickItemForActiveKernel(kernel: IJupyterKernel & Partial<IJupyterKernelSpec>, pathUtils: IPathUtils): IKernelSpecQuickPickItem {
42+
const path = kernel.metadata?.interpreter?.path || kernel.path;
3943
return {
4044
label: kernel.display_name || kernel.name || '',
45+
// If we have a matching interpreter, then display that path in the dropdown else path of the kernelspec.
46+
detail: path ? pathUtils.getDisplayName(path) : '',
4147
description: localize.DataScience.jupyterSelectURIRunningDetailFormat().format(kernel.lastActivityTime.toLocaleString(), kernel.numberOfConnections.toString()),
4248
selection: { kernelModel: kernel, kernelSpec: undefined, interpreter: undefined }
4349
};
@@ -51,7 +57,7 @@ function getQuickPickItemForActiveKernel(kernel: IJupyterKernel & Partial<IJupyt
5157
* @implements {IKernelSelectionListProvider}
5258
*/
5359
export class ActiveJupyterSessionKernelSelectionListProvider implements IKernelSelectionListProvider {
54-
constructor(private readonly sessionManager: IJupyterSessionManager) {}
60+
constructor(private readonly sessionManager: IJupyterSessionManager, private readonly pathUtils: IPathUtils) {}
5561
public async getKernelSelections(_cancelToken?: CancellationToken | undefined): Promise<IKernelSpecQuickPickItem[]> {
5662
const [activeKernels, kernelSpecs] = await Promise.all([this.sessionManager.getRunningKernels(), this.sessionManager.getKernelSpecs()]);
5763
const items = activeKernels.map(item => {
@@ -64,7 +70,7 @@ export class ActiveJupyterSessionKernelSelectionListProvider implements IKernelS
6470
return items
6571
.filter(item => item.display_name || item.name)
6672
.filter(item => (item.language || '').toLowerCase() === PYTHON_LANGUAGE.toLowerCase())
67-
.map(getQuickPickItemForActiveKernel);
73+
.map(item => getQuickPickItemForActiveKernel(item, this.pathUtils));
6874
}
6975
}
7076

@@ -76,13 +82,13 @@ export class ActiveJupyterSessionKernelSelectionListProvider implements IKernelS
7682
* @implements {IKernelSelectionListProvider}
7783
*/
7884
export class InstalledJupyterKernelSelectionListProvider implements IKernelSelectionListProvider {
79-
constructor(private readonly kernelService: KernelService, private readonly sessionManager?: IJupyterSessionManager) {}
85+
constructor(private readonly kernelService: KernelService, private readonly pathUtils: IPathUtils, private readonly sessionManager?: IJupyterSessionManager) {}
8086
public async getKernelSelections(cancelToken?: CancellationToken | undefined): Promise<IKernelSpecQuickPickItem[]> {
8187
const items = await this.kernelService.getKernelSpecs(this.sessionManager, cancelToken);
8288
return items
8389
.filter(item => (item.language || '').toLowerCase() === PYTHON_LANGUAGE.toLowerCase())
84-
.map(getQuickPickItemForKernelSpec);
85-
}
90+
.map(item => getQuickPickItemForKernelSpec(item, this.pathUtils));
91+
}
8692
}
8793

8894
/**
@@ -100,8 +106,7 @@ export class InterpreterKernelSelectionListProvider implements IKernelSelectionL
100106
return items.map(item => {
101107
return {
102108
...item,
103-
// We don't want details & descriptions.
104-
detail: '',
109+
// We don't want descriptions.
105110
description: '',
106111
selection: { kernelModel: undefined, interpreter: item.interpreter, kernelSpec: undefined }
107112
};
@@ -122,7 +127,8 @@ export class KernelSelectionProvider {
122127
constructor(
123128
@inject(KernelService) private readonly kernelService: KernelService,
124129
@inject(IInterpreterSelector) private readonly interpreterSelector: IInterpreterSelector,
125-
@inject(IFileSystem) private readonly fileSystem: IFileSystem) {}
130+
@inject(IFileSystem) private readonly fileSystem: IFileSystem,
131+
@inject(IPathUtils) private readonly pathUtils: IPathUtils) {}
126132
/**
127133
* Gets a selection of kernel specs from a remote session.
128134
*
@@ -132,7 +138,7 @@ export class KernelSelectionProvider {
132138
* @memberof KernelSelectionProvider
133139
*/
134140
public async getKernelSelectionsForRemoteSession(sessionManager: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IKernelSpecQuickPickItem[]> {
135-
const liveItems = new ActiveJupyterSessionKernelSelectionListProvider(sessionManager).getKernelSelections(cancelToken).then(items => {
141+
const liveItems = new ActiveJupyterSessionKernelSelectionListProvider(sessionManager, this.pathUtils).getKernelSelections(cancelToken).then(items => {
136142
// Sorty by name.
137143
items.sort((a, b) => a.label === b.label ? 0 : (a.label > b.label ? 1 : -1));
138144
this.remoteSuggestionsCache = items;
@@ -153,7 +159,7 @@ export class KernelSelectionProvider {
153159
*/
154160
public async getKernelSelectionsForLocalSession(sessionManager?: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IKernelSpecQuickPickItem[]> {
155161
const getSelections = async () => {
156-
const installedKernelsPromise = new InstalledJupyterKernelSelectionListProvider(this.kernelService, sessionManager).getKernelSelections(cancelToken);
162+
const installedKernelsPromise = new InstalledJupyterKernelSelectionListProvider(this.kernelService, this.pathUtils, sessionManager).getKernelSelections(cancelToken);
157163
const interpretersPromise = new InterpreterKernelSelectionListProvider(this.interpreterSelector).getKernelSelections(cancelToken);
158164

159165
// tslint:disable-next-line: prefer-const
@@ -168,8 +174,8 @@ export class KernelSelectionProvider {
168174
}
169175
return true;
170176
}).map(item => {
171-
// We don't want details & descriptions.
172-
return {...item, detail: '', description: ''};
177+
// We don't want descriptions.
178+
return {...item, description: ''};
173179
});
174180

175181
const unifiedList = [...installedKernels!, ...interpreters];

src/client/datascience/jupyter/kernels/kernelSelector.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ export class KernelSelector {
5656
* @returns {Promise<KernelSpecInterpreter>}
5757
* @memberof KernelSelector
5858
*/
59-
public async selectRemoteKernel(session: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<KernelSpecInterpreter> {
59+
public async selectRemoteKernel(session: IJupyterSessionManager, cancelToken?: CancellationToken, currentKernel?: IJupyterKernelSpec | IJupyterKernel & Partial<IJupyterKernelSpec>): Promise<KernelSpecInterpreter> {
6060
const suggestions = await this.selectionProvider.getKernelSelectionsForRemoteSession(session, cancelToken);
61-
return this.selectKernel(suggestions, session, cancelToken);
61+
return this.selectKernel(suggestions, session, cancelToken, currentKernel);
6262
}
6363
/**
6464
* Select a kernel from a local session.
@@ -68,9 +68,9 @@ export class KernelSelector {
6868
* @returns {Promise<KernelSpecInterpreter>}
6969
* @memberof KernelSelector
7070
*/
71-
public async selectLocalKernel(session?: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<KernelSpecInterpreter> {
71+
public async selectLocalKernel(session?: IJupyterSessionManager, cancelToken?: CancellationToken, currentKernel?: IJupyterKernelSpec | IJupyterKernel & Partial<IJupyterKernelSpec>): Promise<KernelSpecInterpreter> {
7272
const suggestions = await this.selectionProvider.getKernelSelectionsForLocalSession(session, cancelToken);
73-
return this.selectKernel(suggestions, session, cancelToken);
73+
return this.selectKernel(suggestions, session, cancelToken, currentKernel);
7474
}
7575
/**
7676
* Gets a kernel that needs to be used with a local session.
@@ -120,8 +120,9 @@ export class KernelSelector {
120120
}
121121
return selection;
122122
}
123-
private async selectKernel(suggestions: IKernelSpecQuickPickItem[], session?: IJupyterSessionManager, cancelToken?: CancellationToken){
124-
const selection = await this.applicationShell.showQuickPick(suggestions, { placeHolder: localize.DataScience.selectKernel() }, cancelToken);
123+
private async selectKernel(suggestions: IKernelSpecQuickPickItem[], session?: IJupyterSessionManager, cancelToken?: CancellationToken, currentKernel?: IJupyterKernelSpec | IJupyterKernel & Partial<IJupyterKernelSpec>){
124+
const placeHolder = localize.DataScience.selectKernel() + (currentKernel ? ` (current: ${currentKernel.display_name || currentKernel.name})` : '');
125+
const selection = await this.applicationShell.showQuickPick(suggestions, { placeHolder }, cancelToken);
125126
if (!selection?.selection) {
126127
return {};
127128
}
@@ -132,7 +133,7 @@ export class KernelSelector {
132133
} else if (selection.selection.kernelModel) {
133134
sendTelemetryEvent(Telemetry.SwitchToExistingKernel);
134135
// tslint:disable-next-line: no-any
135-
const interpreter = selection.selection.kernelModel ? await this.kernelService.findMatchingInterpreter(selection.selection.kernelModel as any, cancelToken) : undefined;
136+
const interpreter = selection.selection.kernelModel ? await this.kernelService.findMatchingInterpreter(selection.selection.kernelModel, cancelToken) : undefined;
136137
return { kernelSpec: selection.selection.kernelSpec, interpreter, kernelModel: selection.selection.kernelModel };
137138
} else if (selection.selection.kernelSpec) {
138139
sendTelemetryEvent(Telemetry.SwitchToExistingKernel);

src/client/datascience/jupyter/kernels/kernelService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { IEnvironmentActivationService } from '../../../interpreter/activation/t
2222
import { IInterpreterService, PythonInterpreter } from '../../../interpreter/contracts';
2323
import { captureTelemetry, sendTelemetryEvent } from '../../../telemetry';
2424
import { JupyterCommands, Telemetry } from '../../constants';
25-
import { IJupyterKernelSpec, IJupyterSessionManager } from '../../types';
25+
import { IJupyterKernel, IJupyterKernelSpec, IJupyterSessionManager } from '../../types';
2626
import { JupyterCommandFinder } from '../jupyterCommandFinder';
2727
import { JupyterKernelSpec } from './jupyterKernelSpec';
2828

@@ -116,8 +116,8 @@ export class KernelService {
116116
* @returns {(Promise<PythonInterpreter | undefined>)}
117117
* @memberof KernelService
118118
*/
119-
public async findMatchingInterpreter(kernelSpec: IJupyterKernelSpec, cancelToken?: CancellationToken): Promise<PythonInterpreter | undefined> {
120-
if (kernelSpec.language.toLowerCase() !== PYTHON_LANGUAGE) {
119+
public async findMatchingInterpreter(kernelSpec: IJupyterKernelSpec | IJupyterKernel & Partial<IJupyterKernelSpec>, cancelToken?: CancellationToken): Promise<PythonInterpreter | undefined> {
120+
if (kernelSpec.language && kernelSpec.language?.toLowerCase() !== PYTHON_LANGUAGE) {
121121
return;
122122
}
123123
const activeInterpreterPromise = this.interpreterService.getActiveInterpreter(undefined);

0 commit comments

Comments
 (0)