From 802c9227f2d952121d0eca85b8eec7dbc811e202 Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Mon, 27 Sep 2021 16:22:10 -0700 Subject: [PATCH] Use the kernel to check for ipykernel 6 version, instead of the python installer. This works for both local and remote. --- news/2 Fixes/7576.md | 1 + .../datascience/jupyter/kernels/kernel.ts | 4 +- .../datascience/jupyter/kernels/types.ts | 3 +- .../debugger/jupyter/debuggingManager.ts | 62 +++++++++---------- 4 files changed, 33 insertions(+), 37 deletions(-) create mode 100644 news/2 Fixes/7576.md diff --git a/news/2 Fixes/7576.md b/news/2 Fixes/7576.md new file mode 100644 index 00000000000..ca4a3522052 --- /dev/null +++ b/news/2 Fixes/7576.md @@ -0,0 +1 @@ +Use the kernel to check for ipykernel 6 version, instead of the python installer. This works for both local and remote. \ No newline at end of file diff --git a/src/client/datascience/jupyter/kernels/kernel.ts b/src/client/datascience/jupyter/kernels/kernel.ts index b5a3e30403f..5a05dc04976 100644 --- a/src/client/datascience/jupyter/kernels/kernel.ts +++ b/src/client/datascience/jupyter/kernels/kernel.ts @@ -164,12 +164,12 @@ export class Kernel implements IKernel { await promise; return promise; } - public async executeHidden(code: string) { + public async executeHidden(code: string): Promise { const stopWatch = new StopWatch(); const notebookPromise = this.startNotebook(); const promise = notebookPromise.then((nb) => executeSilently(nb.session, code)); this.trackNotebookCellPerceivedColdTime(stopWatch, notebookPromise, promise).catch(noop); - await promise; + return promise; } public async start(options: { disableUI?: boolean } = {}): Promise { await this.startNotebook(options); diff --git a/src/client/datascience/jupyter/kernels/types.ts b/src/client/datascience/jupyter/kernels/types.ts index a2131ae4f6d..4d359c8432d 100644 --- a/src/client/datascience/jupyter/kernels/types.ts +++ b/src/client/datascience/jupyter/kernels/types.ts @@ -23,6 +23,7 @@ import type { InterruptResult, KernelSocketInformation } from '../../types'; +import type { nbformat } from '@jupyterlab/coreutils'; export type LiveKernelModel = IJupyterKernel & Partial & { session: Session.IModel }; @@ -146,7 +147,7 @@ export interface IKernel extends IAsyncDisposable { interrupt(): Promise; restart(): Promise; executeCell(cell: NotebookCell): Promise; - executeHidden(code: string): Promise; + executeHidden(code: string): Promise; } export type KernelOptions = { diff --git a/src/client/debugger/jupyter/debuggingManager.ts b/src/client/debugger/jupyter/debuggingManager.ts index 974ee3ddfe9..6a784c20ba4 100644 --- a/src/client/debugger/jupyter/debuggingManager.ts +++ b/src/client/debugger/jupyter/debuggingManager.ts @@ -12,7 +12,6 @@ import { DebugSession, NotebookCell, DebugSessionOptions, - ProgressLocation, DebugAdapterDescriptor, Event, EventEmitter, @@ -20,7 +19,7 @@ import { } from 'vscode'; import * as path from 'path'; import { IKernel, IKernelProvider } from '../../datascience/jupyter/kernels/types'; -import { IConfigurationService, IDisposable, Product, ProductInstallStatus } from '../../common/types'; +import { IConfigurationService, IDisposable } from '../../common/types'; import { KernelDebugAdapter } from './kernelDebugAdapter'; import { INotebookProvider } from '../../datascience/types'; import { IExtensionSingleActivationService } from '../../activation/types'; @@ -35,9 +34,7 @@ import { Commands as DSCommands } from '../../datascience/constants'; import { IFileSystem } from '../../common/platform/types'; import { IDebuggingManager, IKernelDebugAdapterConfig, KernelDebugMode } from '../types'; import { DebuggingTelemetry, pythonKernelDebugAdapter } from '../constants'; -import { IPythonInstaller } from '../../api/types'; import { sendTelemetryEvent } from '../../telemetry'; -import { PythonEnvironment } from '../../pythonEnvironments/info'; import { DebugCellController, RunByLineController } from './debugControllers'; import { assertIsDebugConfig } from './helper'; import { Debugger } from './debugger'; @@ -53,7 +50,6 @@ export class DebuggingManager implements IExtensionSingleActivationService, IDeb private notebookToDebugAdapter = new Map(); private notebookToRunByLineController = new Map(); private notebookInProgress = new Set(); - private cache = new Map(); private readonly disposables: IDisposable[] = []; private _doneDebugging = new EventEmitter(); @@ -65,7 +61,6 @@ export class DebuggingManager implements IExtensionSingleActivationService, IDeb @inject(IApplicationShell) private readonly appShell: IApplicationShell, @inject(IVSCodeNotebook) private readonly vscNotebook: IVSCodeNotebook, @inject(IFileSystem) private fs: IFileSystem, - @inject(IPythonInstaller) private pythonInstaller: IPythonInstaller, @inject(IConfigurationService) private settings: IConfigurationService ) { this.debuggingInProgress = new ContextKey(EditorContexts.DebuggingInProgress, this.commandManager); @@ -245,12 +240,7 @@ export class DebuggingManager implements IExtensionSingleActivationService, IDeb try { this.notebookInProgress.add(editor.document); - if ( - await this.checkForIpykernel6( - editor.document, - mode === KernelDebugMode.RunByLine ? DataScience.startingRunByLine() : undefined - ) - ) { + if (await this.checkForIpykernel6(editor.document)) { switch (mode) { case KernelDebugMode.Everything: await this.startDebugging(editor.document); @@ -421,31 +411,35 @@ export class DebuggingManager implements IExtensionSingleActivationService, IDeb return kernel; } - private async checkForIpykernel6(doc: NotebookDocument, waitingMessage?: string): Promise { + private async checkForIpykernel6(doc: NotebookDocument): Promise { try { - const controller = this.notebookControllerManager.getSelectedNotebookController(doc); - const interpreter = controller?.connection.interpreter; - if (interpreter) { - const cacheResult = this.cache.get(interpreter); - if (cacheResult === true) { - return true; + let kernel = this.kernelProvider.get(doc); + + if (!kernel) { + const controller = this.notebookControllerManager.getSelectedNotebookController(doc); + + if (controller) { + kernel = this.kernelProvider.getOrCreate(doc, { + metadata: controller.connection, + controller: controller?.controller, + resourceUri: doc.uri + }); } + } - const checkCompatible = () => - this.pythonInstaller.isProductVersionCompatible(Product.ipykernel, '>=6.0.0', interpreter); - const status = waitingMessage - ? await this.appShell.withProgress( - { location: ProgressLocation.Notification, title: waitingMessage }, - checkCompatible - ) - : await checkCompatible(); - const result = status === ProductInstallStatus.Installed; - - sendTelemetryEvent(DebuggingTelemetry.ipykernel6Status, undefined, { - status: result ? 'installed' : 'notInstalled' - }); - this.cache.set(interpreter, result); - return result; + if (kernel) { + const code = 'import ipykernel\nprint(ipykernel.__version__)'; + const output = await kernel.executeHidden(code); + + if (output[0].text) { + const majorVersion = Number(output[0].text.toString().charAt(0)); + const result = majorVersion >= 6; + + sendTelemetryEvent(DebuggingTelemetry.ipykernel6Status, undefined, { + status: result ? 'installed' : 'notInstalled' + }); + return result; + } } } catch { traceError('Debugging: Could not check for ipykernel 6');