From 49f4164c5975e247ef8c07903a102bd026eb03fa Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Tue, 28 Apr 2020 15:47:46 -0700 Subject: [PATCH 1/2] basic routing working --- src/client/datascience/baseJupyterSession.ts | 19 ++++++++++++----- .../datascience/jupyter/jupyterNotebook.ts | 2 +- .../datascience/jupyter/jupyterSession.ts | 2 ++ .../liveshare/hostRawNotebookProvider.ts | 7 ++++++- .../raw-kernel/rawJupyterSession.ts | 21 +++++++++++++------ .../raw-kernel/rawNotebookProviderWrapper.ts | 4 ++++ src/client/datascience/types.ts | 6 +++++- 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/client/datascience/baseJupyterSession.ts b/src/client/datascience/baseJupyterSession.ts index 21652e3b4b1a..612a075587f3 100644 --- a/src/client/datascience/baseJupyterSession.ts +++ b/src/client/datascience/baseJupyterSession.ts @@ -13,6 +13,7 @@ import { traceError, traceInfo, traceWarning } from '../common/logger'; import { waitForPromise } from '../common/utils/async'; import * as localize from '../common/utils/localize'; import { noop } from '../common/utils/misc'; +import { PythonInterpreter } from '../interpreter/contracts'; import { sendTelemetryEvent } from '../telemetry'; import { Telemetry } from './constants'; import { JupyterKernelPromiseFailedError } from './jupyter/kernels/jupyterKernelPromiseFailedError'; @@ -41,6 +42,7 @@ export abstract class BaseJupyterSession implements IJupyterSession { return this._session; } protected kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined; + protected interpreter: PythonInterpreter | undefined; public get kernelSocket(): Observable { return this._kernelSocket; } @@ -118,7 +120,11 @@ export abstract class BaseJupyterSession implements IJupyterSession { } } - public async changeKernel(kernel: IJupyterKernelSpec | LiveKernelModel, timeoutMS: number): Promise { + public async changeKernel( + kernel: IJupyterKernelSpec | LiveKernelModel, + timeoutMS: number, + interpreter?: PythonInterpreter + ): Promise { let newSession: ISessionWithSocket | undefined; // If we are already using this kernel in an active session just return back @@ -126,7 +132,7 @@ export abstract class BaseJupyterSession implements IJupyterSession { return; } - newSession = await this.createNewKernelSession(kernel, timeoutMS); + newSession = await this.createNewKernelSession(kernel, timeoutMS, interpreter); // This is just like doing a restart, kill the old session (and the old restart session), and start new ones if (this.session) { @@ -134,8 +140,9 @@ export abstract class BaseJupyterSession implements IJupyterSession { this.restartSessionPromise?.then((r) => this.shutdownSession(r, undefined)).ignoreErrors(); // NOSONAR } - // Update our kernel spec + // Update our kernel spec and interpreter this.kernelSpec = kernel; + this.interpreter = interpreter; // Save the new session this.setSession(newSession); @@ -144,7 +151,7 @@ export abstract class BaseJupyterSession implements IJupyterSession { this.session?.statusChanged.connect(this.statusHandler); // NOSONAR // Start the restart session promise too. - this.restartSessionPromise = this.createRestartSession(kernel, newSession); + this.restartSessionPromise = this.createRestartSession(kernel, newSession, interpreter); } public async restart(_timeout: number): Promise { @@ -298,13 +305,15 @@ export abstract class BaseJupyterSession implements IJupyterSession { protected abstract async createRestartSession( kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined, session: ISessionWithSocket, + interpreter?: PythonInterpreter, cancelToken?: CancellationToken ): Promise; // Sub classes need to implement their own kernel change specific code protected abstract createNewKernelSession( kernel: IJupyterKernelSpec | LiveKernelModel, - timeoutMS: number + timeoutMS: number, + interpreter?: PythonInterpreter ): Promise; // Changes the current session. diff --git a/src/client/datascience/jupyter/jupyterNotebook.ts b/src/client/datascience/jupyter/jupyterNotebook.ts index bf4c87ddc0b4..8a3527b75815 100644 --- a/src/client/datascience/jupyter/jupyterNotebook.ts +++ b/src/client/datascience/jupyter/jupyterNotebook.ts @@ -616,7 +616,7 @@ export class JupyterNotebookBase implements INotebook { this.ranInitialSetup = false; // Change the kernel on the session - await this.session.changeKernel(spec, timeoutMS); + await this.session.changeKernel(spec, timeoutMS, interpreter); // Change our own kernel spec // Only after session was successfully created. diff --git a/src/client/datascience/jupyter/jupyterSession.ts b/src/client/datascience/jupyter/jupyterSession.ts index fcdabfe6baca..694deb5796f1 100644 --- a/src/client/datascience/jupyter/jupyterSession.ts +++ b/src/client/datascience/jupyter/jupyterSession.ts @@ -21,6 +21,7 @@ import { IOutputChannel } from '../../common/types'; import { sleep } from '../../common/utils/async'; import * as localize from '../../common/utils/localize'; import { noop } from '../../common/utils/misc'; +import { PythonInterpreter } from '../../interpreter/contracts'; import { captureTelemetry } from '../../telemetry'; import { BaseJupyterSession, JupyterSessionStartError } from '../baseJupyterSession'; import { Identifiers, Telemetry } from '../constants'; @@ -131,6 +132,7 @@ export class JupyterSession extends BaseJupyterSession { protected async createRestartSession( kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined, session: ISessionWithSocket, + _interpreter?: PythonInterpreter, cancelToken?: CancellationToken ): Promise { // We need all of the above to create a restart session diff --git a/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts b/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts index 6634529730b9..ce75abd9ff3e 100644 --- a/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts +++ b/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts @@ -23,6 +23,7 @@ import * as localize from '../../../common/utils/localize'; import { IServiceContainer } from '../../../ioc/types'; import { Identifiers, LiveShare, Settings } from '../../constants'; import { KernelSelector } from '../../jupyter/kernels/kernelSelector'; +import { KernelService } from '../../jupyter/kernels/kernelService'; import { HostJupyterNotebook } from '../../jupyter/liveshare/hostJupyterNotebook'; import { LiveShareParticipantHost } from '../../jupyter/liveshare/liveShareParticipantMixin'; import { IRoleBasedObject } from '../../jupyter/liveshare/roleBasedFactory'; @@ -58,6 +59,7 @@ export class HostRawNotebookProvider private kernelLauncher: IKernelLauncher, private kernelFinder: IKernelFinder, private kernelSelector: KernelSelector, + private kernelService: KernelService, private progressReporter: ProgressReporter, private outputChannel: IOutputChannel ) { @@ -117,7 +119,10 @@ export class HostRawNotebookProvider cancelToken ); - await rawSession.connect(kernelSpec, launchTimeout, cancelToken); + // Location the interpreter that matches our kernelspec + const interpreter = await this.kernelService.findMatchingInterpreter(kernelSpec); + + await rawSession.connect(kernelSpec, launchTimeout, interpreter, cancelToken); // Get the execution info for our notebook const info = await this.getExecutionInfo(kernelSpec); diff --git a/src/client/datascience/raw-kernel/rawJupyterSession.ts b/src/client/datascience/raw-kernel/rawJupyterSession.ts index ac185e97c4fb..8fc77e3a3d97 100644 --- a/src/client/datascience/raw-kernel/rawJupyterSession.ts +++ b/src/client/datascience/raw-kernel/rawJupyterSession.ts @@ -10,6 +10,7 @@ import { IDisposable, IOutputChannel, Resource } from '../../common/types'; import { waitForPromise } from '../../common/utils/async'; import * as localize from '../../common/utils/localize'; import { noop } from '../../common/utils/misc'; +import { PythonInterpreter } from '../../interpreter/contracts'; import { captureTelemetry, sendTelemetryEvent } from '../../telemetry'; import { BaseJupyterSession } from '../baseJupyterSession'; import { Identifiers, Telemetry } from '../constants'; @@ -62,6 +63,7 @@ export class RawJupyterSession extends BaseJupyterSession { public async connect( kernelSpec: IJupyterKernelSpec, timeout: number, + interpreter?: PythonInterpreter, cancelToken?: CancellationToken ): Promise { // Save the resource that we connect with @@ -71,7 +73,7 @@ export class RawJupyterSession extends BaseJupyterSession { // Notebook Provider level will handle the thrown error newSession = await waitForPromise( Promise.race([ - this.startRawSession(kernelSpec, cancelToken), + this.startRawSession(kernelSpec, interpreter, cancelToken), createPromiseFromCancellation({ cancelAction: 'reject', defaultValue: new CancellationError(), @@ -94,7 +96,11 @@ export class RawJupyterSession extends BaseJupyterSession { sendTelemetryEvent(Telemetry.RawKernelSessionStartSuccess); traceInfo('Raw session started and connected'); this.setSession(newSession); + + // Update kernelspec and interpreter this.kernelSpec = newSession.kernelProcess?.kernelSpec; + this.interpreter = interpreter; + this.outputChannel.appendLine( localize.DataScience.kernelStarted().format(this.kernelSpec.display_name || this.kernelSpec.name) ); @@ -115,7 +121,8 @@ export class RawJupyterSession extends BaseJupyterSession { public async createNewKernelSession( kernel: IJupyterKernelSpec | LiveKernelModel, - _timeoutMS: number + _timeoutMS: number, + interpreter?: PythonInterpreter ): Promise { if (!kernel || 'session' in kernel) { // Don't allow for connecting to a LiveKernelModel @@ -124,7 +131,7 @@ export class RawJupyterSession extends BaseJupyterSession { this.outputChannel.appendLine(localize.DataScience.kernelStarted().format(kernel.display_name || kernel.name)); - return this.startRawSession(kernel); + return this.startRawSession(kernel, interpreter); } protected shutdownSession( @@ -161,19 +168,20 @@ export class RawJupyterSession extends BaseJupyterSession { protected startRestartSession() { if (!this.restartSessionPromise && this.session) { - this.restartSessionPromise = this.createRestartSession(this.kernelSpec, this.session); + this.restartSessionPromise = this.createRestartSession(this.kernelSpec, this.session, this.interpreter); } } protected async createRestartSession( kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined, _session: ISessionWithSocket, + interpreter?: PythonInterpreter, cancelToken?: CancellationToken ): Promise { if (!kernelSpec || 'session' in kernelSpec) { // Need to have connected before restarting and can't use a LiveKernelModel throw new Error(localize.DataScience.sessionDisposed()); } - const startPromise = this.startRawSession(kernelSpec, cancelToken); + const startPromise = this.startRawSession(kernelSpec, interpreter, cancelToken); return startPromise.then((session) => { this.kernelSelector.addKernelToIgnoreList(session.kernel); return session; @@ -183,6 +191,7 @@ export class RawJupyterSession extends BaseJupyterSession { @captureTelemetry(Telemetry.RawKernelStartRawSession, undefined, true) private async startRawSession( kernelSpec: IJupyterKernelSpec, + interpreter?: PythonInterpreter, cancelToken?: CancellationToken ): Promise { const cancellationPromise = createPromiseFromCancellation({ @@ -193,7 +202,7 @@ export class RawJupyterSession extends BaseJupyterSession { cancellationPromise.catch(noop); const process = await Promise.race([ - this.kernelLauncher.launch(kernelSpec, this.resource), + this.kernelLauncher.launch(kernelSpec, this.resource, interpreter), cancellationPromise ]); diff --git a/src/client/datascience/raw-kernel/rawNotebookProviderWrapper.ts b/src/client/datascience/raw-kernel/rawNotebookProviderWrapper.ts index a1d65ca1ac6a..ce2a4b0fb867 100644 --- a/src/client/datascience/raw-kernel/rawNotebookProviderWrapper.ts +++ b/src/client/datascience/raw-kernel/rawNotebookProviderWrapper.ts @@ -19,6 +19,7 @@ import { import { IServiceContainer } from '../../ioc/types'; import { JUPYTER_OUTPUT_CHANNEL } from '../constants'; import { KernelSelector } from '../jupyter/kernels/kernelSelector'; +import { KernelService } from '../jupyter/kernels/kernelService'; import { IRoleBasedObject, RoleBasedFactory } from '../jupyter/liveshare/roleBasedFactory'; import { ILiveShareHasRole } from '../jupyter/liveshare/types'; import { IKernelFinder, IKernelLauncher } from '../kernel-launcher/types'; @@ -43,6 +44,7 @@ type RawNotebookProviderClassType = { kernelLauncher: IKernelLauncher, kernelFinder: IKernelFinder, kernelSelector: KernelSelector, + kernelService: KernelService, progressReporter: ProgressReporter, outputChannel: IOutputChannel ): IRawNotebookProviderInterface; @@ -67,6 +69,7 @@ export class RawNotebookProviderWrapper implements IRawNotebookProvider, ILiveSh @inject(IKernelLauncher) kernelLauncher: IKernelLauncher, @inject(IKernelFinder) kernelFinder: IKernelFinder, @inject(KernelSelector) kernelSelector: KernelSelector, + @inject(KernelService) kernelService: KernelService, @inject(ProgressReporter) progressReporter: ProgressReporter, @inject(IOutputChannel) @named(JUPYTER_OUTPUT_CHANNEL) outputChannel: IOutputChannel ) { @@ -87,6 +90,7 @@ export class RawNotebookProviderWrapper implements IRawNotebookProvider, ILiveSh kernelLauncher, kernelFinder, kernelSelector, + kernelService, progressReporter, outputChannel ); diff --git a/src/client/datascience/types.ts b/src/client/datascience/types.ts index c671d1c31b2a..bf68f6365a02 100644 --- a/src/client/datascience/types.ts +++ b/src/client/datascience/types.ts @@ -326,7 +326,11 @@ export interface IJupyterSession extends IAsyncDisposable { content: KernelMessage.IInspectRequestMsg['content'] ): Promise; sendInputReply(content: string): void; - changeKernel(kernel: IJupyterKernelSpec | LiveKernelModel, timeoutMS: number): Promise; + changeKernel( + kernel: IJupyterKernelSpec | LiveKernelModel, + timeoutMS: number, + interpreter?: PythonInterpreter + ): Promise; registerCommTarget( targetName: string, callback: (comm: Kernel.IComm, msg: KernelMessage.ICommOpenMsg) => void | PromiseLike From 78194ac2ea600ef8386f241ac14d54ff2f48775c Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Tue, 28 Apr 2020 15:53:12 -0700 Subject: [PATCH 2/2] typo fix --- .../datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts b/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts index ce75abd9ff3e..2f08025cf689 100644 --- a/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts +++ b/src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts @@ -119,7 +119,7 @@ export class HostRawNotebookProvider cancelToken ); - // Location the interpreter that matches our kernelspec + // Locate the interpreter that matches our kernelspec const interpreter = await this.kernelService.findMatchingInterpreter(kernelSpec); await rawSession.connect(kernelSpec, launchTimeout, interpreter, cancelToken);