Skip to content

Commit 7d316f0

Browse files
Route python interpreter into kernel launcher (microsoft#11486)
1 parent 6de7c72 commit 7d316f0

7 files changed

Lines changed: 47 additions & 14 deletions

File tree

src/client/datascience/baseJupyterSession.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { traceError, traceInfo, traceWarning } from '../common/logger';
1313
import { waitForPromise } from '../common/utils/async';
1414
import * as localize from '../common/utils/localize';
1515
import { noop } from '../common/utils/misc';
16+
import { PythonInterpreter } from '../interpreter/contracts';
1617
import { sendTelemetryEvent } from '../telemetry';
1718
import { Telemetry } from './constants';
1819
import { JupyterKernelPromiseFailedError } from './jupyter/kernels/jupyterKernelPromiseFailedError';
@@ -41,6 +42,7 @@ export abstract class BaseJupyterSession implements IJupyterSession {
4142
return this._session;
4243
}
4344
protected kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined;
45+
protected interpreter: PythonInterpreter | undefined;
4446
public get kernelSocket(): Observable<KernelSocketInformation | undefined> {
4547
return this._kernelSocket;
4648
}
@@ -118,24 +120,29 @@ export abstract class BaseJupyterSession implements IJupyterSession {
118120
}
119121
}
120122

121-
public async changeKernel(kernel: IJupyterKernelSpec | LiveKernelModel, timeoutMS: number): Promise<void> {
123+
public async changeKernel(
124+
kernel: IJupyterKernelSpec | LiveKernelModel,
125+
timeoutMS: number,
126+
interpreter?: PythonInterpreter
127+
): Promise<void> {
122128
let newSession: ISessionWithSocket | undefined;
123129

124130
// If we are already using this kernel in an active session just return back
125131
if (this.kernelSpec?.name === kernel.name && this.session) {
126132
return;
127133
}
128134

129-
newSession = await this.createNewKernelSession(kernel, timeoutMS);
135+
newSession = await this.createNewKernelSession(kernel, timeoutMS, interpreter);
130136

131137
// This is just like doing a restart, kill the old session (and the old restart session), and start new ones
132138
if (this.session) {
133139
this.shutdownSession(this.session, this.statusHandler).ignoreErrors();
134140
this.restartSessionPromise?.then((r) => this.shutdownSession(r, undefined)).ignoreErrors(); // NOSONAR
135141
}
136142

137-
// Update our kernel spec
143+
// Update our kernel spec and interpreter
138144
this.kernelSpec = kernel;
145+
this.interpreter = interpreter;
139146

140147
// Save the new session
141148
this.setSession(newSession);
@@ -144,7 +151,7 @@ export abstract class BaseJupyterSession implements IJupyterSession {
144151
this.session?.statusChanged.connect(this.statusHandler); // NOSONAR
145152

146153
// Start the restart session promise too.
147-
this.restartSessionPromise = this.createRestartSession(kernel, newSession);
154+
this.restartSessionPromise = this.createRestartSession(kernel, newSession, interpreter);
148155
}
149156

150157
public async restart(_timeout: number): Promise<void> {
@@ -298,13 +305,15 @@ export abstract class BaseJupyterSession implements IJupyterSession {
298305
protected abstract async createRestartSession(
299306
kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined,
300307
session: ISessionWithSocket,
308+
interpreter?: PythonInterpreter,
301309
cancelToken?: CancellationToken
302310
): Promise<ISessionWithSocket>;
303311

304312
// Sub classes need to implement their own kernel change specific code
305313
protected abstract createNewKernelSession(
306314
kernel: IJupyterKernelSpec | LiveKernelModel,
307-
timeoutMS: number
315+
timeoutMS: number,
316+
interpreter?: PythonInterpreter
308317
): Promise<ISessionWithSocket>;
309318

310319
// Changes the current session.

src/client/datascience/jupyter/jupyterNotebook.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ export class JupyterNotebookBase implements INotebook {
616616
this.ranInitialSetup = false;
617617

618618
// Change the kernel on the session
619-
await this.session.changeKernel(spec, timeoutMS);
619+
await this.session.changeKernel(spec, timeoutMS, interpreter);
620620

621621
// Change our own kernel spec
622622
// Only after session was successfully created.

src/client/datascience/jupyter/jupyterSession.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { IOutputChannel } from '../../common/types';
2121
import { sleep } from '../../common/utils/async';
2222
import * as localize from '../../common/utils/localize';
2323
import { noop } from '../../common/utils/misc';
24+
import { PythonInterpreter } from '../../interpreter/contracts';
2425
import { captureTelemetry } from '../../telemetry';
2526
import { BaseJupyterSession, JupyterSessionStartError } from '../baseJupyterSession';
2627
import { Identifiers, Telemetry } from '../constants';
@@ -131,6 +132,7 @@ export class JupyterSession extends BaseJupyterSession {
131132
protected async createRestartSession(
132133
kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined,
133134
session: ISessionWithSocket,
135+
_interpreter?: PythonInterpreter,
134136
cancelToken?: CancellationToken
135137
): Promise<ISessionWithSocket> {
136138
// We need all of the above to create a restart session

src/client/datascience/raw-kernel/liveshare/hostRawNotebookProvider.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import * as localize from '../../../common/utils/localize';
2323
import { IServiceContainer } from '../../../ioc/types';
2424
import { Identifiers, LiveShare, Settings } from '../../constants';
2525
import { KernelSelector } from '../../jupyter/kernels/kernelSelector';
26+
import { KernelService } from '../../jupyter/kernels/kernelService';
2627
import { HostJupyterNotebook } from '../../jupyter/liveshare/hostJupyterNotebook';
2728
import { LiveShareParticipantHost } from '../../jupyter/liveshare/liveShareParticipantMixin';
2829
import { IRoleBasedObject } from '../../jupyter/liveshare/roleBasedFactory';
@@ -58,6 +59,7 @@ export class HostRawNotebookProvider
5859
private kernelLauncher: IKernelLauncher,
5960
private kernelFinder: IKernelFinder,
6061
private kernelSelector: KernelSelector,
62+
private kernelService: KernelService,
6163
private progressReporter: ProgressReporter,
6264
private outputChannel: IOutputChannel
6365
) {
@@ -117,7 +119,10 @@ export class HostRawNotebookProvider
117119
cancelToken
118120
);
119121

120-
await rawSession.connect(kernelSpec, launchTimeout, cancelToken);
122+
// Locate the interpreter that matches our kernelspec
123+
const interpreter = await this.kernelService.findMatchingInterpreter(kernelSpec);
124+
125+
await rawSession.connect(kernelSpec, launchTimeout, interpreter, cancelToken);
121126

122127
// Get the execution info for our notebook
123128
const info = await this.getExecutionInfo(kernelSpec);

src/client/datascience/raw-kernel/rawJupyterSession.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { IDisposable, IOutputChannel, Resource } from '../../common/types';
1010
import { waitForPromise } from '../../common/utils/async';
1111
import * as localize from '../../common/utils/localize';
1212
import { noop } from '../../common/utils/misc';
13+
import { PythonInterpreter } from '../../interpreter/contracts';
1314
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
1415
import { BaseJupyterSession } from '../baseJupyterSession';
1516
import { Identifiers, Telemetry } from '../constants';
@@ -62,6 +63,7 @@ export class RawJupyterSession extends BaseJupyterSession {
6263
public async connect(
6364
kernelSpec: IJupyterKernelSpec,
6465
timeout: number,
66+
interpreter?: PythonInterpreter,
6567
cancelToken?: CancellationToken
6668
): Promise<IJupyterKernelSpec | undefined> {
6769
// Save the resource that we connect with
@@ -71,7 +73,7 @@ export class RawJupyterSession extends BaseJupyterSession {
7173
// Notebook Provider level will handle the thrown error
7274
newSession = await waitForPromise(
7375
Promise.race([
74-
this.startRawSession(kernelSpec, cancelToken),
76+
this.startRawSession(kernelSpec, interpreter, cancelToken),
7577
createPromiseFromCancellation({
7678
cancelAction: 'reject',
7779
defaultValue: new CancellationError(),
@@ -94,7 +96,11 @@ export class RawJupyterSession extends BaseJupyterSession {
9496
sendTelemetryEvent(Telemetry.RawKernelSessionStartSuccess);
9597
traceInfo('Raw session started and connected');
9698
this.setSession(newSession);
99+
100+
// Update kernelspec and interpreter
97101
this.kernelSpec = newSession.kernelProcess?.kernelSpec;
102+
this.interpreter = interpreter;
103+
98104
this.outputChannel.appendLine(
99105
localize.DataScience.kernelStarted().format(this.kernelSpec.display_name || this.kernelSpec.name)
100106
);
@@ -115,7 +121,8 @@ export class RawJupyterSession extends BaseJupyterSession {
115121

116122
public async createNewKernelSession(
117123
kernel: IJupyterKernelSpec | LiveKernelModel,
118-
_timeoutMS: number
124+
_timeoutMS: number,
125+
interpreter?: PythonInterpreter
119126
): Promise<ISessionWithSocket> {
120127
if (!kernel || 'session' in kernel) {
121128
// Don't allow for connecting to a LiveKernelModel
@@ -124,7 +131,7 @@ export class RawJupyterSession extends BaseJupyterSession {
124131

125132
this.outputChannel.appendLine(localize.DataScience.kernelStarted().format(kernel.display_name || kernel.name));
126133

127-
return this.startRawSession(kernel);
134+
return this.startRawSession(kernel, interpreter);
128135
}
129136

130137
protected shutdownSession(
@@ -161,19 +168,20 @@ export class RawJupyterSession extends BaseJupyterSession {
161168

162169
protected startRestartSession() {
163170
if (!this.restartSessionPromise && this.session) {
164-
this.restartSessionPromise = this.createRestartSession(this.kernelSpec, this.session);
171+
this.restartSessionPromise = this.createRestartSession(this.kernelSpec, this.session, this.interpreter);
165172
}
166173
}
167174
protected async createRestartSession(
168175
kernelSpec: IJupyterKernelSpec | LiveKernelModel | undefined,
169176
_session: ISessionWithSocket,
177+
interpreter?: PythonInterpreter,
170178
cancelToken?: CancellationToken
171179
): Promise<ISessionWithSocket> {
172180
if (!kernelSpec || 'session' in kernelSpec) {
173181
// Need to have connected before restarting and can't use a LiveKernelModel
174182
throw new Error(localize.DataScience.sessionDisposed());
175183
}
176-
const startPromise = this.startRawSession(kernelSpec, cancelToken);
184+
const startPromise = this.startRawSession(kernelSpec, interpreter, cancelToken);
177185
return startPromise.then((session) => {
178186
this.kernelSelector.addKernelToIgnoreList(session.kernel);
179187
return session;
@@ -183,6 +191,7 @@ export class RawJupyterSession extends BaseJupyterSession {
183191
@captureTelemetry(Telemetry.RawKernelStartRawSession, undefined, true)
184192
private async startRawSession(
185193
kernelSpec: IJupyterKernelSpec,
194+
interpreter?: PythonInterpreter,
186195
cancelToken?: CancellationToken
187196
): Promise<RawSession> {
188197
const cancellationPromise = createPromiseFromCancellation({
@@ -193,7 +202,7 @@ export class RawJupyterSession extends BaseJupyterSession {
193202
cancellationPromise.catch(noop);
194203

195204
const process = await Promise.race([
196-
this.kernelLauncher.launch(kernelSpec, this.resource),
205+
this.kernelLauncher.launch(kernelSpec, this.resource, interpreter),
197206
cancellationPromise
198207
]);
199208

src/client/datascience/raw-kernel/rawNotebookProviderWrapper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import { IServiceContainer } from '../../ioc/types';
2020
import { JUPYTER_OUTPUT_CHANNEL } from '../constants';
2121
import { KernelSelector } from '../jupyter/kernels/kernelSelector';
22+
import { KernelService } from '../jupyter/kernels/kernelService';
2223
import { IRoleBasedObject, RoleBasedFactory } from '../jupyter/liveshare/roleBasedFactory';
2324
import { ILiveShareHasRole } from '../jupyter/liveshare/types';
2425
import { IKernelFinder, IKernelLauncher } from '../kernel-launcher/types';
@@ -43,6 +44,7 @@ type RawNotebookProviderClassType = {
4344
kernelLauncher: IKernelLauncher,
4445
kernelFinder: IKernelFinder,
4546
kernelSelector: KernelSelector,
47+
kernelService: KernelService,
4648
progressReporter: ProgressReporter,
4749
outputChannel: IOutputChannel
4850
): IRawNotebookProviderInterface;
@@ -67,6 +69,7 @@ export class RawNotebookProviderWrapper implements IRawNotebookProvider, ILiveSh
6769
@inject(IKernelLauncher) kernelLauncher: IKernelLauncher,
6870
@inject(IKernelFinder) kernelFinder: IKernelFinder,
6971
@inject(KernelSelector) kernelSelector: KernelSelector,
72+
@inject(KernelService) kernelService: KernelService,
7073
@inject(ProgressReporter) progressReporter: ProgressReporter,
7174
@inject(IOutputChannel) @named(JUPYTER_OUTPUT_CHANNEL) outputChannel: IOutputChannel
7275
) {
@@ -87,6 +90,7 @@ export class RawNotebookProviderWrapper implements IRawNotebookProvider, ILiveSh
8790
kernelLauncher,
8891
kernelFinder,
8992
kernelSelector,
93+
kernelService,
9094
progressReporter,
9195
outputChannel
9296
);

src/client/datascience/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,11 @@ export interface IJupyterSession extends IAsyncDisposable {
326326
content: KernelMessage.IInspectRequestMsg['content']
327327
): Promise<KernelMessage.IInspectReplyMsg | undefined>;
328328
sendInputReply(content: string): void;
329-
changeKernel(kernel: IJupyterKernelSpec | LiveKernelModel, timeoutMS: number): Promise<void>;
329+
changeKernel(
330+
kernel: IJupyterKernelSpec | LiveKernelModel,
331+
timeoutMS: number,
332+
interpreter?: PythonInterpreter
333+
): Promise<void>;
330334
registerCommTarget(
331335
targetName: string,
332336
callback: (comm: Kernel.IComm, msg: KernelMessage.ICommOpenMsg) => void | PromiseLike<void>

0 commit comments

Comments
 (0)