Skip to content

Commit a4d112a

Browse files
committed
Kernel selectors
1 parent 4ddb34f commit a4d112a

File tree

3 files changed

+69
-30
lines changed

3 files changed

+69
-30
lines changed

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

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55

66
import { inject, injectable } from 'inversify';
77
import { CancellationToken } from 'vscode';
8+
import * as localize from '../../../common/utils/localize';
89
import { IInterpreterSelector } from '../../../interpreter/configuration/types';
9-
import { IJupyterKernelSpec, IJupyterSessionManager } from '../../types';
10+
import { IJupyterKernel, IJupyterKernelSpec, IJupyterSessionManager } from '../../types';
1011
import { KernelService } from './kernelService';
1112
import { IKernelSelectionListProvider, IKernelSpecQuickPickItem } from './types';
1213

@@ -20,11 +21,26 @@ import { IKernelSelectionListProvider, IKernelSpecQuickPickItem } from './types'
2021
* @param {IJupyterKernelSpec} kernelSpec
2122
* @returns {IKernelSpecQuickPickItem}
2223
*/
23-
function getQuickPickFromKernelSpec(activeKernel: boolean, kernelSpec: IJupyterKernelSpec): IKernelSpecQuickPickItem {
24+
function getQuickPickItemForKernelSpec(kernelSpec: IJupyterKernelSpec): IKernelSpecQuickPickItem {
2425
return {
2526
label: kernelSpec.display_name,
26-
description: activeKernel ? '(active kernel)' : '(kernel)',
27-
selection: { kernelSpec: kernelSpec, interpreter: undefined }
27+
description: '(kernel)',
28+
selection: { kernelModel: undefined, kernelSpec: kernelSpec, interpreter: undefined }
29+
};
30+
}
31+
32+
/**
33+
* Given a kernel spec, this will return a quick pick item with appropriate display names and the like.
34+
*
35+
* @param {boolean} activeKernel Whether this is an active kernel in a jupyter session.
36+
* @param {IJupyterKernelSpec} kernelSpec
37+
* @returns {IKernelSpecQuickPickItem}
38+
*/
39+
function getQuickPickItemForActiveKernel(kernel: IJupyterKernel & Partial<IJupyterKernelSpec>): IKernelSpecQuickPickItem {
40+
return {
41+
label: kernel.display_name || kernel.name || '',
42+
description: localize.DataScience.jupyterSelectURIRunningDetailFormat().format(kernel.lastActivityTime.toLocaleString(), kernel.numberOfConnections.toString()),
43+
selection: { kernelModel: kernel, kernelSpec: undefined, interpreter: undefined }
2844
};
2945
}
3046

@@ -36,10 +52,17 @@ function getQuickPickFromKernelSpec(activeKernel: boolean, kernelSpec: IJupyterK
3652
* @implements {IKernelSelectionListProvider}
3753
*/
3854
export class ActiveJupyterSessionKernelSelectionListProvider implements IKernelSelectionListProvider {
39-
constructor(private readonly session: IJupyterSessionManager) {}
55+
constructor(private readonly sessionManager: IJupyterSessionManager) {}
4056
public async getKernelSelections(_cancelToken?: CancellationToken | undefined): Promise<IKernelSpecQuickPickItem[]> {
41-
const items = await this.session.getActiveKernelSpecs();
42-
return items.filter(item => item.display_name || item.name).map(getQuickPickFromKernelSpec.bind(undefined, true));
57+
const [activeKernels, kernelSpecs] = await Promise.all([this.sessionManager.getRunningKernels(), this.sessionManager.getKernelSpecs()]);
58+
const items = activeKernels.map(item => {
59+
const matchingSpec: Partial<IJupyterKernelSpec> = kernelSpecs.find(spec => spec.name === item.name) || {};
60+
return {
61+
...item,
62+
...matchingSpec
63+
};
64+
});
65+
return items.filter(item => item.display_name || item.name).map(getQuickPickItemForActiveKernel);
4366
}
4467
}
4568

@@ -51,10 +74,10 @@ export class ActiveJupyterSessionKernelSelectionListProvider implements IKernelS
5174
* @implements {IKernelSelectionListProvider}
5275
*/
5376
export class JupyterKernelSelectionListProvider implements IKernelSelectionListProvider {
54-
constructor(private readonly kernelService: KernelService) {}
77+
constructor(private readonly kernelService: KernelService, private readonly sessionManager?: IJupyterSessionManager) {}
5578
public async getKernelSelections(cancelToken?: CancellationToken | undefined): Promise<IKernelSpecQuickPickItem[]> {
56-
const items = await this.kernelService.getLocalKernelSpecs(cancelToken);
57-
return items.filter(item => item.display_name || item.name).map(getQuickPickFromKernelSpec.bind(undefined, false));
79+
const items = await this.kernelService.getKernelSpecs(this.sessionManager, cancelToken);
80+
return items.map(getQuickPickItemForKernelSpec);
5881
}
5982
}
6083

@@ -73,7 +96,7 @@ export class InterpreterKernelSelectionListProvider implements IKernelSelectionL
7396
return {
7497
...item,
7598
description: '(register and use interpreter as kernel)',
76-
selection: { interpreter: item.interpreter, kernelSpec: undefined }
99+
selection: { kernelModel: undefined, interpreter: item.interpreter, kernelSpec: undefined }
77100
};
78101
});
79102
}
@@ -91,24 +114,24 @@ export class KernelSelectionProvider {
91114
/**
92115
* Gets a selection of kernel specs from a remote session.
93116
*
94-
* @param {IJupyterSessionManager} session
117+
* @param {IJupyterSessionManager} sessionManager
95118
* @param {CancellationToken} [cancelToken]
96119
* @returns {Promise<IKernelSpecQuickPickItem[]>}
97120
* @memberof KernelSelectionProvider
98121
*/
99-
public async getKernelSelectionsForRemoteSession(session: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IKernelSpecQuickPickItem[]> {
100-
return new ActiveJupyterSessionKernelSelectionListProvider(session).getKernelSelections(cancelToken);
122+
public async getKernelSelectionsForRemoteSession(sessionManager: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IKernelSpecQuickPickItem[]> {
123+
return new ActiveJupyterSessionKernelSelectionListProvider(sessionManager).getKernelSelections(cancelToken);
101124
}
102125
/**
103126
* Gets a selection of kernel specs for a local session.
104127
*
105-
* @param {IJupyterSessionManager} [session]
128+
* @param {IJupyterSessionManager} [sessionManager]
106129
* @param {CancellationToken} [cancelToken]
107130
* @returns {Promise<IKernelSelectionListProvider>}
108131
* @memberof KernelSelectionProvider
109132
*/
110-
public async getLocalKernelSelectionProvider(session?: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IKernelSpecQuickPickItem[]> {
111-
const activeKernelsPromise = session ? new ActiveJupyterSessionKernelSelectionListProvider(session).getKernelSelections(cancelToken) : Promise.resolve([]);
133+
public async getLocalKernelSelectionProvider(sessionManager?: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IKernelSpecQuickPickItem[]> {
134+
const activeKernelsPromise = sessionManager ? new ActiveJupyterSessionKernelSelectionListProvider(sessionManager).getKernelSelections(cancelToken) : Promise.resolve([]);
112135
const jupyterKernelsPromise = new JupyterKernelSelectionListProvider(this.kernelService).getKernelSelections(cancelToken);
113136
const interpretersPromise = new InterpreterKernelSelectionListProvider(this.interpreterSelector).getKernelSelections(cancelToken);
114137
const [activeKernels, jupyterKernels, interprters] = await Promise.all([activeKernelsPromise, jupyterKernelsPromise, interpretersPromise]);

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ export class KernelService {
221221
traceInfo(`Kernel successfully registered for ${interpreter.path} with the name=${name} and spec can be found here ${kernel.specFile}`);
222222
return kernel;
223223
}
224+
/**
225+
* Gets a list of all kernel specs.
226+
*
227+
* @param {IJupyterSessionManager} [sessionManager]
228+
* @param {CancellationToken} [cancelToken]
229+
* @returns {Promise<IJupyterKernelSpec[]>}
230+
* @memberof KernelService
231+
*/
232+
public async getKernelSpecs(sessionManager?: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IJupyterKernelSpec[]> {
233+
const enumerator = sessionManager ? sessionManager.getKernelSpecs() : this.enumerateSpecs(cancelToken);
234+
if (Cancellation.isCanceled(cancelToken)) {
235+
return [];
236+
}
237+
const specs = await enumerator;
238+
return specs.filter(item => !!item);
239+
}
224240
/**
225241
* Not all characters are allowed in a kernel name.
226242
* This method will generate a name for a kernel based on display name and path.
@@ -233,14 +249,6 @@ export class KernelService {
233249
private async generateKernelNameForIntepreter(interpreter: PythonInterpreter): Promise<string> {
234250
return `${interpreter.displayName || ''}_${await this.fileSystem.getFileHash(interpreter.path)}`.replace(/[^A-Za-z0-9]/g, '');
235251
}
236-
private async getKernelSpecs(sessionManager?: IJupyterSessionManager, cancelToken?: CancellationToken): Promise<IJupyterKernelSpec[]> {
237-
const enumerator = sessionManager ? sessionManager.getKernelSpecs() : this.enumerateSpecs(cancelToken);
238-
if (Cancellation.isCanceled(cancelToken)) {
239-
return [];
240-
}
241-
const specs = await enumerator;
242-
return specs.filter(item => !!item);
243-
}
244252
private hasSpecPathMatch = async (info: PythonInterpreter | undefined, cancelToken?: CancellationToken): Promise<boolean> => {
245253
if (info) {
246254
// Enumerate our specs

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@
55

66
import { CancellationToken, QuickPickItem } from 'vscode';
77
import { PythonInterpreter } from '../../../interpreter/contracts';
8-
import { IJupyterKernelSpec, IJupyterSessionManager } from '../../types';
8+
import { IJupyterKernel, IJupyterKernelSpec } from '../../types';
99

1010
export interface IKernelSpecQuickPickItem extends QuickPickItem {
1111
/**
12-
* Whether a kernel spec has been selected or interpter.
13-
* If interpreter is selected, then we need to install this as a kernel to get the kernel spec.
12+
* Whether a
13+
* - Kernel spec (IJupyterKernelSpec)
14+
* - Active kernel (IJupyterKernel) or
15+
* - Interpreter has been selected.
16+
* If interpreter is selected, then we might need to install this as a kernel to get the kernel spec.
1417
*
15-
* @type {({ kernelSpec: IJupyterKernelSpec; interpreter: undefined } | { kernelSpec: undefined; interpreter: PythonInterpreter })}
18+
* @type {({ kernelModel: IJupyterKernel; kernelSpec: IJupyterKernelSpec; interpreter: undefined }
19+
* | { kernelModel: undefined; kernelSpec: IJupyterKernelSpec; interpreter: undefined }
20+
* | { kernelModel: undefined; kernelSpec: undefined; interpreter: PythonInterpreter })}
1621
* @memberof IKernelSpecQuickPickItem
1722
*/
18-
selection: { kernelSpec: IJupyterKernelSpec; interpreter: undefined } | { kernelSpec: undefined; interpreter: PythonInterpreter };
23+
selection:
24+
| { kernelModel: IJupyterKernel & Partial<IJupyterKernelSpec>; kernelSpec: undefined; interpreter: undefined }
25+
| { kernelModel: undefined; kernelSpec: IJupyterKernelSpec; interpreter: undefined }
26+
| { kernelModel: undefined; kernelSpec: undefined; interpreter: PythonInterpreter };
1927
}
2028

2129
export interface IKernelSelectionListProvider {

0 commit comments

Comments
 (0)