Skip to content

Commit

Permalink
Extension api for DataScience (#13923)
Browse files Browse the repository at this point in the history
* Extension API
* Api for DS
  • Loading branch information
DonJayamanne authored Sep 17, 2020
1 parent 016cce8 commit 7b3b541
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NotebookCell } from 'vscode-proposed';
import { isTestExecution } from './common/constants';
import { traceError } from './common/logger';
import { IConfigurationService, Resource } from './common/types';
import { JupyterExtensionIntegration } from './datascience/api/jupyterIntegration';
import { IDataViewerDataProvider, IDataViewerFactory } from './datascience/data-viewing/types';
import { IJupyterUriProvider, IJupyterUriProviderRegistration, INotebookExtensibility } from './datascience/types';
import { getDebugpyLauncherArgs, getDebugpyPackagePath } from './debugger/extension/adapter/remoteLaunchers';
Expand All @@ -26,6 +27,9 @@ export interface IExtensionApi {
* @memberof IExtensionApi
*/
ready: Promise<void>;
jupyter: {
registerHooks(): void;
};
debug: {
/**
* Generate an array of strings for commands to pass to the Python executable to launch the debugger for remote debugging.
Expand Down Expand Up @@ -103,12 +107,17 @@ export function buildApi(
const configurationService = serviceContainer.get<IConfigurationService>(IConfigurationService);
const interpreterService = serviceContainer.get<IInterpreterService>(IInterpreterService);
const notebookExtensibility = serviceContainer.get<INotebookExtensibility>(INotebookExtensibility);
serviceManager.addSingleton<JupyterExtensionIntegration>(JupyterExtensionIntegration, JupyterExtensionIntegration);
const jupyterIntegration = serviceContainer.get<JupyterExtensionIntegration>(JupyterExtensionIntegration);
const api: IExtensionApi = {
// 'ready' will propagate the exception, but we must log it here first.
ready: ready.catch((ex) => {
traceError('Failure during activation.', ex);
return Promise.reject(ex);
}),
jupyter: {
registerHooks: () => jupyterIntegration.integrateWithJupyterExtension()
},
debug: {
async getRemoteLauncherCommand(
host: string,
Expand Down
103 changes: 103 additions & 0 deletions src/client/datascience/api/jupyterIntegration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// tslint:disable-next-line: no-single-line-block-comment
/* eslint-disable comma-dangle */
// tslint:disable-next-line: no-single-line-block-comment
/* eslint-disable implicit-arrow-linebreak */
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { inject, injectable } from 'inversify';
import { CancellationToken, Event, Uri } from 'vscode';
import { InterpreterUri } from '../../common/installer/types';
import { IExtensions, IInstaller, InstallerResponse, Product, Resource } from '../../common/types';
import { IEnvironmentActivationService } from '../../interpreter/activation/types';
import { IInterpreterQuickPickItem, IInterpreterSelector } from '../../interpreter/configuration/types';
import { IInterpreterService } from '../../interpreter/contracts';
import { IWindowsStoreInterpreter } from '../../interpreter/locators/types';
import { WindowsStoreInterpreter } from '../../pythonEnvironments/discovery/locators/services/windowsStoreInterpreter';
import { PythonEnvironment } from '../../pythonEnvironments/info';

type PythonApiForJupyterExtension = {
/**
* IInterpreterService
*/
onDidChangeInterpreter: Event<void>;
/**
* IInterpreterService
*/
getInterpreters(resource?: Uri): Promise<PythonEnvironment[]>;
/**
* IInterpreterService
*/
getActiveInterpreter(resource?: Uri): Promise<PythonEnvironment | undefined>;
/**
* IInterpreterService
*/
getInterpreterDetails(pythonPath: string, resource?: Uri): Promise<undefined | PythonEnvironment>;

/**
* IEnvironmentActivationService
*/
getActivatedEnvironmentVariables(
resource: Resource,
interpreter?: PythonEnvironment,
allowExceptions?: boolean
): Promise<NodeJS.ProcessEnv | undefined>;
isWindowsStoreInterpreter(pythonPath: string): Promise<boolean>;
/**
* IWindowsStoreInterpreter
*/
getSuggestions(resource: Resource): Promise<IInterpreterQuickPickItem[]>;
/**
* IInstaller
*/
install(product: Product, resource?: InterpreterUri, cancel?: CancellationToken): Promise<InstallerResponse>;
};

type JupyterExtensionApi = {
registerPythonApi(interpreterService: PythonApiForJupyterExtension): void;
};

@injectable()
export class JupyterExtensionIntegration {
constructor(
@inject(IExtensions) private readonly extensions: IExtensions,
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
@inject(IInterpreterSelector) private readonly interpreterSelector: IInterpreterSelector,
@inject(WindowsStoreInterpreter) private readonly windowsStoreInterpreter: IWindowsStoreInterpreter,
@inject(IInstaller) private readonly installer: IInstaller,
@inject(IEnvironmentActivationService) private readonly envActivation: IEnvironmentActivationService
) {}

public async integrateWithJupyterExtension(): Promise<void> {
const jupyterExtension = this.extensions.getExtension<JupyterExtensionApi>('ms-ai-tools.jupyter');
if (!jupyterExtension) {
return;
}
await jupyterExtension.activate();
if (!jupyterExtension.isActive) {
return;
}
const jupyterExtensionApi = jupyterExtension.exports;
jupyterExtensionApi.registerPythonApi({
onDidChangeInterpreter: this.interpreterService.onDidChangeInterpreter,
getActiveInterpreter: async (resource?: Uri) => this.interpreterService.getActiveInterpreter(resource),
getInterpreterDetails: async (pythonPath: string) =>
this.interpreterService.getInterpreterDetails(pythonPath),
getInterpreters: async (resource: Uri | undefined) => this.interpreterService.getInterpreters(resource),
getActivatedEnvironmentVariables: async (
resource: Resource,
interpreter?: PythonEnvironment,
allowExceptions?: boolean
) => this.envActivation.getActivatedEnvironmentVariables(resource, interpreter, allowExceptions),
isWindowsStoreInterpreter: async (pythonPath: string): Promise<boolean> =>
this.windowsStoreInterpreter.isWindowsStoreInterpreter(pythonPath),
getSuggestions: async (resource: Resource): Promise<IInterpreterQuickPickItem[]> =>
this.interpreterSelector.getSuggestions(resource),
install: async (
product: Product,
resource?: InterpreterUri,
cancel?: CancellationToken
): Promise<InstallerResponse> => this.installer.install(product, resource, cancel)
});
}
}

0 comments on commit 7b3b541

Please sign in to comment.