Simplify python reinstallation by only installing jupyter. (#11820)

This commit is contained in:
Cory Rivera
2020-08-17 11:02:18 -07:00
committed by GitHub
parent b7e12cb8a7
commit 92db8df000
3 changed files with 21 additions and 95 deletions

View File

@@ -166,7 +166,7 @@ export class ConfigurePythonWizard {
let installSettings: PythonInstallSettings = { let installSettings: PythonInstallSettings = {
installPath: pythonLocation, installPath: pythonLocation,
existingPython: useExistingPython, existingPython: useExistingPython,
specificPackages: this.model.packagesToInstall packages: this.model.packagesToInstall
}; };
this.jupyterInstallation.startInstallProcess(false, installSettings) this.jupyterInstallation.startInstallProcess(false, installSettings)
.then(() => { .then(() => {

View File

@@ -39,7 +39,7 @@ describe('Notebook Extension Python Installation', function () {
jupyterController = notebookExtension.exports.getJupyterController() as JupyterController; jupyterController = notebookExtension.exports.getJupyterController() as JupyterController;
console.log('Start Jupyter Installation'); console.log('Start Jupyter Installation');
await jupyterController.jupyterInstallation.startInstallProcess(false, { installPath: pythonInstallDir, existingPython: false }); await jupyterController.jupyterInstallation.startInstallProcess(false, { installPath: pythonInstallDir, existingPython: false, packages: [] });
installComplete = true; installComplete = true;
console.log('Jupyter Installation is done'); console.log('Jupyter Installation is done');
}); });
@@ -66,14 +66,14 @@ describe('Notebook Extension Python Installation', function () {
console.log('Start Existing Python Installation'); console.log('Start Existing Python Installation');
let existingPythonPath = path.join(pythonInstallDir, pythonBundleVersion); let existingPythonPath = path.join(pythonInstallDir, pythonBundleVersion);
await install.startInstallProcess(false, { installPath: existingPythonPath, existingPython: true }); await install.startInstallProcess(false, { installPath: existingPythonPath, existingPython: true, packages: [] });
should(JupyterServerInstallation.isPythonInstalled()).be.true(); should(JupyterServerInstallation.isPythonInstalled()).be.true();
should(JupyterServerInstallation.getPythonInstallPath()).be.equal(existingPythonPath); should(JupyterServerInstallation.getPythonInstallPath()).be.equal(existingPythonPath);
should(JupyterServerInstallation.getExistingPythonSetting()).be.true(); should(JupyterServerInstallation.getExistingPythonSetting()).be.true();
// Redo "new" install to restore original settings. // Redo "new" install to restore original settings.
// The actual install should get skipped since it already exists. // The actual install should get skipped since it already exists.
await install.startInstallProcess(false, { installPath: pythonInstallDir, existingPython: false }); await install.startInstallProcess(false, { installPath: pythonInstallDir, existingPython: false, packages: [] });
should(JupyterServerInstallation.isPythonInstalled()).be.true(); should(JupyterServerInstallation.isPythonInstalled()).be.true();
should(JupyterServerInstallation.getPythonInstallPath()).be.equal(pythonInstallDir); should(JupyterServerInstallation.getPythonInstallPath()).be.equal(pythonInstallDir);
should(JupyterServerInstallation.getExistingPythonSetting()).be.false(); should(JupyterServerInstallation.getExistingPythonSetting()).be.false();

View File

@@ -38,7 +38,7 @@ function msgPackageRetrievalFailed(errorMessage: string): string { return locali
export interface PythonInstallSettings { export interface PythonInstallSettings {
installPath: string; installPath: string;
existingPython: boolean; existingPython: boolean;
specificPackages?: PythonPkgDetails[]; packages: PythonPkgDetails[];
} }
export interface IJupyterServerInstallation { export interface IJupyterServerInstallation {
installCondaPackages(packages: PythonPkgDetails[], useMinVersion: boolean): Promise<void>; installCondaPackages(packages: PythonPkgDetails[], useMinVersion: boolean): Promise<void>;
@@ -74,33 +74,6 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
public static readonly DefaultPythonLocation = path.join(utils.getUserHome(), 'azuredatastudio-python'); public static readonly DefaultPythonLocation = path.join(utils.getUserHome(), 'azuredatastudio-python');
private readonly _commonPackages: PythonPkgDetails[] = [
{
name: 'jupyter',
version: '1.0.0'
}, {
name: 'pandas',
version: '0.24.2'
}, {
name: 'sparkmagic',
version: '0.12.9'
}
];
private readonly _commonPipPackages: PythonPkgDetails[] = [
{
name: 'prose-codeaccelerator',
version: '1.3.0'
}, {
name: 'powershell-kernel',
version: '0.1.3'
}
];
private readonly _expectedPythonPackages = this._commonPackages.concat(this._commonPipPackages);
private readonly _expectedCondaPipPackages = this._commonPipPackages;
private readonly _expectedCondaPackages: PythonPkgDetails[];
private _kernelSetupCache: Map<string, boolean>; private _kernelSetupCache: Map<string, boolean>;
private readonly _requiredKernelPackages: Map<string, PythonPkgDetails[]>; private readonly _requiredKernelPackages: Map<string, PythonPkgDetails[]>;
private readonly _requiredPackagesSet: Set<string>; private readonly _requiredPackagesSet: Set<string>;
@@ -124,12 +97,6 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
this._usingConda = false; this._usingConda = false;
this._installInProgress = false; this._installInProgress = false;
if (process.platform !== constants.winPlatform) {
this._expectedCondaPackages = this._commonPackages.concat([{ name: 'pykerberos', version: '1.2.1' }]);
} else {
this._expectedCondaPackages = this._commonPackages;
}
this._kernelSetupCache = new Map<string, boolean>(); this._kernelSetupCache = new Map<string, boolean>();
this._requiredKernelPackages = new Map<string, PythonPkgDetails[]>(); this._requiredKernelPackages = new Map<string, PythonPkgDetails[]>();
@@ -170,7 +137,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
}); });
} }
private async installDependencies(backgroundOperation: azdata.BackgroundOperation, forceInstall: boolean, specificPackages?: PythonPkgDetails[]): Promise<void> { private async installDependencies(backgroundOperation: azdata.BackgroundOperation, forceInstall: boolean, packages: PythonPkgDetails[]): Promise<void> {
vscode.window.showInformationMessage(msgInstallPkgStart); vscode.window.showInformationMessage(msgInstallPkgStart);
this.outputChannel.show(true); this.outputChannel.show(true);
@@ -182,7 +149,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
if (!pythonExists || forceInstall) { if (!pythonExists || forceInstall) {
await this.installPythonPackage(backgroundOperation, this._usingExistingPython, this._pythonInstallationPath, this.outputChannel); await this.installPythonPackage(backgroundOperation, this._usingExistingPython, this._pythonInstallationPath, this.outputChannel);
} }
await this.upgradePythonPackages(forceInstall, specificPackages); await this.upgradePythonPackages(forceInstall, packages);
} catch (err) { } catch (err) {
this.outputChannel.appendLine(msgDependenciesInstallationFailed(utils.getErrorMessage(err))); this.outputChannel.appendLine(msgDependenciesInstallationFailed(utils.getErrorMessage(err)));
throw err; throw err;
@@ -401,7 +368,8 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
if (!installSettings) { if (!installSettings) {
installSettings = { installSettings = {
installPath: this._pythonInstallationPath, installPath: this._pythonInstallationPath,
existingPython: this._usingExistingPython existingPython: this._usingExistingPython,
packages: this.getRequiredPackagesForKernel(constants.python3DisplayName)
}; };
} }
@@ -433,7 +401,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
description: msgTaskName, description: msgTaskName,
isCancelable: false, isCancelable: false,
operation: op => { operation: op => {
this.installDependencies(op, forceInstall, installSettings.specificPackages) this.installDependencies(op, forceInstall, installSettings.packages)
.then(async () => { .then(async () => {
let notebookConfig = vscode.workspace.getConfiguration(constants.notebookConfigKey); let notebookConfig = vscode.workspace.getConfiguration(constants.notebookConfigKey);
await notebookConfig.update(constants.pythonPathConfigKey, this._pythonInstallationPath, vscode.ConfigurationTarget.Global); await notebookConfig.update(constants.pythonPathConfigKey, this._pythonInstallationPath, vscode.ConfigurationTarget.Global);
@@ -498,70 +466,28 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
return true; return true;
} }
private async upgradePythonPackages(forceInstall: boolean, specificPackages?: PythonPkgDetails[]): Promise<void> { private async upgradePythonPackages(forceInstall: boolean, packages: PythonPkgDetails[]): Promise<void> {
let expectedCondaPackages: PythonPkgDetails[]; let packagesToInstall: PythonPkgDetails[];
let expectedPipPackages: PythonPkgDetails[];
if (specificPackages) {
// Always install generic packages with pip, since conda may not have them.
expectedCondaPackages = [];
expectedPipPackages = specificPackages;
} else if (this._usingConda) {
expectedCondaPackages = this._expectedCondaPackages;
expectedPipPackages = this._expectedCondaPipPackages;
} else {
expectedCondaPackages = [];
expectedPipPackages = this._expectedPythonPackages;
}
let condaPackagesToInstall: PythonPkgDetails[];
let pipPackagesToInstall: PythonPkgDetails[];
if (forceInstall) { if (forceInstall) {
condaPackagesToInstall = expectedCondaPackages; packagesToInstall = packages;
pipPackagesToInstall = expectedPipPackages;
} else { } else {
condaPackagesToInstall = []; packagesToInstall = [];
pipPackagesToInstall = [];
// Conda packages
if (this._usingConda) {
let installedCondaPackages = await this.getInstalledCondaPackages();
let condaVersionMap = new Map<string, string>();
installedCondaPackages.forEach(pkg => condaVersionMap.set(pkg.name, pkg.version));
expectedCondaPackages.forEach(expectedPkg => {
let installedPkgVersion = condaVersionMap.get(expectedPkg.name);
if (!installedPkgVersion || utils.comparePackageVersions(installedPkgVersion, expectedPkg.version) < 0) {
condaPackagesToInstall.push(expectedPkg);
}
});
}
// Pip packages
let installedPipPackages = await this.getInstalledPipPackages(); let installedPipPackages = await this.getInstalledPipPackages();
let pipVersionMap = new Map<string, string>(); let pipVersionMap = new Map<string, string>();
installedPipPackages.forEach(pkg => pipVersionMap.set(pkg.name, pkg.version)); installedPipPackages.forEach(pkg => pipVersionMap.set(pkg.name, pkg.version));
expectedPipPackages.forEach(expectedPkg => { packages.forEach(pkg => {
let installedPkgVersion = pipVersionMap.get(expectedPkg.name); let installedPkgVersion = pipVersionMap.get(pkg.name);
if (!installedPkgVersion || utils.comparePackageVersions(installedPkgVersion, expectedPkg.version) < 0) { if (!installedPkgVersion || utils.comparePackageVersions(installedPkgVersion, pkg.version) < 0) {
pipPackagesToInstall.push(expectedPkg); packagesToInstall.push(pkg);
} }
}); });
} }
if (condaPackagesToInstall.length > 0 || pipPackagesToInstall.length > 0) { if (packagesToInstall.length > 0) {
let installPromise = new Promise(async (resolve, reject) => { // Always install generic packages with pip, since conda may not have them (like powershell-kernel).
try { await this.installPipPackages(packagesToInstall, true);
if (this._usingConda) {
await this.installCondaPackages(condaPackagesToInstall, true);
}
await this.installPipPackages(pipPackagesToInstall, true);
resolve();
} catch (err) {
reject(err);
}
});
await installPromise;
} }
} }