mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Simplify python reinstallation by only installing jupyter. (#11820)
This commit is contained in:
@@ -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(() => {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user