Add dialog to notebooks for managing Pip packages (#5944)

This commit is contained in:
Cory Rivera
2019-06-10 17:02:31 -07:00
committed by GitHub
parent 14a6bf581c
commit ff38bc8143
9 changed files with 613 additions and 23 deletions

View File

@@ -24,6 +24,7 @@ import { NotebookCompletionItemProvider } from '../intellisense/completionItemPr
import { JupyterNotebookProvider } from './jupyterNotebookProvider';
import { ConfigurePythonDialog } from '../dialog/configurePythonDialog';
import CodeAdapter from '../prompts/adapter';
import { ManagePackagesDialog } from '../dialog/managePackages/managePackagesDialog';
let untitledCounter = 0;
@@ -73,7 +74,7 @@ export class JupyterController implements vscode.Disposable {
});
this.apiWrapper.registerCommand(constants.jupyterReinstallDependenciesCommand, () => { return this.handleDependenciesReinstallation(); });
this.apiWrapper.registerCommand(constants.jupyterInstallPackages, () => { return this.doManagePackages(); });
this.apiWrapper.registerCommand(constants.jupyterManagePackages, () => { return this.doManagePackages(); });
this.apiWrapper.registerCommand(constants.jupyterConfigurePython, () => { return this.doConfigurePython(this._jupyterInstallation); });
let supportedFileFilter: vscode.DocumentFilter[] = [
@@ -194,10 +195,8 @@ export class JupyterController implements vscode.Disposable {
public doManagePackages(): void {
try {
let terminal = this.apiWrapper.createTerminalWithOptions({ cwd: this.getPythonBinDir() });
terminal.show(true);
let shellType = this.apiWrapper.getConfiguration().get('terminal.integrated.shell.windows');
terminal.sendText(this.getTextToSendToTerminal(shellType), true);
let packagesDialog = new ManagePackagesDialog(this._jupyterInstallation);
packagesDialog.showDialog();
} catch (error) {
let message = utils.getErrorMessage(error);
this.apiWrapper.showErrorMessage(message);
@@ -225,10 +224,6 @@ export class JupyterController implements vscode.Disposable {
}
}
private getPythonBinDir(): string {
return JupyterServerInstallation.getPythonBinPath(this.apiWrapper);
}
public get jupyterInstallation() {
return this._jupyterInstallation;
}

View File

@@ -347,6 +347,28 @@ export default class JupyterServerInstallation {
}
}
public async getInstalledPipPackages(): Promise<PythonPkgDetails[]> {
let cmd = `"${this.pythonExecutable}" -m pip list --format=json`;
let packagesInfo = await this.executeBufferedCommand(cmd);
let packagesResult: PythonPkgDetails[] = [];
if (packagesInfo) {
packagesResult = <PythonPkgDetails[]>JSON.parse(packagesInfo);
}
return packagesResult;
}
public installPipPackage(packageName: string, version: string): Promise<void> {
let cmd = `"${this.pythonExecutable}" -m pip install ${packageName}==${version}`;
return this.executeStreamedCommand(cmd);
}
public uninstallPipPackages(packages: PythonPkgDetails[]): Promise<void> {
let packagesStr = packages.map(pkg => `${pkg.name}==${pkg.version}`).join(' ');
let cmd = `"${this.pythonExecutable}" -m pip uninstall -y ${packagesStr}`;
return this.executeStreamedCommand(cmd);
}
private async installOfflinePipPackages(): Promise<void> {
let installJupyterCommand: string;
if (process.platform === constants.winPlatform) {
@@ -357,7 +379,7 @@ export default class JupyterServerInstallation {
if (installJupyterCommand) {
this.outputChannel.show(true);
this.outputChannel.appendLine(localize('msgInstallStart', "Installing required packages to run Notebooks..."));
await this.executeCommand(installJupyterCommand);
await this.executeStreamedCommand(installJupyterCommand);
this.outputChannel.appendLine(localize('msgJupyterInstallDone', "... Jupyter installation complete."));
} else {
return Promise.resolve();
@@ -378,7 +400,7 @@ export default class JupyterServerInstallation {
if (installSparkMagic) {
this.outputChannel.show(true);
this.outputChannel.appendLine(localize('msgInstallingSpark', "Installing SparkMagic..."));
await this.executeCommand(installSparkMagic);
await this.executeStreamedCommand(installSparkMagic);
}
}
@@ -387,10 +409,10 @@ export default class JupyterServerInstallation {
this.outputChannel.appendLine(localize('msgInstallStart', "Installing required packages to run Notebooks..."));
let installCommand = `"${this._pythonExecutable}" -m pip install jupyter==1.0.0 pandas==0.24.2`;
await this.executeCommand(installCommand);
await this.executeStreamedCommand(installCommand);
installCommand = `"${this._pythonExecutable}" -m pip install prose-codeaccelerator==1.3.0 --extra-index-url https://prose-python-packages.azurewebsites.net`;
await this.executeCommand(installCommand);
await this.executeStreamedCommand(installCommand);
this.outputChannel.appendLine(localize('msgJupyterInstallDone', "... Jupyter installation complete."));
}
@@ -403,18 +425,22 @@ export default class JupyterServerInstallation {
if (process.platform !== constants.winPlatform) {
installCommand = `${installCommand} pykerberos==1.2.1`;
}
await this.executeCommand(installCommand);
await this.executeStreamedCommand(installCommand);
installCommand = `"${this._pythonExecutable}" -m pip install prose-codeaccelerator==1.3.0 --extra-index-url https://prose-python-packages.azurewebsites.net`;
await this.executeCommand(installCommand);
await this.executeStreamedCommand(installCommand);
this.outputChannel.appendLine(localize('msgJupyterInstallDone', "... Jupyter installation complete."));
}
private async executeCommand(command: string): Promise<void> {
private async executeStreamedCommand(command: string): Promise<void> {
await utils.executeStreamedCommand(command, { env: this.execOptions.env }, this.outputChannel);
}
private async executeBufferedCommand(command: string): Promise<string> {
return await utils.executeBufferedCommand(command, { env: this.execOptions.env });
}
public get pythonExecutable(): string {
return this._pythonExecutable;
}
@@ -500,10 +526,20 @@ export default class JupyterServerInstallation {
pythonBinPathSuffix);
}
public async getPythonPackagesPath(): Promise<string> {
let cmd = `"${this.pythonExecutable}" -c "import site; print(site.getsitepackages()[0])"`;
return await this.executeBufferedCommand(cmd);
}
public static getPythonExePath(pythonInstallPath: string, useExistingInstall: boolean): string {
return path.join(
pythonInstallPath,
useExistingInstall ? '' : constants.pythonBundleVersion,
process.platform === constants.winPlatform ? 'python.exe' : 'bin/python3');
}
}
export interface PythonPkgDetails {
name: string;
version: string;
}