Skip to content

Commit fcb40b0

Browse files
committed
Find interpreter based on hash in kernelspec of nb metadata (#13856)
1 parent aaca611 commit fcb40b0

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33
import type { nbformat } from '@jupyterlab/coreutils';
44
import type { Kernel } from '@jupyterlab/services';
5+
import { sha256 } from 'hash.js';
56
import { inject, injectable } from 'inversify';
67
// tslint:disable-next-line: no-require-imports
78
import cloneDeep = require('lodash/cloneDeep');
@@ -18,6 +19,7 @@ import { PythonEnvironment } from '../../../pythonEnvironments/info';
1819
import { IEventNamePropertyMapping, sendTelemetryEvent } from '../../../telemetry';
1920
import { Commands, KnownNotebookLanguages, Settings, Telemetry } from '../../constants';
2021
import { IKernelFinder } from '../../kernel-launcher/types';
22+
import { getInterpreterInfoStoredInMetadata } from '../../notebookStorage/baseModel';
2123
import { reportAction } from '../../progress/decorator';
2224
import { ReportableAction } from '../../progress/types';
2325
import {
@@ -486,6 +488,17 @@ export class KernelSelector implements IKernelSelectionUsage {
486488
}
487489
}
488490
}
491+
private async findInterpreterStoredInNotebookMetadata(
492+
resource: Resource,
493+
notebookMetadata?: nbformat.INotebookMetadata
494+
): Promise<PythonEnvironment | undefined> {
495+
const info = getInterpreterInfoStoredInMetadata(notebookMetadata);
496+
if (!info) {
497+
return;
498+
}
499+
const interpreters = await this.interpreterService.getInterpreters(resource);
500+
return interpreters.find((item) => sha256().update(item.path).digest('hex') === info.hash);
501+
}
489502

490503
// Get our kernelspec and interpreter for a local raw connection
491504
private async getKernelForLocalRawConnection(
@@ -494,6 +507,19 @@ export class KernelSelector implements IKernelSelectionUsage {
494507
cancelToken?: CancellationToken,
495508
ignoreDependencyCheck?: boolean
496509
): Promise<KernelSpecConnectionMetadata | PythonKernelConnectionMetadata | undefined> {
510+
// If user had selected an interpreter (raw kernel), then that interpreter would be stored in the kernelspec metadata.
511+
// Find this matching interpreter & start that using raw kernel.
512+
const interpreterStoredInKernelSpec = await this.findInterpreterStoredInNotebookMetadata(
513+
resource,
514+
notebookMetadata
515+
);
516+
if (interpreterStoredInKernelSpec) {
517+
return {
518+
kind: 'startUsingPythonInterpreter',
519+
interpreter: interpreterStoredInKernelSpec
520+
};
521+
}
522+
497523
// First use our kernel finder to locate a kernelspec on disk
498524
const kernelSpec = await this.kernelFinder.findKernelSpec(
499525
resource,

src/client/datascience/notebookStorage/baseModel.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ type KernelIdListEntry = {
2323
kernelId: string | undefined;
2424
};
2525

26+
export function getInterpreterInfoStoredInMetadata(
27+
metadata?: nbformat.INotebookMetadata
28+
): { displayName: string; hash: string } | undefined {
29+
if (!metadata || !metadata.kernelspec || !metadata.kernelspec.name) {
30+
return;
31+
}
32+
// See `updateNotebookMetadata` to determine how & where exactly interpreter hash is stored.
33+
// tslint:disable-next-line: no-any
34+
const kernelSpecMetadata: undefined | any = metadata.kernelspec.metadata as any;
35+
const interpreterHash = kernelSpecMetadata?.interpreter?.hash;
36+
return interpreterHash ? { displayName: metadata.kernelspec.name, hash: interpreterHash } : undefined;
37+
}
38+
2639
// tslint:disable-next-line: cyclomatic-complexity
2740
export function updateNotebookMetadata(
2841
metadata?: nbformat.INotebookMetadata,
@@ -93,12 +106,29 @@ export function updateNotebookMetadata(
93106
metadata.kernelspec.display_name = displayName;
94107
kernelId = kernelSpecOrModel.id;
95108
}
109+
<<<<<<< HEAD
96110
try {
97111
// This is set only for when we select an interpreter.
98112
// tslint:disable-next-line: no-any
99113
delete (metadata.kernelspec as any).metadata;
100114
} catch {
101115
// Noop.
116+
=======
117+
} else if (kernelConnection?.kind === 'startUsingPythonInterpreter') {
118+
// Store interpreter name, we expect the kernel finder will find the corresponding interpreter based on this name.
119+
const name = kernelConnection.interpreter.displayName || '';
120+
if (metadata.kernelspec?.name !== name || metadata.kernelspec?.display_name !== name) {
121+
changed = true;
122+
metadata.kernelspec = {
123+
name,
124+
display_name: name,
125+
metadata: {
126+
interpreter: {
127+
hash: sha256().update(kernelConnection.interpreter.path).digest('hex')
128+
}
129+
}
130+
};
131+
>>>>>>> da389971d... Find interpreter based on hash in kernelspec of nb metadata (#13856)
102132
}
103133
}
104134
return { changed, kernelId };

0 commit comments

Comments
 (0)