mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Remove preview flag for Configure Python wizard. (#11813)
This commit is contained in:
@@ -1,302 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as azdata from 'azdata';
|
||||
import { promises as fs } from 'fs';
|
||||
import * as utils from '../../common/utils';
|
||||
|
||||
import { JupyterServerInstallation } from '../../jupyter/jupyterServerInstallation';
|
||||
import { Deferred } from '../../common/promise';
|
||||
import { PythonPathLookup, PythonPathInfo } from '../pythonPathLookup';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class ConfigurePythonDialog {
|
||||
private dialog: azdata.window.Dialog;
|
||||
|
||||
private readonly DialogTitle = localize('configurePython.dialogName', "Configure Python for Notebooks");
|
||||
private readonly InstallButtonText = localize('configurePython.okButtonText', "Install");
|
||||
private readonly CancelButtonText = localize('configurePython.cancelButtonText', "Cancel");
|
||||
private readonly BrowseButtonText = localize('configurePython.browseButtonText', "Browse");
|
||||
private readonly LocationTextBoxTitle = localize('configurePython.locationTextBoxText', "Python Install Location");
|
||||
private readonly SelectFileLabel = localize('configurePython.selectFileLabel', "Select");
|
||||
private readonly InstallationNote = localize('configurePython.installNote', "This installation will take some time. It is recommended to not close the application until the installation is complete.");
|
||||
private readonly InvalidLocationMsg = localize('configurePython.invalidLocationMsg', "The specified install location is invalid.");
|
||||
private readonly PythonNotFoundMsg = localize('configurePython.pythonNotFoundMsg', "No python installation was found at the specified location.");
|
||||
|
||||
private pythonLocationDropdown: azdata.DropDownComponent;
|
||||
private pythonDropdownLoader: azdata.LoadingComponent;
|
||||
private browseButton: azdata.ButtonComponent;
|
||||
private newInstallButton: azdata.RadioButtonComponent;
|
||||
private existingInstallButton: azdata.RadioButtonComponent;
|
||||
|
||||
private setupComplete: Deferred<void>;
|
||||
private pythonPathsPromise: Promise<PythonPathInfo[]>;
|
||||
private usingCustomPath: boolean;
|
||||
|
||||
constructor(private jupyterInstallation: JupyterServerInstallation) {
|
||||
this.setupComplete = new Deferred<void>();
|
||||
this.pythonPathsPromise = (new PythonPathLookup()).getSuggestions();
|
||||
this.usingCustomPath = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialog to configure python installation for notebooks.
|
||||
* @param rejectOnCancel Specifies whether an error should be thrown after clicking Cancel.
|
||||
* @returns A promise that is resolved when the python installation completes.
|
||||
*/
|
||||
public showDialog(rejectOnCancel: boolean = false): Promise<void> {
|
||||
this.dialog = azdata.window.createModelViewDialog(this.DialogTitle);
|
||||
|
||||
this.initializeContent();
|
||||
|
||||
this.dialog.okButton.label = this.InstallButtonText;
|
||||
this.dialog.cancelButton.label = this.CancelButtonText;
|
||||
this.dialog.cancelButton.onClick(() => {
|
||||
if (rejectOnCancel) {
|
||||
this.setupComplete.reject(localize('configurePython.pythonInstallDeclined', "Python installation was declined."));
|
||||
} else {
|
||||
this.setupComplete.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
this.dialog.registerCloseValidator(() => this.handleInstall());
|
||||
|
||||
azdata.window.openDialog(this.dialog);
|
||||
|
||||
return this.setupComplete.promise;
|
||||
}
|
||||
|
||||
private initializeContent(): void {
|
||||
this.dialog.registerContent(async view => {
|
||||
this.pythonLocationDropdown = view.modelBuilder.dropDown()
|
||||
.withProperties<azdata.DropDownProperties>({
|
||||
value: undefined,
|
||||
values: [],
|
||||
width: '100%'
|
||||
}).component();
|
||||
this.pythonDropdownLoader = view.modelBuilder.loadingComponent()
|
||||
.withItem(this.pythonLocationDropdown)
|
||||
.withProperties<azdata.LoadingComponentProperties>({
|
||||
loading: false
|
||||
})
|
||||
.component();
|
||||
|
||||
this.browseButton = view.modelBuilder.button()
|
||||
.withProperties<azdata.ButtonProperties>({
|
||||
label: this.BrowseButtonText,
|
||||
width: '70px'
|
||||
}).component();
|
||||
this.browseButton.onDidClick(() => this.handleBrowse());
|
||||
|
||||
let installationNoteText = view.modelBuilder.text().withProperties({
|
||||
value: this.InstallationNote
|
||||
}).component();
|
||||
let noteWrapper = view.modelBuilder.flexContainer().component();
|
||||
noteWrapper.addItem(installationNoteText, {
|
||||
flex: '1 1 auto',
|
||||
CSSStyles: {
|
||||
'margin-top': '60px',
|
||||
'padding-left': '15px',
|
||||
'padding-right': '15px',
|
||||
'border': '1px solid'
|
||||
}
|
||||
});
|
||||
|
||||
let useExistingPython = JupyterServerInstallation.getExistingPythonSetting();
|
||||
this.createInstallRadioButtons(view.modelBuilder, useExistingPython);
|
||||
|
||||
let formModel = view.modelBuilder.formContainer()
|
||||
.withFormItems([{
|
||||
component: this.newInstallButton,
|
||||
title: localize('configurePython.installationType', "Installation Type")
|
||||
}, {
|
||||
component: this.existingInstallButton,
|
||||
title: ''
|
||||
}, {
|
||||
component: this.pythonDropdownLoader,
|
||||
title: this.LocationTextBoxTitle
|
||||
}, {
|
||||
component: this.browseButton,
|
||||
title: ''
|
||||
}, {
|
||||
component: noteWrapper,
|
||||
title: ''
|
||||
}]).component();
|
||||
|
||||
await view.initializeModel(formModel);
|
||||
|
||||
await this.updatePythonPathsDropdown(useExistingPython);
|
||||
});
|
||||
}
|
||||
|
||||
private async updatePythonPathsDropdown(useExistingPython: boolean): Promise<void> {
|
||||
await this.pythonDropdownLoader.updateProperties({ loading: true });
|
||||
try {
|
||||
let pythonPaths: PythonPathInfo[];
|
||||
let dropdownValues: azdata.CategoryValue[];
|
||||
if (useExistingPython) {
|
||||
pythonPaths = await this.pythonPathsPromise;
|
||||
if (pythonPaths && pythonPaths.length > 0) {
|
||||
dropdownValues = pythonPaths.map(path => {
|
||||
return {
|
||||
displayName: `${path.installDir} (Python ${path.version})`,
|
||||
name: path.installDir
|
||||
};
|
||||
});
|
||||
} else {
|
||||
dropdownValues = [{
|
||||
displayName: 'No supported Python versions found.',
|
||||
name: ''
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
let defaultPath = JupyterServerInstallation.DefaultPythonLocation;
|
||||
dropdownValues = [{
|
||||
displayName: `${defaultPath} (Default)`,
|
||||
name: defaultPath
|
||||
}];
|
||||
}
|
||||
|
||||
this.usingCustomPath = false;
|
||||
await this.pythonLocationDropdown.updateProperties({
|
||||
value: dropdownValues[0],
|
||||
values: dropdownValues
|
||||
});
|
||||
} finally {
|
||||
await this.pythonDropdownLoader.updateProperties({ loading: false });
|
||||
}
|
||||
}
|
||||
|
||||
private createInstallRadioButtons(modelBuilder: azdata.ModelBuilder, useExistingPython: boolean): void {
|
||||
let buttonGroup = 'installationType';
|
||||
this.newInstallButton = modelBuilder.radioButton()
|
||||
.withProperties<azdata.RadioButtonProperties>({
|
||||
name: buttonGroup,
|
||||
label: localize('configurePython.newInstall', "New Python installation"),
|
||||
checked: !useExistingPython
|
||||
}).component();
|
||||
this.newInstallButton.onDidClick(() => {
|
||||
this.existingInstallButton.checked = false;
|
||||
this.updatePythonPathsDropdown(false)
|
||||
.catch(err => {
|
||||
this.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
});
|
||||
|
||||
this.existingInstallButton = modelBuilder.radioButton()
|
||||
.withProperties<azdata.RadioButtonProperties>({
|
||||
name: buttonGroup,
|
||||
label: localize('configurePython.existingInstall', "Use existing Python installation"),
|
||||
checked: useExistingPython
|
||||
}).component();
|
||||
this.existingInstallButton.onDidClick(() => {
|
||||
this.newInstallButton.checked = false;
|
||||
this.updatePythonPathsDropdown(true)
|
||||
.catch(err => {
|
||||
this.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async handleInstall(): Promise<boolean> {
|
||||
let pythonLocation = (this.pythonLocationDropdown.value as azdata.CategoryValue).name;
|
||||
if (!pythonLocation || pythonLocation.length === 0) {
|
||||
this.showErrorMessage(this.InvalidLocationMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
let useExistingPython = !!this.existingInstallButton.checked;
|
||||
try {
|
||||
let isValid = await this.isFileValid(pythonLocation);
|
||||
if (!isValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (useExistingPython) {
|
||||
let exePath = JupyterServerInstallation.getPythonExePath(pythonLocation, true);
|
||||
let pythonExists = await utils.exists(exePath);
|
||||
if (!pythonExists) {
|
||||
this.showErrorMessage(this.PythonNotFoundMsg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.showErrorMessage(utils.getErrorMessage(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't wait on installation, since there's currently no Cancel functionality
|
||||
this.jupyterInstallation.startInstallProcess(false, { installPath: pythonLocation, existingPython: useExistingPython })
|
||||
.then(() => {
|
||||
this.setupComplete.resolve();
|
||||
})
|
||||
.catch(err => {
|
||||
this.setupComplete.reject(utils.getErrorMessage(err));
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async isFileValid(pythonLocation: string): Promise<boolean> {
|
||||
let self = this;
|
||||
try {
|
||||
const stats = await fs.stat(pythonLocation);
|
||||
if (stats.isFile()) {
|
||||
self.showErrorMessage(self.InvalidLocationMsg);
|
||||
return false;
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore error if folder doesn't exist, since it will be
|
||||
// created during installation
|
||||
if (err.code !== 'ENOENT') {
|
||||
self.showErrorMessage(err.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async handleBrowse(): Promise<void> {
|
||||
let options: vscode.OpenDialogOptions = {
|
||||
defaultUri: vscode.Uri.file(utils.getUserHome()),
|
||||
canSelectFiles: false,
|
||||
canSelectFolders: true,
|
||||
canSelectMany: false,
|
||||
openLabel: this.SelectFileLabel
|
||||
};
|
||||
|
||||
let fileUris: vscode.Uri[] = await vscode.window.showOpenDialog(options);
|
||||
if (fileUris && fileUris[0]) {
|
||||
let existingValues = <azdata.CategoryValue[]>this.pythonLocationDropdown.values;
|
||||
let filePath = fileUris[0].fsPath;
|
||||
let newValue = {
|
||||
displayName: `${filePath} (Custom)`,
|
||||
name: filePath
|
||||
};
|
||||
|
||||
if (this.usingCustomPath) {
|
||||
existingValues[0] = newValue;
|
||||
} else {
|
||||
existingValues.unshift(newValue);
|
||||
this.usingCustomPath = true;
|
||||
}
|
||||
|
||||
await this.pythonLocationDropdown.updateProperties({
|
||||
value: existingValues[0],
|
||||
values: existingValues
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private showErrorMessage(message: string): void {
|
||||
this.dialog.message = {
|
||||
text: message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import { LocalPipPackageManageProvider } from './localPipPackageManageProvider';
|
||||
import { LocalCondaPackageManageProvider } from './localCondaPackageManageProvider';
|
||||
import { ManagePackagesDialogModel, ManagePackageDialogOptions } from '../dialog/managePackages/managePackagesDialogModel';
|
||||
import { PyPiClient } from './pypiClient';
|
||||
import { ConfigurePythonDialog } from '../dialog/configurePython/configurePythonDialog';
|
||||
import { IconPathHelper } from '../common/iconHelper';
|
||||
|
||||
let untitledCounter = 0;
|
||||
@@ -248,20 +247,13 @@ export class JupyterController implements vscode.Disposable {
|
||||
}
|
||||
|
||||
public doConfigurePython(jupyterInstaller: JupyterServerInstallation): void {
|
||||
if (jupyterInstaller.previewFeaturesEnabled) {
|
||||
let pythonWizard = new ConfigurePythonWizard(jupyterInstaller);
|
||||
pythonWizard.start().catch((err: any) => {
|
||||
vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
pythonWizard.setupComplete.catch((err: any) => {
|
||||
vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
} else {
|
||||
let pythonDialog = new ConfigurePythonDialog(jupyterInstaller);
|
||||
pythonDialog.showDialog().catch((err: any) => {
|
||||
vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
}
|
||||
let pythonWizard = new ConfigurePythonWizard(jupyterInstaller);
|
||||
pythonWizard.start().catch((err: any) => {
|
||||
vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
pythonWizard.setupComplete.catch((err: any) => {
|
||||
vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
});
|
||||
}
|
||||
|
||||
public get jupyterInstallation() {
|
||||
|
||||
@@ -17,9 +17,6 @@ import * as constants from '../common/constants';
|
||||
import * as utils from '../common/utils';
|
||||
import { Deferred } from '../common/promise';
|
||||
import { ConfigurePythonWizard } from '../dialog/configurePython/configurePythonWizard';
|
||||
import { IPrompter, IQuestion, confirm } from '../prompts/question';
|
||||
import CodeAdapter from '../prompts/adapter';
|
||||
import { ConfigurePythonDialog } from '../dialog/configurePython/configurePythonDialog';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const msgInstallPkgProgress = localize('msgInstallPkgProgress', "Notebook dependencies installation is in progress");
|
||||
@@ -77,8 +74,6 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
|
||||
public static readonly DefaultPythonLocation = path.join(utils.getUserHome(), 'azuredatastudio-python');
|
||||
|
||||
private _prompter: IPrompter;
|
||||
|
||||
private readonly _commonPackages: PythonPkgDetails[] = [
|
||||
{
|
||||
name: 'jupyter',
|
||||
@@ -129,8 +124,6 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
this._usingConda = false;
|
||||
this._installInProgress = false;
|
||||
|
||||
this._prompter = new CodeAdapter();
|
||||
|
||||
if (process.platform !== constants.winPlatform) {
|
||||
this._expectedCondaPackages = this._commonPackages.concat([{ name: 'pykerberos', version: '1.2.1' }]);
|
||||
} else {
|
||||
@@ -189,7 +182,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
if (!pythonExists || forceInstall) {
|
||||
await this.installPythonPackage(backgroundOperation, this._usingExistingPython, this._pythonInstallationPath, this.outputChannel);
|
||||
}
|
||||
await this.upgradePythonPackages(false, forceInstall, specificPackages);
|
||||
await this.upgradePythonPackages(forceInstall, specificPackages);
|
||||
} catch (err) {
|
||||
this.outputChannel.appendLine(msgDependenciesInstallationFailed(utils.getErrorMessage(err)));
|
||||
throw err;
|
||||
@@ -476,53 +469,12 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
let isPythonInstalled = JupyterServerInstallation.isPythonInstalled();
|
||||
let areRequiredPackagesInstalled = await this.areRequiredPackagesInstalled(kernelDisplayName);
|
||||
if (!isPythonInstalled || !areRequiredPackagesInstalled) {
|
||||
if (this.previewFeaturesEnabled) {
|
||||
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);
|
||||
return pythonDialog.showDialog(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts user to upgrade certain python packages if they're below the minimum expected version.
|
||||
*/
|
||||
public async promptForPackageUpgrade(kernelName: string): Promise<void> {
|
||||
if (this._runningOnSAW) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (this._installInProgress) {
|
||||
vscode.window.showInformationMessage(msgWaitingForInstall);
|
||||
return this._installCompletion.promise;
|
||||
}
|
||||
|
||||
let requiredPackages: PythonPkgDetails[];
|
||||
if (this.previewFeaturesEnabled) {
|
||||
if (this._kernelSetupCache.get(kernelName)) {
|
||||
return;
|
||||
}
|
||||
requiredPackages = this.getRequiredPackagesForKernel(kernelName);
|
||||
}
|
||||
|
||||
this._installInProgress = true;
|
||||
this._installCompletion = new Deferred<void>();
|
||||
this.upgradePythonPackages(true, false, requiredPackages)
|
||||
.then(() => {
|
||||
this._installCompletion.resolve();
|
||||
this._installInProgress = false;
|
||||
this._kernelSetupCache.set(kernelName, true);
|
||||
})
|
||||
.catch(err => {
|
||||
let errorMsg = msgDependenciesInstallationFailed(utils.getErrorMessage(err));
|
||||
this._installCompletion.reject(errorMsg);
|
||||
this._installInProgress = false;
|
||||
let pythonWizard = new ConfigurePythonWizard(this);
|
||||
await pythonWizard.start(kernelDisplayName, true);
|
||||
return pythonWizard.setupComplete.then(() => {
|
||||
this._kernelSetupCache.set(kernelDisplayName, true);
|
||||
});
|
||||
return this._installCompletion.promise;
|
||||
}
|
||||
}
|
||||
|
||||
private async areRequiredPackagesInstalled(kernelDisplayName: string): Promise<boolean> {
|
||||
@@ -546,7 +498,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
return true;
|
||||
}
|
||||
|
||||
private async upgradePythonPackages(promptForUpgrade: boolean, forceInstall: boolean, specificPackages?: PythonPkgDetails[]): Promise<void> {
|
||||
private async upgradePythonPackages(forceInstall: boolean, specificPackages?: PythonPkgDetails[]): Promise<void> {
|
||||
let expectedCondaPackages: PythonPkgDetails[];
|
||||
let expectedPipPackages: PythonPkgDetails[];
|
||||
if (specificPackages) {
|
||||
@@ -598,63 +550,18 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
}
|
||||
|
||||
if (condaPackagesToInstall.length > 0 || pipPackagesToInstall.length > 0) {
|
||||
let doUpgrade: boolean;
|
||||
if (promptForUpgrade) {
|
||||
doUpgrade = await this._prompter.promptSingle<boolean>(<IQuestion>{
|
||||
type: confirm,
|
||||
message: localize('confirmPackageUpgrade', "Some required python packages need to be installed. Would you like to install them now?"),
|
||||
default: true
|
||||
});
|
||||
if (!doUpgrade) {
|
||||
throw new Error(localize('configurePython.packageInstallDeclined', "Package installation was declined."));
|
||||
}
|
||||
} else {
|
||||
doUpgrade = true;
|
||||
}
|
||||
|
||||
if (doUpgrade) {
|
||||
let installPromise = new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (this._usingConda) {
|
||||
await this.installCondaPackages(condaPackagesToInstall, true);
|
||||
}
|
||||
await this.installPipPackages(pipPackagesToInstall, true);
|
||||
resolve();
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
let installPromise = new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (this._usingConda) {
|
||||
await this.installCondaPackages(condaPackagesToInstall, true);
|
||||
}
|
||||
});
|
||||
|
||||
if (promptForUpgrade) {
|
||||
let packagesStr = condaPackagesToInstall.concat(pipPackagesToInstall).map(pkg => {
|
||||
return `${pkg.name}>=${pkg.version}`;
|
||||
}).join(' ');
|
||||
let taskName = localize('upgradePackages.pipInstall',
|
||||
"Installing {0}",
|
||||
packagesStr);
|
||||
|
||||
let backgroundTaskComplete = new Deferred<void>();
|
||||
azdata.tasks.startBackgroundOperation({
|
||||
displayName: taskName,
|
||||
description: taskName,
|
||||
isCancelable: false,
|
||||
operation: async op => {
|
||||
try {
|
||||
await installPromise;
|
||||
op.updateStatus(azdata.TaskStatus.Succeeded);
|
||||
backgroundTaskComplete.resolve();
|
||||
} catch (err) {
|
||||
let errorMsg = utils.getErrorMessage(err);
|
||||
op.updateStatus(azdata.TaskStatus.Failed, errorMsg);
|
||||
backgroundTaskComplete.reject(errorMsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
await backgroundTaskComplete.promise;
|
||||
} else {
|
||||
await installPromise;
|
||||
await this.installPipPackages(pipPackagesToInstall, true);
|
||||
resolve();
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
await installPromise;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,10 +782,6 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
public getRequiredPackagesForKernel(kernelName: string): PythonPkgDetails[] {
|
||||
return this._requiredKernelPackages.get(kernelName) ?? [];
|
||||
}
|
||||
|
||||
public get previewFeaturesEnabled(): boolean {
|
||||
return vscode.workspace.getConfiguration('workbench').get('enablePreviewFeatures');
|
||||
}
|
||||
}
|
||||
|
||||
export interface PythonPkgDetails {
|
||||
|
||||
@@ -105,9 +105,6 @@ export class LocalJupyterServerManager implements nb.ServerManager, vscode.Dispo
|
||||
private async doStartServer(kernelSpec: nb.IKernelSpec): Promise<IServerInstance> { // We can't find or create servers until the installation is complete
|
||||
let installation = this.options.jupyterInstallation;
|
||||
await installation.promptForPythonInstall(kernelSpec.display_name);
|
||||
if (!installation.previewFeaturesEnabled) {
|
||||
await installation.promptForPackageUpgrade(kernelSpec.display_name);
|
||||
}
|
||||
vscode.commands.executeCommand(BuiltInCommands.SetContext, CommandContext.NotebookPythonInstalled, true);
|
||||
|
||||
// Calculate the path to use as the notebook-dir for Jupyter based on the path of the uri of the
|
||||
|
||||
@@ -237,11 +237,7 @@ export class JupyterSession implements nb.ISession {
|
||||
public async changeKernel(kernelInfo: nb.IKernelSpec): Promise<nb.IKernel> {
|
||||
if (this._installation) {
|
||||
try {
|
||||
if (this._installation.previewFeaturesEnabled) {
|
||||
await this._installation.promptForPythonInstall(kernelInfo.display_name);
|
||||
} else {
|
||||
await this._installation.promptForPackageUpgrade(kernelInfo.display_name);
|
||||
}
|
||||
await this._installation.promptForPythonInstall(kernelInfo.display_name);
|
||||
} catch (err) {
|
||||
// Have to swallow the error here to prevent hangs when changing back to the old kernel.
|
||||
console.error(err.toString());
|
||||
|
||||
Reference in New Issue
Block a user