Skip to content

Commit 8805276

Browse files
committed
Notebook should use kernel from metadata (#9936)
For #9927 * Notebook should use kernel from metadata * Fix formatting
1 parent 8d7636e commit 8805276

File tree

6 files changed

+43
-12
lines changed

6 files changed

+43
-12
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -972,9 +972,9 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
972972
private async ensureNotebookImpl(server: INotebookServer): Promise<void> {
973973
// Create a new notebook if we need to.
974974
if (!this._notebook) {
975-
this._notebook = await server.createNotebook(await this.getNotebookIdentity());
975+
const [uri, options] = await Promise.all([this.getNotebookIdentity(), this.getNotebookOptions()]);
976+
this._notebook = await server.createNotebook(uri, options.metadata);
976977
if (this._notebook) {
977-
const uri: Uri = await this.getNotebookIdentity();
978978
this.postMessage(InteractiveWindowMessages.NotebookExecutionActivated, uri.toString()).ignoreErrors();
979979

980980
const statusChangeHandler = async (status: ServerStatus) => {

src/client/datascience/interactive-ipynb/nativeEditor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
8484
private savedEvent: EventEmitter<INotebookEditor> = new EventEmitter<INotebookEditor>();
8585
private metadataUpdatedEvent: EventEmitter<INotebookEditor> = new EventEmitter<INotebookEditor>();
8686
private loadedPromise: Deferred<void> = createDeferred<void>();
87+
private contentsLoadedPromise: Deferred<void> = createDeferred<void>();
8788
private _file: Uri = Uri.file('');
8889
private _dirty: boolean = false;
8990
private isPromptingToSaveToDisc: boolean = false;
@@ -299,6 +300,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
299300

300301
public async getNotebookOptions(): Promise<INotebookServerOptions> {
301302
const options = await this.ipynbProvider.getNotebookOptions();
303+
await this.contentsLoadedPromise.promise;
302304
const metadata = this.notebookJson.metadata;
303305
return {
304306
...options,
@@ -587,6 +589,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
587589
if (json) {
588590
this.notebookJson = json;
589591
}
592+
this.contentsLoadedPromise.resolve();
590593

591594
// Extract cells from the json
592595
const cells = contents ? (json.cells as (nbformat.ICodeCell | nbformat.IRawCell | nbformat.IMarkdownCell)[]) : [];

src/client/datascience/jupyter/jupyterServer.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33
'use strict';
4+
import { nbformat } from '@jupyterlab/coreutils';
45
import * as uuid from 'uuid/v4';
56
import { Disposable, Uri } from 'vscode';
67
import { CancellationToken } from 'vscode-jsonrpc';
@@ -39,7 +40,7 @@ export class JupyterServerBase implements INotebookServer {
3940
_liveShare: ILiveShareApi,
4041
private asyncRegistry: IAsyncDisposableRegistry,
4142
private disposableRegistry: IDisposableRegistry,
42-
private configService: IConfigurationService,
43+
protected readonly configService: IConfigurationService,
4344
private sessionManagerFactory: IJupyterSessionManagerFactory,
4445
private loggers: INotebookExecutionLogger[]
4546
) {
@@ -77,7 +78,7 @@ export class JupyterServerBase implements INotebookServer {
7778
this.savedSession = session;
7879
}
7980

80-
public createNotebook(resource: Uri, cancelToken?: CancellationToken): Promise<INotebook> {
81+
public createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise<INotebook> {
8182
if (!this.sessionManager) {
8283
throw new Error(localize.DataScience.sessionDisposed());
8384
}
@@ -86,7 +87,7 @@ export class JupyterServerBase implements INotebookServer {
8687
this.savedSession = undefined;
8788

8889
// Create a notebook and return it.
89-
return this.createNotebookInstance(resource, this.sessionManager, savedSession, this.disposableRegistry, this.configService, this.loggers, cancelToken);
90+
return this.createNotebookInstance(resource, this.sessionManager, savedSession, this.disposableRegistry, this.configService, this.loggers, notebookMetadata, cancelToken);
9091
}
9192

9293
public async shutdown(): Promise<void> {
@@ -187,6 +188,7 @@ export class JupyterServerBase implements INotebookServer {
187188
_disposableRegistry: IDisposableRegistry,
188189
_configService: IConfigurationService,
189190
_loggers: INotebookExecutionLogger[],
191+
_notebookMetadata?: nbformat.INotebookMetadata,
190192
_cancelToken?: CancellationToken
191193
): Promise<INotebook> {
192194
throw new Error('You forgot to override createNotebookInstance');

src/client/datascience/jupyter/jupyterServerWrapper.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33
'use strict';
4+
import { nbformat } from '@jupyterlab/coreutils';
45
import { inject, injectable, multiInject, optional } from 'inversify';
56
import * as uuid from 'uuid/v4';
67
import { Uri } from 'vscode';
@@ -12,6 +13,7 @@ import { IFileSystem } from '../../common/platform/types';
1213
import { IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry } from '../../common/types';
1314
import { IInterpreterService } from '../../interpreter/contracts';
1415
import { IConnection, IDataScience, IJupyterSessionManagerFactory, INotebook, INotebookExecutionLogger, INotebookServer, INotebookServerLaunchInfo } from '../types';
16+
import { KernelSelector } from './kernels/kernelSelector';
1517
import { GuestJupyterServer } from './liveshare/guestJupyterServer';
1618
import { HostJupyterServer } from './liveshare/hostJupyterServer';
1719
import { IRoleBasedObject, RoleBasedFactory } from './liveshare/roleBasedFactory';
@@ -32,6 +34,7 @@ type JupyterServerClassType = {
3234
loggers: INotebookExecutionLogger[],
3335
appShell: IApplicationShell,
3436
fs: IFileSystem,
37+
kernelSelector: KernelSelector,
3538
interpreterService: IInterpreterService
3639
): IJupyterServerInterface;
3740
};
@@ -57,7 +60,8 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
5760
@multiInject(INotebookExecutionLogger) @optional() loggers: INotebookExecutionLogger[] | undefined,
5861
@inject(IApplicationShell) appShell: IApplicationShell,
5962
@inject(IFileSystem) fs: IFileSystem,
60-
@inject(IInterpreterService) interpreterService: IInterpreterService
63+
@inject(IInterpreterService) interpreterService: IInterpreterService,
64+
@inject(KernelSelector) kernelSelector: KernelSelector
6165
) {
6266
// The server factory will create the appropriate HostJupyterServer or GuestJupyterServer based on
6367
// the liveshare state.
@@ -75,6 +79,7 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
7579
loggers ? loggers : [],
7680
appShell,
7781
fs,
82+
kernelSelector,
7883
interpreterService
7984
);
8085
}
@@ -93,9 +98,9 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
9398
return server.connect(launchInfo, cancelToken);
9499
}
95100

96-
public async createNotebook(resource: Uri): Promise<INotebook> {
101+
public async createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise<INotebook> {
97102
const server = await this.serverFactory.get();
98-
return server.createNotebook(resource);
103+
return server.createNotebook(resource, notebookMetadata, cancelToken);
99104
}
100105

101106
public async shutdown(): Promise<void> {

src/client/datascience/jupyter/liveshare/hostJupyterServer.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
88
import { CancellationToken } from 'vscode-jsonrpc';
99
import * as vsls from 'vsls/vscode';
1010

11+
import { nbformat } from '@jupyterlab/coreutils';
1112
import { IApplicationShell, ILiveShareApi, IWorkspaceService } from '../../../common/application/types';
1213
import { traceInfo } from '../../../common/logger';
1314
import { IFileSystem } from '../../../common/platform/types';
@@ -25,6 +26,7 @@ import {
2526
INotebookServerLaunchInfo
2627
} from '../../types';
2728
import { JupyterServerBase } from '../jupyterServer';
29+
import { KernelSelector } from '../kernels/kernelSelector';
2830
import { HostJupyterNotebook } from './hostJupyterNotebook';
2931
import { LiveShareParticipantHost } from './liveShareParticipantMixin';
3032
import { IRoleBasedObject } from './roleBasedFactory';
@@ -46,7 +48,8 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
4648
private workspaceService: IWorkspaceService,
4749
loggers: INotebookExecutionLogger[],
4850
private appService: IApplicationShell,
49-
private fs: IFileSystem
51+
private fs: IFileSystem,
52+
private readonly kernelSelector: KernelSelector
5053
) {
5154
super(liveShare, asyncRegistry, disposableRegistry, configService, sessionManager, loggers);
5255
}
@@ -86,7 +89,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
8689
const uri = vscode.Uri.parse(args[0]);
8790
const resource = uri.scheme && uri.scheme !== Identifiers.InteractiveWindowIdentityScheme ? this.finishedApi!.convertSharedUriToLocal(uri) : uri;
8891
// Don't return the notebook. We don't want it to be serialized. We just want its live share server to be started.
89-
const notebook = (await this.createNotebook(resource, cancellation)) as HostJupyterNotebook;
92+
const notebook = (await this.createNotebook(resource, undefined, cancellation)) as HostJupyterNotebook;
9093
await notebook.onAttach(api);
9194
});
9295

@@ -137,6 +140,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
137140
disposableRegistry: IDisposableRegistry,
138141
configService: IConfigurationService,
139142
loggers: INotebookExecutionLogger[],
143+
notebookMetadata?: nbformat.INotebookMetadata,
140144
cancelToken?: CancellationToken
141145
): Promise<INotebook> {
142146
// See if already exists.
@@ -159,8 +163,25 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
159163
throw this.getDisposedError();
160164
}
161165

166+
// Find a kernel that can be used.
167+
// Do this only if kernel information has been provided in the metadata, else use the default.
168+
let defaultKernelInfoToUse = launchInfo.kernelSpec;
169+
if (notebookMetadata?.kernelspec) {
170+
const kernelInfo = await (launchInfo.connectionInfo.localLaunch
171+
? this.kernelSelector.getKernelForLocalConnection(sessionManager, notebookMetadata, false, cancelToken)
172+
: this.kernelSelector.getKernelForRemoteConnection(sessionManager, notebookMetadata, cancelToken));
173+
174+
const kernelInfoToUse = kernelInfo?.kernelSpec || kernelInfo?.kernelModel;
175+
if (kernelInfoToUse) {
176+
defaultKernelInfoToUse = kernelInfoToUse;
177+
}
178+
if (possibleSession && kernelInfoToUse) {
179+
await possibleSession.changeKernel(kernelInfoToUse, this.configService.getSettings().datascience.jupyterLaunchTimeout);
180+
}
181+
launchInfo.kernelSpec = defaultKernelInfoToUse;
182+
}
162183
// Start a session (or use the existing one)
163-
const session = possibleSession || (await sessionManager.startNew(launchInfo.kernelSpec, cancelToken));
184+
const session = possibleSession || (await sessionManager.startNew(defaultKernelInfoToUse, cancelToken));
164185
traceInfo(`Started session ${this.id}`);
165186

166187
if (session) {

src/client/datascience/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface INotebookCompletion {
8181
export const INotebookServer = Symbol('INotebookServer');
8282
export interface INotebookServer extends IAsyncDisposable {
8383
readonly id: string;
84-
createNotebook(resource: Uri, cancelToken?: CancellationToken): Promise<INotebook>;
84+
createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise<INotebook>;
8585
getNotebook(resource: Uri): Promise<INotebook | undefined>;
8686
connect(launchInfo: INotebookServerLaunchInfo, cancelToken?: CancellationToken): Promise<void>;
8787
getConnectionInfo(): IConnection | undefined;

0 commit comments

Comments
 (0)