com.jetbrains.python.packaging.PyPackageManagerUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of python-community Show documentation
Show all versions of python-community Show documentation
A packaging of the IntelliJ Community Edition python-community library.
This is release number 1 of trunk branch 142.
The newest version!
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.packaging;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunCanceledByUserException;
import com.intellij.icons.AllIcons;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.webcore.packaging.PackageManagementService;
import com.intellij.webcore.packaging.PackagesNotificationPanel;
import com.jetbrains.python.packaging.ui.PyPackageManagementService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.util.*;
/**
* @author vlan
*/
public class PyPackageManagerUI {
@NotNull private static final Logger LOG = Logger.getInstance(PyPackageManagerUI.class);
@Nullable private Listener myListener;
@NotNull private Project myProject;
@NotNull private Sdk mySdk;
public interface Listener {
void started();
void finished(List exceptions);
}
public PyPackageManagerUI(@NotNull Project project, @NotNull Sdk sdk, @Nullable Listener listener) {
myProject = project;
mySdk = sdk;
myListener = listener;
}
public void installManagement() {
ProgressManager.getInstance().run(new InstallManagementTask(myProject, mySdk, myListener));
}
public void install(@NotNull final List requirements, @NotNull final List extraArgs) {
ProgressManager.getInstance().run(new InstallTask(myProject, mySdk, requirements, extraArgs, myListener));
}
public void uninstall(@NotNull final List packages) {
if (checkDependents(packages)) {
return;
}
ProgressManager.getInstance().run(new UninstallTask(myProject, mySdk, myListener, packages));
}
private boolean checkDependents(@NotNull final List packages) {
try {
final Map> dependentPackages = collectDependents(packages, mySdk);
final int[] warning = {0};
if (!dependentPackages.isEmpty()) {
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
if (dependentPackages.size() == 1) {
String message = "You are attempting to uninstall ";
List dep = new ArrayList();
int size = 1;
for (Map.Entry> entry : dependentPackages.entrySet()) {
final Set value = entry.getValue();
size = value.size();
dep.add(entry.getKey() + " package which is required for " + StringUtil.join(value, ", "));
}
message += StringUtil.join(dep, "\n");
message += size == 1 ? " package" : " packages";
message += "\n\nDo you want to proceed?";
warning[0] = Messages.showYesNoDialog(message, "Warning",
AllIcons.General.BalloonWarning);
}
else {
String message = "You are attempting to uninstall packages which are required for another packages.\n\n";
List dep = new ArrayList();
for (Map.Entry> entry : dependentPackages.entrySet()) {
dep.add(entry.getKey() + " -> " + StringUtil.join(entry.getValue(), ", "));
}
message += StringUtil.join(dep, "\n");
message += "\n\nDo you want to proceed?";
warning[0] = Messages.showYesNoDialog(message, "Warning",
AllIcons.General.BalloonWarning);
}
}
}, ModalityState.current());
}
if (warning[0] != Messages.YES) return true;
}
catch (ExecutionException e) {
LOG.info("Error loading packages dependents: " + e.getMessage(), e);
}
return false;
}
private static Map> collectDependents(@NotNull final List packages,
Sdk sdk) throws ExecutionException {
Map> dependentPackages = new HashMap>();
for (PyPackage pkg : packages) {
final Set dependents = PyPackageManager.getInstance(sdk).getDependents(pkg);
if (dependents != null && !dependents.isEmpty()) {
for (PyPackage dependent : dependents) {
if (!packages.contains(dependent)) {
dependentPackages.put(pkg.getName(), dependents);
}
}
}
}
return dependentPackages;
}
private abstract static class PackagingTask extends Task.Backgroundable {
private static final String PACKAGING_GROUP_ID = "Packaging";
@NotNull protected final Sdk mySdk;
@Nullable protected final Listener myListener;
public PackagingTask(@Nullable Project project, @NotNull Sdk sdk, @NotNull String title, @Nullable Listener listener) {
super(project, title);
mySdk = sdk;
myListener = listener;
}
@Override
public void run(@NotNull ProgressIndicator indicator) {
taskStarted(indicator);
taskFinished(runTask(indicator));
}
@NotNull
protected abstract List runTask(@NotNull ProgressIndicator indicator);
@NotNull
protected abstract String getSuccessTitle();
@NotNull
protected abstract String getSuccessDescription();
@NotNull
protected abstract String getFailureTitle();
protected void taskStarted(@NotNull ProgressIndicator indicator) {
final PackagingNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(PackagingNotification.class, getProject());
for (PackagingNotification notification : notifications) {
notification.expire();
}
indicator.setText(getTitle() + "...");
if (myListener != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myListener.started();
}
});
}
}
protected void taskFinished(@NotNull final List exceptions) {
final Ref notificationRef = new Ref(null);
if (exceptions.isEmpty()) {
notificationRef.set(new PackagingNotification(PACKAGING_GROUP_ID, getSuccessTitle(), getSuccessDescription(),
NotificationType.INFORMATION, null));
}
else {
final PackageManagementService.ErrorDescription description = PyPackageManagementService.toErrorDescription(exceptions, mySdk);
if (description != null) {
final String firstLine = getTitle() + ": error occurred.";
final NotificationListener listener = new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification,
@NotNull HyperlinkEvent event) {
assert myProject != null;
final String title = StringUtil.capitalizeWords(getFailureTitle(), true);
PackagesNotificationPanel.showError(title, description);
}
};
notificationRef.set(new PackagingNotification(PACKAGING_GROUP_ID, getFailureTitle(), firstLine + " Details...",
NotificationType.ERROR, listener));
}
}
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (myListener != null) {
myListener.finished(exceptions);
}
final Notification notification = notificationRef.get();
if (notification != null) {
notification.notify(myProject);
}
}
});
}
private static class PackagingNotification extends Notification{
public PackagingNotification(@NotNull String groupDisplayId,
@NotNull String title,
@NotNull String content,
@NotNull NotificationType type, @Nullable NotificationListener listener) {
super(groupDisplayId, title, content, type, listener);
}
}
}
private static class InstallTask extends PackagingTask {
@NotNull private final List myRequirements;
@NotNull private final List myExtraArgs;
public InstallTask(@Nullable Project project,
@NotNull Sdk sdk,
@NotNull List requirements,
@NotNull List extraArgs,
@Nullable Listener listener) {
super(project, sdk, "Installing packages", listener);
myRequirements = requirements;
myExtraArgs = extraArgs;
}
@NotNull
@Override
protected List runTask(@NotNull ProgressIndicator indicator) {
final List exceptions = new ArrayList();
final int size = myRequirements.size();
final PyPackageManager manager = PyPackageManagers.getInstance().forSdk(mySdk);
for (int i = 0; i < size; i++) {
final PyRequirement requirement = myRequirements.get(i);
indicator.setText(String.format("Installing package '%s'...", requirement));
if (i == 0) {
indicator.setIndeterminate(true);
}
else {
indicator.setIndeterminate(false);
indicator.setFraction((double)i / size);
}
try {
manager.install(Collections.singletonList(requirement), myExtraArgs);
}
catch (RunCanceledByUserException e) {
exceptions.add(e);
break;
}
catch (ExecutionException e) {
exceptions.add(e);
}
}
manager.refresh();
return exceptions;
}
@NotNull
@Override
protected String getSuccessTitle() {
return "Packages installed successfully";
}
@NotNull
@Override
protected String getSuccessDescription() {
return "Installed packages: " + PyPackageUtil.requirementsToString(myRequirements);
}
@NotNull
@Override
protected String getFailureTitle() {
return "Install packages failed";
}
}
private static class InstallManagementTask extends InstallTask {
public InstallManagementTask(@Nullable Project project,
@NotNull Sdk sdk,
@Nullable Listener listener) {
super(project, sdk, Collections.emptyList(), Collections.emptyList(), listener);
}
@NotNull
@Override
protected List runTask(@NotNull ProgressIndicator indicator) {
final List exceptions = new ArrayList();
final PyPackageManager manager = PyPackageManagers.getInstance().forSdk(mySdk);
indicator.setText("Installing packaging tools...");
indicator.setIndeterminate(true);
try {
manager.installManagement();
}
catch (ExecutionException e) {
exceptions.add(e);
}
manager.refresh();
return exceptions;
}
@NotNull
@Override
protected String getSuccessDescription() {
return "Installed Python packaging tools";
}
}
private static class UninstallTask extends PackagingTask {
@NotNull private final List myPackages;
public UninstallTask(@Nullable Project project,
@NotNull Sdk sdk,
@Nullable Listener listener,
@NotNull List packages) {
super(project, sdk, "Uninstalling packages", listener);
myPackages = packages;
}
@NotNull
@Override
protected List runTask(@NotNull ProgressIndicator indicator) {
final PyPackageManager manager = PyPackageManagers.getInstance().forSdk(mySdk);
indicator.setIndeterminate(true);
try {
manager.uninstall(myPackages);
return Collections.emptyList();
}
catch (ExecutionException e) {
return Collections.singletonList(e);
}
finally {
manager.refresh();
}
}
@NotNull
@Override
protected String getSuccessTitle() {
return "Packages uninstalled successfully";
}
@NotNull
@Override
protected String getSuccessDescription() {
final String packagesString = StringUtil.join(myPackages, new Function() {
@Override
public String fun(PyPackage pkg) {
return "'" + pkg.getName() + "'";
}
}, ", ");
return "Uninstalled packages: " + packagesString;
}
@NotNull
@Override
protected String getFailureTitle() {
return "Uninstall packages failed";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy