Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/client/datascience/interactive-common/interactiveBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -972,9 +972,9 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
private async ensureNotebookImpl(server: INotebookServer): Promise<void> {
// Create a new notebook if we need to.
if (!this._notebook) {
this._notebook = await server.createNotebook(await this.getNotebookIdentity());
const [uri, options] = await Promise.all([this.getNotebookIdentity(), this.getNotebookOptions()]);
this._notebook = await server.createNotebook(uri, options.metadata);
if (this._notebook) {
const uri: Uri = await this.getNotebookIdentity();
this.postMessage(InteractiveWindowMessages.NotebookExecutionActivated, uri.toString()).ignoreErrors();

const statusChangeHandler = async (status: ServerStatus) => {
Expand Down
3 changes: 3 additions & 0 deletions src/client/datascience/interactive-ipynb/nativeEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
private savedEvent: EventEmitter<INotebookEditor> = new EventEmitter<INotebookEditor>();
private metadataUpdatedEvent: EventEmitter<INotebookEditor> = new EventEmitter<INotebookEditor>();
private loadedPromise: Deferred<void> = createDeferred<void>();
private contentsLoadedPromise: Deferred<void> = createDeferred<void>();
private _file: Uri = Uri.file('');
private _dirty: boolean = false;
private isPromptingToSaveToDisc: boolean = false;
Expand Down Expand Up @@ -299,6 +300,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {

public async getNotebookOptions(): Promise<INotebookServerOptions> {
const options = await this.ipynbProvider.getNotebookOptions();
await this.contentsLoadedPromise.promise;
const metadata = this.notebookJson.metadata;
return {
...options,
Expand Down Expand Up @@ -587,6 +589,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
if (json) {
this.notebookJson = json;
}
this.contentsLoadedPromise.resolve();

// Extract cells from the json
const cells = contents ? (json.cells as (nbformat.ICodeCell | nbformat.IRawCell | nbformat.IMarkdownCell)[]) : [];
Expand Down
8 changes: 5 additions & 3 deletions src/client/datascience/jupyter/jupyterServer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
'use strict';
import { nbformat } from '@jupyterlab/coreutils';
import * as uuid from 'uuid/v4';
import { Disposable, Uri } from 'vscode';
import { CancellationToken } from 'vscode-jsonrpc';
Expand Down Expand Up @@ -39,7 +40,7 @@ export class JupyterServerBase implements INotebookServer {
_liveShare: ILiveShareApi,
private asyncRegistry: IAsyncDisposableRegistry,
private disposableRegistry: IDisposableRegistry,
private configService: IConfigurationService,
protected readonly configService: IConfigurationService,
private sessionManagerFactory: IJupyterSessionManagerFactory,
private loggers: INotebookExecutionLogger[]
) {
Expand Down Expand Up @@ -77,7 +78,7 @@ export class JupyterServerBase implements INotebookServer {
this.savedSession = session;
}

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

// Create a notebook and return it.
return this.createNotebookInstance(resource, this.sessionManager, savedSession, this.disposableRegistry, this.configService, this.loggers, cancelToken);
return this.createNotebookInstance(resource, this.sessionManager, savedSession, this.disposableRegistry, this.configService, this.loggers, notebookMetadata, cancelToken);
}

public async shutdown(): Promise<void> {
Expand Down Expand Up @@ -187,6 +188,7 @@ export class JupyterServerBase implements INotebookServer {
_disposableRegistry: IDisposableRegistry,
_configService: IConfigurationService,
_loggers: INotebookExecutionLogger[],
_notebookMetadata?: nbformat.INotebookMetadata,
_cancelToken?: CancellationToken
): Promise<INotebook> {
throw new Error('You forgot to override createNotebookInstance');
Expand Down
11 changes: 8 additions & 3 deletions src/client/datascience/jupyter/jupyterServerWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
'use strict';
import { nbformat } from '@jupyterlab/coreutils';
import { inject, injectable, multiInject, optional } from 'inversify';
import * as uuid from 'uuid/v4';
import { Uri } from 'vscode';
Expand All @@ -12,6 +13,7 @@ import { IFileSystem } from '../../common/platform/types';
import { IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry } from '../../common/types';
import { IInterpreterService } from '../../interpreter/contracts';
import { IConnection, IDataScience, IJupyterSessionManagerFactory, INotebook, INotebookExecutionLogger, INotebookServer, INotebookServerLaunchInfo } from '../types';
import { KernelSelector } from './kernels/kernelSelector';
import { GuestJupyterServer } from './liveshare/guestJupyterServer';
import { HostJupyterServer } from './liveshare/hostJupyterServer';
import { IRoleBasedObject, RoleBasedFactory } from './liveshare/roleBasedFactory';
Expand All @@ -32,6 +34,7 @@ type JupyterServerClassType = {
loggers: INotebookExecutionLogger[],
appShell: IApplicationShell,
fs: IFileSystem,
kernelSelector: KernelSelector,
interpreterService: IInterpreterService
): IJupyterServerInterface;
};
Expand All @@ -57,7 +60,8 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
@multiInject(INotebookExecutionLogger) @optional() loggers: INotebookExecutionLogger[] | undefined,
@inject(IApplicationShell) appShell: IApplicationShell,
@inject(IFileSystem) fs: IFileSystem,
@inject(IInterpreterService) interpreterService: IInterpreterService
@inject(IInterpreterService) interpreterService: IInterpreterService,
@inject(KernelSelector) kernelSelector: KernelSelector
) {
// The server factory will create the appropriate HostJupyterServer or GuestJupyterServer based on
// the liveshare state.
Expand All @@ -75,6 +79,7 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
loggers ? loggers : [],
appShell,
fs,
kernelSelector,
interpreterService
);
}
Expand All @@ -93,9 +98,9 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
return server.connect(launchInfo, cancelToken);
}

public async createNotebook(resource: Uri): Promise<INotebook> {
public async createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise<INotebook> {
const server = await this.serverFactory.get();
return server.createNotebook(resource);
return server.createNotebook(resource, notebookMetadata, cancelToken);
}

public async shutdown(): Promise<void> {
Expand Down
27 changes: 24 additions & 3 deletions src/client/datascience/jupyter/liveshare/hostJupyterServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as vscode from 'vscode';
import { CancellationToken } from 'vscode-jsonrpc';
import * as vsls from 'vsls/vscode';

import { nbformat } from '@jupyterlab/coreutils';
import { IApplicationShell, ILiveShareApi, IWorkspaceService } from '../../../common/application/types';
import { traceInfo } from '../../../common/logger';
import { IFileSystem } from '../../../common/platform/types';
Expand All @@ -25,6 +26,7 @@ import {
INotebookServerLaunchInfo
} from '../../types';
import { JupyterServerBase } from '../jupyterServer';
import { KernelSelector } from '../kernels/kernelSelector';
import { HostJupyterNotebook } from './hostJupyterNotebook';
import { LiveShareParticipantHost } from './liveShareParticipantMixin';
import { IRoleBasedObject } from './roleBasedFactory';
Expand All @@ -46,7 +48,8 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
private workspaceService: IWorkspaceService,
loggers: INotebookExecutionLogger[],
private appService: IApplicationShell,
private fs: IFileSystem
private fs: IFileSystem,
private readonly kernelSelector: KernelSelector
) {
super(liveShare, asyncRegistry, disposableRegistry, configService, sessionManager, loggers);
}
Expand Down Expand Up @@ -86,7 +89,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
const uri = vscode.Uri.parse(args[0]);
const resource = uri.scheme && uri.scheme !== Identifiers.InteractiveWindowIdentityScheme ? this.finishedApi!.convertSharedUriToLocal(uri) : uri;
// Don't return the notebook. We don't want it to be serialized. We just want its live share server to be started.
const notebook = (await this.createNotebook(resource, cancellation)) as HostJupyterNotebook;
const notebook = (await this.createNotebook(resource, undefined, cancellation)) as HostJupyterNotebook;
await notebook.onAttach(api);
});

Expand Down Expand Up @@ -137,6 +140,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
disposableRegistry: IDisposableRegistry,
configService: IConfigurationService,
loggers: INotebookExecutionLogger[],
notebookMetadata?: nbformat.INotebookMetadata,
cancelToken?: CancellationToken
): Promise<INotebook> {
// See if already exists.
Expand All @@ -159,8 +163,25 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
throw this.getDisposedError();
}

// Find a kernel that can be used.
// Do this only if kernel information has been provided in the metadata, else use the default.
let defaultKernelInfoToUse = launchInfo.kernelSpec;
if (notebookMetadata?.kernelspec) {
const kernelInfo = await (launchInfo.connectionInfo.localLaunch
? this.kernelSelector.getKernelForLocalConnection(sessionManager, notebookMetadata, false, cancelToken)
: this.kernelSelector.getKernelForRemoteConnection(sessionManager, notebookMetadata, cancelToken));

const kernelInfoToUse = kernelInfo?.kernelSpec || kernelInfo?.kernelModel;
if (kernelInfoToUse) {
defaultKernelInfoToUse = kernelInfoToUse;
}
if (possibleSession && kernelInfoToUse) {
await possibleSession.changeKernel(kernelInfoToUse, this.configService.getSettings().datascience.jupyterLaunchTimeout);
}
launchInfo.kernelSpec = defaultKernelInfoToUse;
}
// Start a session (or use the existing one)
const session = possibleSession || (await sessionManager.startNew(launchInfo.kernelSpec, cancelToken));
const session = possibleSession || (await sessionManager.startNew(defaultKernelInfoToUse, cancelToken));
traceInfo(`Started session ${this.id}`);

if (session) {
Expand Down
2 changes: 1 addition & 1 deletion src/client/datascience/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export interface INotebookCompletion {
export const INotebookServer = Symbol('INotebookServer');
export interface INotebookServer extends IAsyncDisposable {
readonly id: string;
createNotebook(resource: Uri, cancelToken?: CancellationToken): Promise<INotebook>;
createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise<INotebook>;
getNotebook(resource: Uri): Promise<INotebook | undefined>;
connect(launchInfo: INotebookServerLaunchInfo, cancelToken?: CancellationToken): Promise<void>;
getConnectionInfo(): IConnection | undefined;
Expand Down