Skip to content

Commit 8b8fbbf

Browse files
authored
Fixes to blowing away of kernel info & not using right startup info (#14295)
1 parent 68aeb27 commit 8b8fbbf

File tree

18 files changed

+199
-66
lines changed

18 files changed

+199
-66
lines changed

build/ci/templates/test_phases.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ steps:
118118
python -c "import sys;print(sys.executable)"
119119
displayName: 'pip install functional requirements'
120120
condition: and(succeeded(), eq(variables['NeedsPythonFunctionalReqs'], 'true'))
121-
121+
122122
# Add CONDA to the path so anaconda works
123123
#
124124
# This task will only run if variable `NeedsPythonFunctionalReqs` is true.
@@ -422,7 +422,7 @@ steps:
422422
# Upload the test results to Azure DevOps to facilitate test reporting in their UX.
423423
- task: PublishTestResults@2
424424
displayName: 'Publish functional tests results'
425-
condition: or(contains(variables['TestsToRun'], 'testFunctional'), contains(variables['TestsToRun'], 'testParallelFunctional'))
425+
condition: or(contains(variables['TestsToRun'], 'testFunctional'), contains(variables['TestsToRun'], 'testParallelFunctional'))
426426
inputs:
427427
testResultsFiles: '$(Build.ArtifactStagingDirectory)/test-junit*.xml'
428428
testRunTitle: 'functional-$(Agent.Os)-Py$(pythonVersion)'
@@ -446,7 +446,7 @@ steps:
446446
- script: |
447447
npm run testDataScience
448448
continueOnError: true
449-
displayName: 'Run DataScience Tests in VSCode Insiders'
449+
displayName: 'Run Native Notebook Tests in VSCode Insiders'
450450
condition: and(succeeded(), contains(variables['TestsToRun'], 'testDataScience'), not(contains(variables['TestsToRun'], 'testDataScienceInVSCode')))
451451
env:
452452
DISPLAY: :10

build/ci/vscode-python-pr-validation.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ stages:
5252
'Single Workspace':
5353
TestsToRun: 'testSingleWorkspace'
5454
NeedsPythonTestReqs: true
55-
'DataScience':
55+
'Native Notebook':
5656
TestsToRun: 'testDataScience'
5757
NeedsPythonTestReqs: true
5858
NeedsPythonFunctionalReqs: true

src/client/datascience/baseJupyterSession.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ export abstract class BaseJupyterSession implements IJupyterSession {
122122
);
123123
}
124124
}
125-
125+
public async requestKernelInfo(): Promise<KernelMessage.IInfoReplyMsg> {
126+
if (!this.session) {
127+
throw new Error('Cannot request KernelInfo, Session not initialized.');
128+
}
129+
return this.session.kernel.requestKernelInfo();
130+
}
126131
public async changeKernel(kernelConnection: KernelConnectionMetadata, timeoutMS: number): Promise<void> {
127132
let newSession: ISessionWithSocket | undefined;
128133

src/client/datascience/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ export namespace LiveShareCommands {
574574
export const getUsableJupyterPython = 'getUsableJupyterPython';
575575
export const executeObservable = 'executeObservable';
576576
export const getSysInfo = 'getSysInfo';
577+
export const requestKernelInfo = 'requestKernelInfo';
577578
export const serverResponse = 'serverResponse';
578579
export const catchupRequest = 'catchupRequest';
579580
export const syncRequest = 'synchRequest';

src/client/datascience/jupyter/jupyterNotebook.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ export class JupyterNotebookBase implements INotebook {
241241
}
242242
}
243243
}
244-
244+
public async requestKernelInfo(): Promise<KernelMessage.IInfoReplyMsg> {
245+
return this.session.requestKernelInfo();
246+
}
245247
public get onSessionStatusChanged(): Event<ServerStatus> {
246248
if (!this.onStatusChangedEvent) {
247249
this.onStatusChangedEvent = new EventEmitter<ServerStatus>();

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'use strict';
55

66
import { nbformat } from '@jupyterlab/coreutils';
7+
import { KernelMessage } from '@jupyterlab/services';
78
import { Observable } from 'rxjs/Observable';
89
import { Subject } from 'rxjs/Subject';
910
import * as uuid from 'uuid/v4';
@@ -18,11 +19,10 @@ import {
1819
} from 'vscode';
1920
import { ServerStatus } from '../../../../datascience-ui/interactive-common/mainState';
2021
import { IApplicationShell, ICommandManager, IVSCodeNotebook } from '../../../common/application/types';
21-
import { traceError } from '../../../common/logger';
22+
import { traceError, traceWarning } from '../../../common/logger';
2223
import { IDisposableRegistry } from '../../../common/types';
2324
import { createDeferred, Deferred } from '../../../common/utils/async';
2425
import { noop } from '../../../common/utils/misc';
25-
import { IInterpreterService } from '../../../interpreter/contracts';
2626
import { CodeSnippets } from '../../constants';
2727
import { getDefaultNotebookContent, updateNotebookMetadata } from '../../notebookStorage/baseModel';
2828
import {
@@ -51,6 +51,10 @@ export class Kernel implements IKernel {
5151
get onDisposed(): Event<void> {
5252
return this._onDisposed.event;
5353
}
54+
private _info?: KernelMessage.IInfoReplyMsg['content'];
55+
get info(): KernelMessage.IInfoReplyMsg['content'] | undefined {
56+
return this._info;
57+
}
5458
get status(): ServerStatus {
5559
return this.notebook?.status ?? ServerStatus.NotStarted;
5660
}
@@ -79,7 +83,6 @@ export class Kernel implements IKernel {
7983
private readonly disposables: IDisposableRegistry,
8084
private readonly launchTimeout: number,
8185
commandManager: ICommandManager,
82-
interpreterService: IInterpreterService,
8386
private readonly errorHandler: IDataScienceErrorHandler,
8487
editorProvider: INotebookEditorProvider,
8588
private readonly kernelProvider: IKernelProvider,
@@ -90,12 +93,12 @@ export class Kernel implements IKernel {
9093
this.kernelExecution = new KernelExecution(
9194
kernelProvider,
9295
commandManager,
93-
interpreterService,
9496
errorHandler,
9597
editorProvider,
9698
kernelSelectionUsage,
9799
appShell,
98-
vscNotebook
100+
vscNotebook,
101+
metadata
99102
);
100103
}
101104
public async executeCell(cell: NotebookCell): Promise<void> {
@@ -124,8 +127,9 @@ export class Kernel implements IKernel {
124127
} else {
125128
await this.validate(this.uri);
126129
const metadata = ((getDefaultNotebookContent().metadata || {}) as unknown) as nbformat.INotebookMetadata;
130+
// Create a dummy notebook metadata & update the metadata before starting the notebook (required to ensure we fetch & start the right kernel).
131+
// Lower layers of code below getOrCreateNotebook searches for kernels again using the metadata.
127132
updateNotebookMetadata(metadata, this.metadata);
128-
129133
this._notebookPromise = this.notebookProvider.getOrCreateNotebook({
130134
identity: this.uri,
131135
resource: this.uri,
@@ -232,6 +236,10 @@ export class Kernel implements IKernel {
232236
if (isPythonKernelConnection(this.metadata)) {
233237
await this.notebook.setLaunchingFile(this.uri.fsPath);
234238
}
239+
await this.notebook
240+
.requestKernelInfo()
241+
.then((item) => (this._info = item.content))
242+
.catch(traceWarning.bind('Failed to request KernelInfo'));
235243
await this.notebook.waitForIdle(this.launchTimeout);
236244
}
237245

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

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@ import { NotebookCell, NotebookCellRunState, NotebookDocument } from 'vscode';
77
import { IApplicationShell, ICommandManager, IVSCodeNotebook } from '../../../common/application/types';
88
import { IDisposable } from '../../../common/types';
99
import { noop } from '../../../common/utils/misc';
10-
import { IInterpreterService } from '../../../interpreter/contracts';
1110
import { captureTelemetry } from '../../../telemetry';
1211
import { Commands, Telemetry, VSCodeNativeTelemetry } from '../../constants';
1312
import { MultiCancellationTokenSource } from '../../notebook/helpers/multiCancellationToken';
1413
import { IDataScienceErrorHandler, INotebook, INotebookEditorProvider } from '../../types';
1514
import { CellExecution, CellExecutionFactory } from './cellExecution';
16-
import type { IKernel, IKernelProvider, IKernelSelectionUsage } from './types';
15+
import type { IKernel, IKernelProvider, IKernelSelectionUsage, KernelConnectionMetadata } from './types';
1716
// tslint:disable-next-line: no-var-requires no-require-imports
1817
const vscodeNotebookEnums = require('vscode') as typeof import('vscode-proposed');
1918

@@ -35,12 +34,12 @@ export class KernelExecution implements IDisposable {
3534
constructor(
3635
private readonly kernelProvider: IKernelProvider,
3736
private readonly commandManager: ICommandManager,
38-
private readonly interpreterService: IInterpreterService,
3937
errorHandler: IDataScienceErrorHandler,
4038
editorProvider: INotebookEditorProvider,
4139
readonly kernelSelectionUsage: IKernelSelectionUsage,
4240
readonly appShell: IApplicationShell,
43-
readonly vscNotebook: IVSCodeNotebook
41+
readonly vscNotebook: IVSCodeNotebook,
42+
readonly metadata: Readonly<KernelConnectionMetadata>
4443
) {
4544
this.executionFactory = new CellExecutionFactory(errorHandler, editorProvider, appShell, vscNotebook);
4645
}
@@ -142,15 +141,7 @@ export class KernelExecution implements IDisposable {
142141
await this.validateKernel(document);
143142
let kernel = this.kernelProvider.get(document.uri);
144143
if (!kernel) {
145-
const activeInterpreter = await this.interpreterService.getActiveInterpreter(document.uri);
146-
kernel = this.kernelProvider.getOrCreate(document.uri, {
147-
metadata: {
148-
interpreter: activeInterpreter!,
149-
kernelModel: undefined,
150-
kernelSpec: undefined,
151-
kind: 'startUsingPythonInterpreter'
152-
}
153-
});
144+
kernel = this.kernelProvider.getOrCreate(document.uri, { metadata: this.metadata });
154145
}
155146
if (!kernel) {
156147
throw new Error('Unable to create a Kernel to run cell');

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { Uri } from 'vscode';
99
import { IApplicationShell, ICommandManager, IVSCodeNotebook } from '../../../common/application/types';
1010
import { traceInfo, traceWarning } from '../../../common/logger';
1111
import { IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry } from '../../../common/types';
12-
import { IInterpreterService } from '../../../interpreter/contracts';
1312
import { IDataScienceErrorHandler, INotebookEditorProvider, INotebookProvider } from '../../types';
1413
import { Kernel } from './kernel';
1514
import { KernelSelector } from './kernelSelector';
@@ -24,7 +23,6 @@ export class KernelProvider implements IKernelProvider {
2423
@inject(INotebookProvider) private notebookProvider: INotebookProvider,
2524
@inject(IConfigurationService) private configService: IConfigurationService,
2625
@inject(ICommandManager) private readonly commandManager: ICommandManager,
27-
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
2826
@inject(IDataScienceErrorHandler) private readonly errorHandler: IDataScienceErrorHandler,
2927
@inject(INotebookEditorProvider) private readonly editorProvider: INotebookEditorProvider,
3028
@inject(KernelSelector) private readonly kernelSelectionUsage: IKernelSelectionUsage,
@@ -50,7 +48,6 @@ export class KernelProvider implements IKernelProvider {
5048
this.disposables,
5149
waitForIdleTimeout,
5250
this.commandManager,
53-
this.interpreterService,
5451
this.errorHandler,
5552
this.editorProvider,
5653
this,

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
'use strict';
55

6-
import type { Session } from '@jupyterlab/services';
6+
import type { KernelMessage, Session } from '@jupyterlab/services';
77
import type { Observable } from 'rxjs/Observable';
88
import type { CancellationToken, Event, QuickPickItem, Uri } from 'vscode';
99
import { NotebookCell, NotebookDocument } from '../../../../../types/vscode-proposed';
@@ -130,6 +130,11 @@ export interface IKernel extends IAsyncDisposable {
130130
readonly onRestarted: Event<void>;
131131
readonly status: ServerStatus;
132132
readonly disposed: boolean;
133+
/**
134+
* Kernel information, used to save in ipynb in the metadata.
135+
* Crucial for non-python notebooks, else we save the incorrect information.
136+
*/
137+
readonly info?: KernelMessage.IInfoReplyMsg['content'];
133138
readonly kernelSocket: Observable<KernelSocketInformation | undefined>;
134139
start(): Promise<void>;
135140
interrupt(): Promise<InterruptResult>;

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ export class GuestJupyterNotebook
205205
}
206206
}
207207

208+
public async requestKernelInfo(): Promise<KernelMessage.IInfoReplyMsg> {
209+
// This is a special case. Ask the shared server
210+
const service = await this.waitForService();
211+
if (service) {
212+
return service.request(LiveShareCommands.getSysInfo, []);
213+
} else {
214+
throw new Error('No LiveShare service to get KernelInfo');
215+
}
216+
}
217+
208218
public async getCompletion(
209219
_cellCode: string,
210220
_offsetInCode: number,

src/client/datascience/notebook/helpers/helpers.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { JupyterNotebookView } from '../constants';
2727
// tslint:disable-next-line: no-var-requires no-require-imports
2828
const vscodeNotebookEnums = require('vscode') as typeof import('vscode-proposed');
2929
// tslint:disable-next-line: no-require-imports
30+
import { KernelMessage } from '@jupyterlab/services';
31+
// tslint:disable-next-line: no-require-imports
3032
import cloneDeep = require('lodash/cloneDeep');
3133
import { isUntitledFile } from '../../../common/utils/misc';
3234
import { KernelConnectionMetadata } from '../../jupyter/kernels/types';
@@ -54,7 +56,10 @@ export function isJupyterNotebook(option: NotebookDocument | string) {
5456
}
5557
}
5658

57-
const kernelInformationForNotebooks = new WeakMap<NotebookDocument, KernelConnectionMetadata | undefined>();
59+
const kernelInformationForNotebooks = new WeakMap<
60+
NotebookDocument,
61+
{ metadata?: KernelConnectionMetadata | undefined; kernelInfo?: KernelMessage.IInfoReplyMsg['content'] }
62+
>();
5863

5964
export function getNotebookMetadata(document: NotebookDocument): nbformat.INotebookMetadata | undefined {
6065
// tslint:disable-next-line: no-any
@@ -70,8 +75,9 @@ export function getNotebookMetadata(document: NotebookDocument): nbformat.INoteb
7075
notebookContent = { ...content, metadata: { ...metadata, language_info } } as any;
7176
}
7277
notebookContent = cloneDeep(notebookContent);
73-
if (kernelInformationForNotebooks.has(document)) {
74-
updateNotebookMetadata(notebookContent.metadata, kernelInformationForNotebooks.get(document));
78+
const data = kernelInformationForNotebooks.get(document);
79+
if (data && data.metadata) {
80+
updateNotebookMetadata(notebookContent.metadata, data.metadata, data.kernelInfo);
7581
}
7682

7783
return notebookContent.metadata;
@@ -88,7 +94,20 @@ export function updateKernelInNotebookMetadata(
8894
document: NotebookDocument,
8995
kernelConnection: KernelConnectionMetadata | undefined
9096
) {
91-
kernelInformationForNotebooks.set(document, kernelConnection);
97+
const data = { ...(kernelInformationForNotebooks.get(document) || {}) };
98+
data.metadata = kernelConnection;
99+
kernelInformationForNotebooks.set(document, data);
100+
}
101+
export function updateKernelInfoInNotebookMetadata(
102+
document: NotebookDocument,
103+
kernelInfo: KernelMessage.IInfoReplyMsg['content']
104+
) {
105+
if (kernelInformationForNotebooks.get(document)?.kernelInfo === kernelInfo) {
106+
return;
107+
}
108+
const data = { ...(kernelInformationForNotebooks.get(document) || {}) };
109+
data.kernelInfo = kernelInfo;
110+
kernelInformationForNotebooks.set(document, data);
92111
}
93112
/**
94113
* Converts a NotebookModel into VSCode friendly format.

0 commit comments

Comments
 (0)