Remove ApiWrapper from notebook extension (#11224)

* Remove ApiWrapper in notebook extension

* delete file

* Remove copyrights
This commit is contained in:
Charles Gagnon
2020-07-08 11:06:32 -07:00
committed by GitHub
parent 449a46d7fc
commit b3a01fcf77
38 changed files with 359 additions and 445 deletions

View File

@@ -18,7 +18,6 @@ import * as utils from '../common/utils';
import { IPrompter, IQuestion, confirm } from '../prompts/question';
import { AppContext } from '../common/appContext';
import { ApiWrapper } from '../common/apiWrapper';
import { LocalJupyterServerManager, ServerInstanceFactory } from './jupyterServerManager';
import { NotebookCompletionItemProvider } from '../intellisense/completionItemProvider';
import { JupyterNotebookProvider } from './jupyterNotebookProvider';
@@ -46,11 +45,7 @@ export class JupyterController implements vscode.Disposable {
constructor(private appContext: AppContext) {
this.prompter = new CodeAdapter();
this.outputChannel = this.appContext.apiWrapper.createOutputChannel(constants.extensionOutputChannel);
}
private get apiWrapper(): ApiWrapper {
return this.appContext.apiWrapper;
this.outputChannel = vscode.window.createOutputChannel(constants.extensionOutputChannel);
}
public get extensionContext(): vscode.ExtensionContext {
@@ -69,33 +64,32 @@ export class JupyterController implements vscode.Disposable {
public async activate(): Promise<boolean> {
this._jupyterInstallation = new JupyterServerInstallation(
this.extensionContext.extensionPath,
this.outputChannel,
this.apiWrapper);
this.outputChannel);
await this._jupyterInstallation.configurePackagePaths();
// Add command/task handlers
this.apiWrapper.registerTaskHandler(constants.jupyterOpenNotebookTask, (profile: azdata.IConnectionProfile) => {
azdata.tasks.registerTask(constants.jupyterOpenNotebookTask, (profile: azdata.IConnectionProfile) => {
return this.handleOpenNotebookTask(profile);
});
this.apiWrapper.registerTaskHandler(constants.jupyterNewNotebookTask, (profile: azdata.IConnectionProfile) => {
azdata.tasks.registerTask(constants.jupyterNewNotebookTask, (profile: azdata.IConnectionProfile) => {
return this.saveProfileAndCreateNotebook(profile);
});
this.apiWrapper.registerCommand(constants.jupyterNewNotebookCommand, (explorerContext: azdata.ObjectExplorerContext) => {
vscode.commands.registerCommand(constants.jupyterNewNotebookCommand, (explorerContext: azdata.ObjectExplorerContext) => {
return this.saveProfileAndCreateNotebook(explorerContext ? explorerContext.connectionProfile : undefined);
});
this.apiWrapper.registerCommand(constants.jupyterAnalyzeCommand, (explorerContext: azdata.ObjectExplorerContext) => {
vscode.commands.registerCommand(constants.jupyterAnalyzeCommand, (explorerContext: azdata.ObjectExplorerContext) => {
return this.saveProfileAndAnalyzeNotebook(explorerContext);
});
this.apiWrapper.registerCommand(constants.jupyterReinstallDependenciesCommand, () => { return this.handleDependenciesReinstallation(); });
this.apiWrapper.registerCommand(constants.jupyterManagePackages, async (args) => { return this.doManagePackages(args); });
this.apiWrapper.registerCommand(constants.jupyterConfigurePython, () => { return this.doConfigurePython(this._jupyterInstallation); });
vscode.commands.registerCommand(constants.jupyterReinstallDependenciesCommand, () => { return this.handleDependenciesReinstallation(); });
vscode.commands.registerCommand(constants.jupyterManagePackages, async (args) => { return this.doManagePackages(args); });
vscode.commands.registerCommand(constants.jupyterConfigurePython, () => { return this.doConfigurePython(this._jupyterInstallation); });
let supportedFileFilter: vscode.DocumentFilter[] = [
{ scheme: 'untitled', language: '*' }
];
this.registerNotebookProvider();
this.extensionContext.subscriptions.push(this.apiWrapper.registerCompletionItemProvider(supportedFileFilter, new NotebookCompletionItemProvider(this._notebookProvider)));
this.extensionContext.subscriptions.push(vscode.languages.registerCompletionItemProvider(supportedFileFilter, new NotebookCompletionItemProvider(this._notebookProvider)));
this.registerDefaultPackageManageProviders();
return true;
@@ -106,7 +100,6 @@ export class JupyterController implements vscode.Disposable {
documentPath: documentUri.fsPath,
jupyterInstallation: this._jupyterInstallation,
extensionContext: this.extensionContext,
apiWrapper: this.apiWrapper,
factory: this._serverInstanceFactory
}));
azdata.nb.registerNotebookProvider(this._notebookProvider);
@@ -127,14 +120,14 @@ export class JupyterController implements vscode.Disposable {
// EVENT HANDLERS //////////////////////////////////////////////////////
public async getDefaultConnection(): Promise<azdata.connection.ConnectionProfile> {
return await this.apiWrapper.getCurrentConnection();
return await azdata.connection.getCurrentConnection();
}
private async handleOpenNotebookTask(profile: azdata.IConnectionProfile): Promise<void> {
let notebookFileTypeName = localize('notebookFileType', "Notebooks");
let filter: { [key: string]: Array<string> } = {};
filter[notebookFileTypeName] = ['ipynb'];
let uris = await this.apiWrapper.showOpenDialog({
let uris = await vscode.window.showOpenDialog({
filters: filter,
canSelectFiles: true,
canSelectMany: false
@@ -144,7 +137,7 @@ export class JupyterController implements vscode.Disposable {
// Verify this is a .ipynb file since this isn't actually filtered on Mac/Linux
if (path.extname(fileUri.fsPath) !== '.ipynb') {
// in the future might want additional supported types
this.apiWrapper.showErrorMessage(localize('unsupportedFileType', "Only .ipynb Notebooks are supported"));
vscode.window.showErrorMessage(localize('unsupportedFileType', "Only .ipynb Notebooks are supported"));
} else {
await azdata.nb.showNotebookDocument(fileUri, {
connectionProfile: profile,
@@ -195,7 +188,7 @@ export class JupyterController implements vscode.Disposable {
await this._jupyterInstallation.startInstallProcess(true);
}
} catch (err) {
this.apiWrapper.showErrorMessage(utils.getErrorMessage(err));
vscode.window.showErrorMessage(utils.getErrorMessage(err));
}
}
@@ -205,7 +198,7 @@ export class JupyterController implements vscode.Disposable {
type: confirm,
message: localize('confirmReinstall', "Are you sure you want to reinstall?"),
default: true
}, this.apiWrapper);
});
}
public async doManagePackages(options?: ManagePackageDialogOptions): Promise<void> {
@@ -223,7 +216,7 @@ export class JupyterController implements vscode.Disposable {
packagesDialog.showDialog();
} catch (error) {
let message = utils.getErrorMessage(error);
this.apiWrapper.showErrorMessage(message);
vscode.window.showErrorMessage(message);
}
}
@@ -256,17 +249,17 @@ export class JupyterController implements vscode.Disposable {
public doConfigurePython(jupyterInstaller: JupyterServerInstallation): void {
if (jupyterInstaller.previewFeaturesEnabled) {
let pythonWizard = new ConfigurePythonWizard(this.apiWrapper, jupyterInstaller);
let pythonWizard = new ConfigurePythonWizard(jupyterInstaller);
pythonWizard.start().catch((err: any) => {
this.apiWrapper.showErrorMessage(utils.getErrorMessage(err));
vscode.window.showErrorMessage(utils.getErrorMessage(err));
});
pythonWizard.setupComplete.catch((err: any) => {
this.apiWrapper.showErrorMessage(utils.getErrorMessage(err));
vscode.window.showErrorMessage(utils.getErrorMessage(err));
});
} else {
let pythonDialog = new ConfigurePythonDialog(this.apiWrapper, jupyterInstaller);
let pythonDialog = new ConfigurePythonDialog(jupyterInstaller);
pythonDialog.showDialog().catch((err: any) => {
this.apiWrapper.showErrorMessage(utils.getErrorMessage(err));
vscode.window.showErrorMessage(utils.getErrorMessage(err));
});
}
}

View File

@@ -8,14 +8,13 @@ import * as vscode from 'vscode';
import { ServerConnection, SessionManager } from '@jupyterlab/services';
import { JupyterSessionManager } from './jupyterSessionManager';
import { ApiWrapper } from '../common/apiWrapper';
import { LocalJupyterServerManager } from './jupyterServerManager';
export class JupyterNotebookManager implements nb.NotebookManager, vscode.Disposable {
protected _serverSettings: ServerConnection.ISettings;
private _sessionManager: JupyterSessionManager;
constructor(private _serverManager: LocalJupyterServerManager, sessionManager?: JupyterSessionManager, private apiWrapper: ApiWrapper = new ApiWrapper()) {
constructor(private _serverManager: LocalJupyterServerManager, sessionManager?: JupyterSessionManager) {
let pythonEnvVarPath = this._serverManager && this._serverManager.jupyterServerInstallation && this._serverManager.jupyterServerInstallation.pythonEnvVarPath;
this._sessionManager = sessionManager || new JupyterSessionManager(pythonEnvVarPath);
this._serverManager.onServerStarted(() => {
@@ -49,7 +48,7 @@ export class JupyterNotebookManager implements nb.NotebookManager, vscode.Dispos
this._sessionManager.shutdownAll().then(() => this._sessionManager.dispose());
}
if (this._serverManager) {
this._serverManager.stopServer().then(success => undefined, error => this.apiWrapper.showErrorMessage(error));
this._serverManager.stopServer().then(success => undefined, error => vscode.window.showErrorMessage(error));
}
}
}

View File

@@ -13,7 +13,6 @@ import * as request from 'request';
import * as zip from 'adm-zip';
import * as tar from 'tar';
import { ApiWrapper } from '../common/apiWrapper';
import * as constants from '../common/constants';
import * as utils from '../common/utils';
import { Deferred } from '../common/promise';
@@ -62,7 +61,6 @@ export interface IJupyterServerInstallation {
installPythonPackage(backgroundOperation: azdata.BackgroundOperation, usingExistingPython: boolean, pythonInstallationPath: string, outputChannel: vscode.OutputChannel): Promise<void>;
}
export class JupyterServerInstallation implements IJupyterServerInstallation {
public apiWrapper: ApiWrapper;
public extensionPath: string;
public pythonBinPath: string;
public outputChannel: vscode.OutputChannel;
@@ -114,10 +112,9 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
private readonly _runningOnSAW: boolean;
constructor(extensionPath: string, outputChannel: vscode.OutputChannel, apiWrapper: ApiWrapper) {
constructor(extensionPath: string, outputChannel: vscode.OutputChannel) {
this.extensionPath = extensionPath;
this.outputChannel = outputChannel;
this.apiWrapper = apiWrapper;
this._runningOnSAW = vscode.env.appName.toLowerCase().indexOf('saw') > 0;
vscode.commands.executeCommand(constants.BuiltInCommands.SetContext, 'notebook:runningOnSAW', this._runningOnSAW);
@@ -126,8 +123,8 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
this._pythonInstallationPath = `${vscode.env.appRoot}\\ads-python`;
this._usingExistingPython = true;
} else {
this._pythonInstallationPath = JupyterServerInstallation.getPythonInstallPath(this.apiWrapper);
this._usingExistingPython = JupyterServerInstallation.getExistingPythonSetting(this.apiWrapper);
this._pythonInstallationPath = JupyterServerInstallation.getPythonInstallPath();
this._usingExistingPython = JupyterServerInstallation.getExistingPythonSetting();
}
this._usingConda = false;
this._installInProgress = false;
@@ -427,7 +424,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
}
if (this._installInProgress) {
this.apiWrapper.showInfoMessage(msgWaitingForInstall);
vscode.window.showInformationMessage(msgWaitingForInstall);
return this._installCompletion.promise;
}
@@ -438,14 +435,14 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
this._usingExistingPython = installSettings.existingPython;
await this.configurePackagePaths();
this.apiWrapper.startBackgroundOperation({
azdata.tasks.startBackgroundOperation({
displayName: msgTaskName,
description: msgTaskName,
isCancelable: false,
operation: op => {
this.installDependencies(op, forceInstall, installSettings.specificPackages)
.then(async () => {
let notebookConfig = this.apiWrapper.getConfiguration(constants.notebookConfigKey);
let notebookConfig = vscode.workspace.getConfiguration(constants.notebookConfigKey);
await notebookConfig.update(constants.pythonPathConfigKey, this._pythonInstallationPath, vscode.ConfigurationTarget.Global);
await notebookConfig.update(constants.existingPythonConfigKey, this._usingExistingPython, vscode.ConfigurationTarget.Global);
await this.configurePackagePaths();
@@ -472,21 +469,21 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
return Promise.resolve();
}
if (this._installInProgress) {
this.apiWrapper.showInfoMessage(msgWaitingForInstall);
vscode.window.showInformationMessage(msgWaitingForInstall);
return this._installCompletion.promise;
}
let isPythonInstalled = JupyterServerInstallation.isPythonInstalled(this.apiWrapper);
let isPythonInstalled = JupyterServerInstallation.isPythonInstalled();
let areRequiredPackagesInstalled = await this.areRequiredPackagesInstalled(kernelDisplayName);
if (!isPythonInstalled || !areRequiredPackagesInstalled) {
if (this.previewFeaturesEnabled) {
let pythonWizard = new ConfigurePythonWizard(this.apiWrapper, this);
let pythonWizard = new ConfigurePythonWizard(this);
await pythonWizard.start(kernelDisplayName, true);
return pythonWizard.setupComplete.then(() => {
this._kernelSetupCache.set(kernelDisplayName, true);
});
} else {
let pythonDialog = new ConfigurePythonDialog(this.apiWrapper, this);
let pythonDialog = new ConfigurePythonDialog(this);
return pythonDialog.showDialog(true);
}
}
@@ -500,7 +497,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
return Promise.resolve();
}
if (this._installInProgress) {
this.apiWrapper.showInfoMessage(msgWaitingForInstall);
vscode.window.showInformationMessage(msgWaitingForInstall);
return this._installCompletion.promise;
}
@@ -607,7 +604,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
type: confirm,
message: localize('confirmPackageUpgrade', "Some required python packages need to be installed. Would you like to install them now?"),
default: true
}, this.apiWrapper);
});
if (!doUpgrade) {
throw new Error(localize('configurePython.packageInstallDeclined', "Package installation was declined."));
}
@@ -637,7 +634,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
packagesStr);
let backgroundTaskComplete = new Deferred<void>();
this.apiWrapper.startBackgroundOperation({
azdata.tasks.startBackgroundOperation({
displayName: taskName,
description: taskName,
isCancelable: false,
@@ -667,7 +664,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
if (!fs.existsSync(pythonExePath)) {
return [];
}
} else if (!JupyterServerInstallation.isPythonInstalled(this.apiWrapper)) {
} else if (!JupyterServerInstallation.isPythonInstalled()) {
return [];
}
@@ -801,16 +798,15 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
/**
* Checks if a python executable exists at the "notebook.pythonPath" defined in the user's settings.
* @param apiWrapper An ApiWrapper to use when retrieving user settings info.
*/
public static isPythonInstalled(apiWrapper: ApiWrapper): boolean {
public static isPythonInstalled(): boolean {
// Don't use _pythonExecutable here, since it could be populated with a default value
let pathSetting = JupyterServerInstallation.getPythonPathSetting(apiWrapper);
let pathSetting = JupyterServerInstallation.getPythonPathSetting();
if (!pathSetting) {
return false;
}
let useExistingInstall = JupyterServerInstallation.getExistingPythonSetting(apiWrapper);
let useExistingInstall = JupyterServerInstallation.getExistingPythonSetting();
let pythonExe = JupyterServerInstallation.getPythonExePath(pathSetting, useExistingInstall);
// eslint-disable-next-line no-sync
return fs.existsSync(pythonExe);
@@ -819,34 +815,29 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
/**
* Returns the Python installation path defined in "notebook.pythonPath" in the user's settings.
* Returns a default path if the setting is not defined.
* @param apiWrapper An ApiWrapper to use when retrieving user settings info.
*/
public static getPythonInstallPath(apiWrapper: ApiWrapper): string {
let userPath = JupyterServerInstallation.getPythonPathSetting(apiWrapper);
public static getPythonInstallPath(): string {
let userPath = JupyterServerInstallation.getPythonPathSetting();
return userPath ? userPath : JupyterServerInstallation.DefaultPythonLocation;
}
public static getExistingPythonSetting(apiWrapper: ApiWrapper): boolean {
public static getExistingPythonSetting(): boolean {
let useExistingPython = false;
if (apiWrapper) {
let notebookConfig = apiWrapper.getConfiguration(constants.notebookConfigKey);
if (notebookConfig) {
useExistingPython = !!notebookConfig[constants.existingPythonConfigKey];
}
let notebookConfig = vscode.workspace.getConfiguration(constants.notebookConfigKey);
if (notebookConfig) {
useExistingPython = !!notebookConfig[constants.existingPythonConfigKey];
}
return useExistingPython;
}
public static getPythonPathSetting(apiWrapper: ApiWrapper): string {
public static getPythonPathSetting(): string {
let path = undefined;
if (apiWrapper) {
let notebookConfig = apiWrapper.getConfiguration(constants.notebookConfigKey);
if (notebookConfig) {
let configPythonPath = notebookConfig[constants.pythonPathConfigKey];
// eslint-disable-next-line no-sync
if (configPythonPath && fs.existsSync(configPythonPath)) {
path = configPythonPath;
}
let notebookConfig = vscode.workspace.getConfiguration(constants.notebookConfigKey);
if (notebookConfig) {
let configPythonPath = notebookConfig[constants.pythonPathConfigKey];
// eslint-disable-next-line no-sync
if (configPythonPath && fs.existsSync(configPythonPath)) {
path = configPythonPath;
}
}
return path;
@@ -888,7 +879,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
}
public get previewFeaturesEnabled(): boolean {
return this.apiWrapper.getConfiguration('workbench').get('enablePreviewFeatures');
return vscode.workspace.getConfiguration('workbench').get('enablePreviewFeatures');
}
}

View File

@@ -10,7 +10,6 @@ import { ServerConnection } from '@jupyterlab/services';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { ApiWrapper } from '../common/apiWrapper';
import { JupyterServerInstallation } from './jupyterServerInstallation';
import * as utils from '../common/utils';
import { IServerInstance } from './common';
@@ -21,18 +20,15 @@ export interface IServerManagerOptions {
documentPath: string;
jupyterInstallation: JupyterServerInstallation;
extensionContext: vscode.ExtensionContext;
apiWrapper?: ApiWrapper;
factory?: ServerInstanceFactory;
}
export class LocalJupyterServerManager implements nb.ServerManager, vscode.Disposable {
private _serverSettings: Partial<ServerConnection.ISettings>;
private _onServerStarted = new vscode.EventEmitter<void>();
private _instanceOptions: IInstanceOptions;
private _apiWrapper: ApiWrapper;
private _jupyterServer: IServerInstance;
factory: ServerInstanceFactory;
constructor(private options: IServerManagerOptions) {
this._apiWrapper = options.apiWrapper || new ApiWrapper();
this.factory = options.factory || new ServerInstanceFactory();
}
@@ -74,7 +70,7 @@ export class LocalJupyterServerManager implements nb.ServerManager, vscode.Dispo
public dispose(): void {
this.stopServer().catch(err => {
let msg = utils.getErrorMessage(err);
this._apiWrapper.showErrorMessage(localize('shutdownError', "Shutdown of Notebook server failed: {0}", msg));
vscode.window.showErrorMessage(localize('shutdownError', "Shutdown of Notebook server failed: {0}", msg));
});
}
@@ -124,7 +120,7 @@ export class LocalJupyterServerManager implements nb.ServerManager, vscode.Dispo
// /path2/nb2.ipynb
// /path2/nb3.ipynb
// ... will result in 2 notebook servers being started, one for /path1/ and one for /path2/
let notebookDir = this._apiWrapper.getWorkspacePathFromUri(vscode.Uri.file(this.documentPath));
let notebookDir = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(this.documentPath))?.uri.fsPath;
if (!notebookDir) {
let docDir;
// If a folder is passed in for documentPath, use the folder instead of calling dirname