-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move NotebookControllerManager into the DI container for web #9690
Conversation
@@ -32,23 +32,6 @@ const config = { | |||
}, | |||
module: { | |||
rules: [ | |||
{ | |||
// JupyterServices imports node-fetch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As soon as I started importing these into the web bundle, this code failed to work.
I believe we don't need in the webbundle anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm not seeing the node-fetch usage anymore in jupyterlab services.
@@ -16,4 +21,15 @@ export function registerTypes(serviceManager: IServiceManager, _isDevMode: boole | |||
IExtensionSingleActivationService, | |||
PythonKernelCompletionProviderRegistration | |||
); | |||
serviceManager.addSingleton<IExtensionSyncActivationService>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved a bunch of stuff here from the 'notebooks' serviceRegistry. Seemed weird that notebooks would register stuff from the intellisense folder.
@@ -186,7 +173,7 @@ export class InteractiveWindow implements IInteractiveWindowLoadable { | |||
}; | |||
// When connecting, we need to update the sys info message | |||
this.updateSysInfoMessage(this.getSysInfoMessage(metadata, SysInfoReason.Start), false, sysInfoCell); | |||
const kernel = await connectToKernel( | |||
const kernel = await KernelConnector.connectToKernel( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved all the loose functions for connecting to a kernel into a new static class - KernelConnector.
* Keep track of the fact that we attempted to install a package into an interpreter. | ||
* (don't care whether it was successful or not). | ||
*/ | ||
export async function trackPackageInstalledIntoInterpreter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These loose functions didn't have any .node dependencies but were used elsewhere so moved them into a separate file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes those are helpers.ts? Or does that note fit here?
} | ||
|
||
this.scriptProviders = scriptProviders; | ||
// Use the platform specific factory to get our providers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to make this class platform agnostic, the creation of the script providers was moved to a platform specific factory.
The web version only support remote right now, but we might be able to do something about loading it from the CDN later.
@inject(IPythonExecutionFactory) private readonly factory: IPythonExecutionFactory | ||
) {} | ||
|
||
public getProviders(kernel: IKernel, uriConverter: ILocalResourceUriConverter, httpClient: IHttpClient) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function used to be in ipyWidgetScriptSourceProvider.ts. This is the node version.
Codecov Report
@@ Coverage Diff @@
## main #9690 +/- ##
====================================
Coverage 63% 63%
====================================
Files 201 204 +3
Lines 9826 9837 +11
Branches 1557 1556 -1
====================================
+ Hits 6230 6245 +15
+ Misses 3097 3091 -6
- Partials 499 501 +2
|
@injectable() | ||
export class ScriptSourceProviderFactory implements IWidgetScriptSourceProviderFactory { | ||
public getProviders(kernel: IKernel, _uriConverter: ILocalResourceUriConverter, httpClient: IHttpClient) { | ||
const scriptProviders: IWidgetScriptSourceProvider[] = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THis is the web version of the same function.
const sanitize = require('sanitize-filename'); | ||
|
||
@injectable() | ||
export class ScriptUriConverter implements ILocalResourceUriConverter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also had to separate out the URI converter part from the ipyWidgetScriptSource because it has node specific stuff in it too (reading/writing to local disk)
_connInfo: INotebookProviderConnection | undefined | ||
): Promise<KernelConnectionMetadata[]> { | ||
sendKernelListTelemetry(resource, []); | ||
return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will likely be the same as the node version once I get all of the session classes below this to work. For now there are two so I can stop this PR at this point.
// Instead there will be a IKernelFinder for web and an IKernelFinder for node. It will coalesce the local/remote bits. | ||
// But for now, it was simpler to just make this kernel finder that returns nothing. | ||
@injectable() | ||
export class LocalKernelFinder implements ILocalKernelFinder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class should be temporary. The reason this exists is because the NotebookControllerManager is doing special logic for local.
I hope to remove this entirely in a IKernelFinder implementation later.
import { getDisplayPath } from '../platform/common/platform/fs-paths'; | ||
import { IPythonExecutionFactory } from '../platform/common/process/types.node'; | ||
import { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of this file moved to helpers.ts. Only the 'node' specific stuff remained here.
import { SilentExecutionErrorOptions } from './helpers'; | ||
import { originalFSPath } from '../platform/vscode-path/resources'; | ||
|
||
export abstract class BaseKernel implements IKernel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created this as the common parts of the IKernel implementation.
configService, | ||
workspaceService, | ||
cellHashProviderFactory | ||
); | ||
this.kernelExecution = new KernelExecution( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
KernelExecution is node specific at the moment, so chopped off this work at this point.
When I get to implementing the kernel for web, KernelExecution will likely be the starting point.
/** | ||
* Class used for connecting a controller to an instance of an IKernel | ||
*/ | ||
export class KernelConnector { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all the functions that used to be in helper.ts for connecting to a kernel. There was even a little bit of state. Figured it made sense to put the functions into a class to hold the state.
import { noop } from '../platform/common/utils/misc'; | ||
import { IKernel, IKernelProvider, KernelOptions } from './types'; | ||
|
||
export abstract class BaseKernelProvider implements IKernelProvider { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
KernelProvider creates the Kernel class directly so I had to split it into two parts as well. This is the base class for them both.
this._onDidDisposeKernel.dispose(); | ||
this._onDidRestartKernel.dispose(); | ||
this._onKernelStatusChanged.dispose(); | ||
} | ||
public getOrCreate(uri: Uri, options: KernelOptions): IKernel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only function that's specific to each version.
import { INotebookControllerManager } from '../types'; | ||
|
||
@injectable() | ||
export class CondaControllerRefresher implements IExtensionSingleActivationService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file exists because the NotebookControllerManager used to listen to the conda service in order to refresh its list of controllers.
Conda Service is node only, so I created this one off to accomplish the same thing.
import { ConsoleForegroundColors, TraceOptions } from '../../platform/logging/types'; | ||
import { KernelConnector } from '../../kernels/kernelConnector'; | ||
|
||
export class VSCodeNotebookController implements Disposable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was the reason for this PR. And just getting this to build caused all of these other changes :)
import { IInteractiveWindowProvider, IInteractiveWindow } from './types'; | ||
|
||
export type InteractiveCellMetadata = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a src/interactive-window/types.ts maybe put the type into that?
import { fsPathToUri } from '../../vscode-path/utils'; | ||
import { EnvironmentVariables } from '../variables/types'; | ||
import { getOSType, OSType } from './platform'; | ||
export * from './platform'; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports | ||
const untildify = require('untildify'); | ||
const homePath = untildify('~'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was kinda redundant. Untilidify uses the homedir to replace ~
.
@@ -22,3 +22,7 @@ export function getOSType(platform: string = process.platform): OSType { | |||
return OSType.Unknown; | |||
} | |||
} | |||
|
|||
export function untildify(path: string, home: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the platform neutral version.
import { injectable } from 'inversify'; | ||
import { traceError } from '../logging'; | ||
import { ICryptoUtils, IHashFormat } from './types'; | ||
import * as hashjs from 'hash.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need a secure hash for this stuff, we just use it to create names of files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plus crypto is deprecated I think.
import { PythonEnvironment } from '.'; | ||
import { getOSType, OSType } from '../../common/utils/platform'; | ||
|
||
export function getInterpreterHash(interpreter: PythonEnvironment | {uri: Uri}){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these functions could be used in both .node and .web.
import { compare as strCompare, equalsIgnoreCase } from './strings'; | ||
import { Schemas } from './utils'; | ||
|
||
function originalFSPath(uri: URI): string { | ||
return uri.fsPath; | ||
export function originalFSPath(uri: URI | undefined): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might not have payed enough attention to where this was used, but the name seems a bit off now. A .path property for a web URI isn't an fspath.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually looking at the usage I think this works. NVMD
Fixes #9662