src/eric7/PluginManager/PluginRepositoryDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/PluginManager/PluginRepositoryDialog.py
--- a/src/eric7/PluginManager/PluginRepositoryDialog.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/PluginManager/PluginRepositoryDialog.py	Wed Jul 13 14:55:47 2022 +0200
@@ -13,15 +13,33 @@
 import re
 
 from PyQt6.QtCore import (
-    pyqtSignal, pyqtSlot, Qt, QFile, QIODevice, QUrl, QProcess, QPoint,
-    QCoreApplication
+    pyqtSignal,
+    pyqtSlot,
+    Qt,
+    QFile,
+    QIODevice,
+    QUrl,
+    QProcess,
+    QPoint,
+    QCoreApplication,
 )
 from PyQt6.QtWidgets import (
-    QWidget, QDialogButtonBox, QAbstractButton, QTreeWidgetItem, QDialog,
-    QVBoxLayout, QHBoxLayout, QMenu, QLabel, QToolButton
+    QWidget,
+    QDialogButtonBox,
+    QAbstractButton,
+    QTreeWidgetItem,
+    QDialog,
+    QVBoxLayout,
+    QHBoxLayout,
+    QMenu,
+    QLabel,
+    QToolButton,
 )
 from PyQt6.QtNetwork import (
-    QNetworkAccessManager, QNetworkRequest, QNetworkReply, QNetworkInformation
+    QNetworkAccessManager,
+    QNetworkRequest,
+    QNetworkReply,
+    QNetworkInformation,
 )
 
 from .Ui_PluginRepositoryDialog import Ui_PluginRepositoryDialog
@@ -31,10 +49,10 @@
 from EricWidgets.EricApplication import ericApp
 
 from EricNetwork.EricNetworkProxyFactory import proxyAuthenticationRequired
+
 try:
-    from EricNetwork.EricSslErrorHandler import (
-        EricSslErrorHandler, EricSslErrorState
-    )
+    from EricNetwork.EricSslErrorHandler import EricSslErrorHandler, EricSslErrorState
+
     SSL_AVAILABLE = True
 except ImportError:
     SSL_AVAILABLE = False
@@ -51,12 +69,13 @@
 class PluginRepositoryWidget(QWidget, Ui_PluginRepositoryDialog):
     """
     Class implementing a dialog showing the available plugins.
-    
+
     @signal closeAndInstall() emitted when the Close & Install button is
         pressed
     """
+
     closeAndInstall = pyqtSignal()
-    
+
     DescrRole = Qt.ItemDataRole.UserRole
     UrlRole = Qt.ItemDataRole.UserRole + 1
     FilenameRole = Qt.ItemDataRole.UserRole + 2
@@ -67,11 +86,11 @@
     PluginStatusLocalUpdate = 2
     PluginStatusRemoteUpdate = 3
     PluginStatusError = 4
-    
+
     def __init__(self, pluginManager, integrated=False, parent=None):
         """
         Constructor
-        
+
         @param pluginManager reference to the plugin manager object
         @type PluginManager
         @param integrated flag indicating the integration into the sidebar
@@ -81,171 +100,179 @@
         """
         super().__init__(parent)
         self.setupUi(self)
-        
+
         if pluginManager is None:
             # started as external plug-in repository dialog
             from .PluginManager import PluginManager
+
             self.__pluginManager = PluginManager()
             self.__external = True
         else:
             self.__pluginManager = pluginManager
             self.__external = False
         self.__integratedWidget = integrated
-        
+
         if integrated:
             self.layout().setContentsMargins(0, 3, 0, 0)
-        
+
         if self.__integratedWidget:
             self.__actionButtonsLayout = QHBoxLayout()
             self.__actionButtonsLayout.addStretch()
-            
+
             self.__updateButton = QToolButton(self)
             self.__updateButton.setIcon(UI.PixmapCache.getIcon("reload"))
             self.__updateButton.setToolTip(self.tr("Update"))
             self.__updateButton.clicked.connect(self.__updateList)
             self.__actionButtonsLayout.addWidget(self.__updateButton)
-            
+
             self.__downloadButton = QToolButton(self)
             self.__downloadButton.setIcon(UI.PixmapCache.getIcon("download"))
             self.__downloadButton.setToolTip(self.tr("Download"))
             self.__downloadButton.clicked.connect(self.__downloadButtonClicked)
             self.__actionButtonsLayout.addWidget(self.__downloadButton)
-            
+
             self.__downloadInstallButton = QToolButton(self)
-            self.__downloadInstallButton.setIcon(
-                UI.PixmapCache.getIcon("downloadPlus"))
-            self.__downloadInstallButton.setToolTip(
-                self.tr("Download & Install"))
+            self.__downloadInstallButton.setIcon(UI.PixmapCache.getIcon("downloadPlus"))
+            self.__downloadInstallButton.setToolTip(self.tr("Download & Install"))
             self.__downloadInstallButton.clicked.connect(
-                self.__downloadInstallButtonClicked)
+                self.__downloadInstallButtonClicked
+            )
             self.__actionButtonsLayout.addWidget(self.__downloadInstallButton)
-            
+
             self.__downloadCancelButton = QToolButton(self)
-            self.__downloadCancelButton.setIcon(
-                UI.PixmapCache.getIcon("cancel"))
+            self.__downloadCancelButton.setIcon(UI.PixmapCache.getIcon("cancel"))
             self.__downloadCancelButton.setToolTip(self.tr("Cancel"))
             self.__downloadCancelButton.clicked.connect(self.__downloadCancel)
             self.__actionButtonsLayout.addWidget(self.__downloadCancelButton)
-            
+
             self.__installButton = QToolButton(self)
             self.__installButton.setIcon(UI.PixmapCache.getIcon("plus"))
             self.__installButton.setToolTip(self.tr("Install"))
             self.__installButton.clicked.connect(self.__closeAndInstall)
             self.__actionButtonsLayout.addWidget(self.__installButton)
-            
+
             self.__actionButtonsLayout.addStretch()
-            
+
             self.layout().addLayout(self.__actionButtonsLayout)
             self.buttonBox.hide()
         else:
             self.__updateButton = self.buttonBox.addButton(
-                self.tr("Update"), QDialogButtonBox.ButtonRole.ActionRole)
+                self.tr("Update"), QDialogButtonBox.ButtonRole.ActionRole
+            )
             self.__downloadButton = self.buttonBox.addButton(
-                self.tr("Download"), QDialogButtonBox.ButtonRole.ActionRole)
+                self.tr("Download"), QDialogButtonBox.ButtonRole.ActionRole
+            )
             self.__downloadInstallButton = self.buttonBox.addButton(
-                self.tr("Download && Install"),
-                QDialogButtonBox.ButtonRole.ActionRole)
+                self.tr("Download && Install"), QDialogButtonBox.ButtonRole.ActionRole
+            )
             self.__downloadCancelButton = self.buttonBox.addButton(
-                self.tr("Cancel"), QDialogButtonBox.ButtonRole.ActionRole)
+                self.tr("Cancel"), QDialogButtonBox.ButtonRole.ActionRole
+            )
             self.__installButton = self.buttonBox.addButton(
-                self.tr("Close && Install"),
-                QDialogButtonBox.ButtonRole.ActionRole)
+                self.tr("Close && Install"), QDialogButtonBox.ButtonRole.ActionRole
+            )
             if not self.__integratedWidget:
                 self.__closeButton = self.buttonBox.addButton(
-                    self.tr("Close"), QDialogButtonBox.ButtonRole.RejectRole)
+                    self.tr("Close"), QDialogButtonBox.ButtonRole.RejectRole
+                )
                 self.__closeButton.setEnabled(True)
-        
+
         self.__downloadButton.setEnabled(False)
         self.__downloadInstallButton.setEnabled(False)
         self.__downloadCancelButton.setEnabled(False)
         self.__installButton.setEnabled(False)
-        
-        self.repositoryUrlEdit.setText(
-            Preferences.getUI("PluginRepositoryUrl7"))
-        
+
+        self.repositoryUrlEdit.setText(Preferences.getUI("PluginRepositoryUrl7"))
+
         if self.__integratedWidget:
             self.repositoryList.setHeaderHidden(True)
         else:
             self.repositoryList.headerItem().setText(
-                self.repositoryList.columnCount(), "")
+                self.repositoryList.columnCount(), ""
+            )
             self.repositoryList.header().setSortIndicator(
-                0, Qt.SortOrder.AscendingOrder)
-        
+                0, Qt.SortOrder.AscendingOrder
+            )
+
         self.__pluginContextMenu = QMenu(self)
         self.__hideAct = self.__pluginContextMenu.addAction(
-            self.tr("Hide"), self.__hidePlugin)
+            self.tr("Hide"), self.__hidePlugin
+        )
         self.__hideSelectedAct = self.__pluginContextMenu.addAction(
-            self.tr("Hide Selected"), self.__hideSelectedPlugins)
+            self.tr("Hide Selected"), self.__hideSelectedPlugins
+        )
         self.__pluginContextMenu.addSeparator()
         self.__showAllAct = self.__pluginContextMenu.addAction(
-            self.tr("Show All"), self.__showAllPlugins)
+            self.tr("Show All"), self.__showAllPlugins
+        )
         self.__pluginContextMenu.addSeparator()
         self.__pluginContextMenu.addAction(
-            self.tr("Cleanup Downloads"), self.__cleanupDownloads)
-        
-        self.pluginRepositoryFile = os.path.join(Utilities.getConfigDir(),
-                                                 "PluginRepository")
-        
-        self.__pluginManager.pluginRepositoryFileDownloaded.connect(
-            self.__populateList)
-        
+            self.tr("Cleanup Downloads"), self.__cleanupDownloads
+        )
+
+        self.pluginRepositoryFile = os.path.join(
+            Utilities.getConfigDir(), "PluginRepository"
+        )
+
+        self.__pluginManager.pluginRepositoryFileDownloaded.connect(self.__populateList)
+
         # attributes for the network objects
         self.__networkManager = QNetworkAccessManager(self)
         self.__networkManager.proxyAuthenticationRequired.connect(
-            proxyAuthenticationRequired)
+            proxyAuthenticationRequired
+        )
         if SSL_AVAILABLE:
             self.__sslErrorHandler = EricSslErrorHandler(self)
             self.__networkManager.sslErrors.connect(self.__sslErrors)
         self.__replies = []
-        
-        if (
-            Preferences.getUI("DynamicOnlineCheck") and
-            QNetworkInformation.load(QNetworkInformation.Feature.Reachability)
+
+        if Preferences.getUI("DynamicOnlineCheck") and QNetworkInformation.load(
+            QNetworkInformation.Feature.Reachability
         ):
-            self.__reachabilityChanged(
-                QNetworkInformation.instance().reachability())
+            self.__reachabilityChanged(QNetworkInformation.instance().reachability())
             QNetworkInformation.instance().reachabilityChanged.connect(
-                self.__reachabilityChanged)
+                self.__reachabilityChanged
+            )
         else:
             # assume to be 'always online' if no backend could be loaded or
             # dynamic online check is switched of
             self.__reachabilityChanged(QNetworkInformation.Reachability.Online)
-        
+
         self.__pluginsToDownload = []
         self.__pluginsDownloaded = []
         self.__isDownloadInstall = False
         self.__allDownloadedOk = False
-        
+
         self.__hiddenPlugins = Preferences.getPluginManager("HiddenPlugins")
-        
+
         self.__populateList()
-    
+
     def __reachabilityChanged(self, reachability):
         """
         Private slot handling reachability state changes.
-        
+
         @param reachability new reachability state
         @type QNetworkInformation.Reachability
         """
         online = reachability == QNetworkInformation.Reachability.Online
         self.__online = online
-        
+
         self.__updateButton.setEnabled(online)
         self.on_repositoryList_itemSelectionChanged()
-        
+
         if not self.__integratedWidget:
             msg = (
                 self.tr("Internet Reachability Status: Reachable")
-                if online else
-                self.tr("Internet Reachability Status: Not Reachable")
+                if online
+                else self.tr("Internet Reachability Status: Not Reachable")
             )
             self.statusLabel.setText(msg)
-    
+
     @pyqtSlot(QAbstractButton)
     def on_buttonBox_clicked(self, button):
         """
         Private slot to handle the click of a button of the button box.
-        
+
         @param button reference to the button pressed (QAbstractButton)
         """
         if button == self.__updateButton:
@@ -258,7 +285,7 @@
             self.__downloadCancel()
         elif button == self.__installButton:
             self.__closeAndInstall()
-    
+
     @pyqtSlot()
     def __downloadButtonClicked(self):
         """
@@ -266,7 +293,7 @@
         """
         self.__isDownloadInstall = False
         self.__downloadPlugins()
-    
+
     @pyqtSlot()
     def __downloadInstallButtonClicked(self):
         """
@@ -275,35 +302,35 @@
         self.__isDownloadInstall = True
         self.__allDownloadedOk = True
         self.__downloadPlugins()
-    
+
     def __formatDescription(self, lines):
         """
         Private method to format the description.
-        
+
         @param lines lines of the description (list of strings)
         @return formatted description (string)
         """
         # remove empty line at start and end
         newlines = lines[:]
-        if len(newlines) and newlines[0] == '':
+        if len(newlines) and newlines[0] == "":
             del newlines[0]
-        if len(newlines) and newlines[-1] == '':
+        if len(newlines) and newlines[-1] == "":
             del newlines[-1]
-        
+
         # replace empty lines by newline character
         index = 0
         while index < len(newlines):
-            if newlines[index] == '':
-                newlines[index] = '\n'
+            if newlines[index] == "":
+                newlines[index] = "\n"
             index += 1
-        
+
         # join lines by a blank
-        return ' '.join(newlines)
-    
+        return " ".join(newlines)
+
     def __changeScheme(self, url, newScheme=""):
         """
         Private method to change the scheme of the given URL.
-        
+
         @param url URL to be modified
         @type str
         @param newScheme scheme to be set for the given URL
@@ -312,29 +339,29 @@
         """
         if not newScheme:
             newScheme = self.repositoryUrlEdit.text().split("//", 1)[0]
-        
+
         return newScheme + "//" + url.split("//", 1)[1]
-    
+
     @pyqtSlot(QPoint)
     def on_repositoryList_customContextMenuRequested(self, pos):
         """
         Private slot to show the context menu.
-        
+
         @param pos position to show the menu (QPoint)
         """
         self.__hideAct.setEnabled(
-            self.repositoryList.currentItem() is not None and
-            len(self.__selectedItems()) == 1)
-        self.__hideSelectedAct.setEnabled(
-            len(self.__selectedItems()) > 1)
+            self.repositoryList.currentItem() is not None
+            and len(self.__selectedItems()) == 1
+        )
+        self.__hideSelectedAct.setEnabled(len(self.__selectedItems()) > 1)
         self.__showAllAct.setEnabled(bool(self.__hasHiddenPlugins()))
         self.__pluginContextMenu.popup(self.repositoryList.mapToGlobal(pos))
-    
+
     @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
     def on_repositoryList_currentItemChanged(self, current, previous):
         """
         Private slot to handle the change of the current item.
-        
+
         @param current reference to the new current item (QTreeWidgetItem)
         @param previous reference to the old current item (QTreeWidgetItem)
         """
@@ -342,21 +369,25 @@
             self.descriptionEdit.clear()
             self.authorEdit.clear()
             return
-        
+
         url = current.data(0, PluginRepositoryWidget.UrlRole)
         url = "" if url is None else self.__changeScheme(url)
         self.urlEdit.setText(url)
         self.descriptionEdit.setPlainText(
-            current.data(0, PluginRepositoryWidget.DescrRole) and
-            self.__formatDescription(
-                current.data(0, PluginRepositoryWidget.DescrRole)) or "")
+            current.data(0, PluginRepositoryWidget.DescrRole)
+            and self.__formatDescription(
+                current.data(0, PluginRepositoryWidget.DescrRole)
+            )
+            or ""
+        )
         self.authorEdit.setText(
-            current.data(0, PluginRepositoryWidget.AuthorRole) or "")
-    
+            current.data(0, PluginRepositoryWidget.AuthorRole) or ""
+        )
+
     def __selectedItems(self):
         """
         Private method to get all selected items without the toplevel ones.
-        
+
         @return list of selected items (list)
         """
         ql = self.repositoryList.selectedItems()
@@ -365,7 +396,7 @@
             if ti in ql:
                 ql.remove(ti)
         return ql
-    
+
     @pyqtSlot()
     def on_repositoryList_itemSelectionChanged(self):
         """
@@ -375,13 +406,13 @@
         self.__downloadButton.setEnabled(enable and self.__online)
         self.__downloadInstallButton.setEnabled(enable and self.__online)
         self.__installButton.setEnabled(enable)
-    
+
     def reloadList(self):
         """
         Public method to reload the list of plugins.
         """
         self.__populateList()
-    
+
     @pyqtSlot()
     def __updateList(self):
         """
@@ -389,20 +420,20 @@
         """
         url = self.repositoryUrlEdit.text()
         self.__pluginManager.downLoadRepositoryFile(url=url)
-    
+
     def __downloadRepositoryFileDone(self, status, filename):
         """
         Private method called after the repository file was downloaded.
-        
+
         @param status flaging indicating a successful download (boolean)
         @param filename full path of the downloaded file (string)
         """
         self.__populateList()
-    
+
     def __downloadPluginDone(self, status, filename):
         """
         Private method called, when the download of a plugin is finished.
-        
+
         @param status flag indicating a successful download (boolean)
         @param filename full path of the downloaded file (string)
         """
@@ -410,23 +441,25 @@
             self.__pluginsDownloaded.append(filename)
         if self.__isDownloadInstall:
             self.__allDownloadedOk &= status
-        
+
         if len(self.__pluginsToDownload):
             self.__pluginsToDownload.pop(0)
-        
+
         if len(self.__pluginsToDownload):
             self.__downloadPlugin()
         else:
             self.__downloadPluginsDone()
-    
+
     def __downloadPlugin(self):
         """
         Private method to download the next plugin.
         """
-        self.__downloadFile(self.__pluginsToDownload[0][0],
-                            self.__pluginsToDownload[0][1],
-                            self.__downloadPluginDone)
-    
+        self.__downloadFile(
+            self.__pluginsToDownload[0][0],
+            self.__pluginsToDownload[0][1],
+            self.__downloadPluginDone,
+        )
+
     def __downloadPlugins(self):
         """
         Private slot to download the selected plugins.
@@ -436,21 +469,26 @@
         self.__downloadButton.setEnabled(False)
         self.__downloadInstallButton.setEnabled(False)
         self.__installButton.setEnabled(False)
-        
+
         newScheme = self.repositoryUrlEdit.text().split("//", 1)[0]
         for itm in self.repositoryList.selectedItems():
-            if itm not in [self.__stableItem, self.__unstableItem,
-                           self.__unknownItem, self.__obsoleteItem]:
+            if itm not in [
+                self.__stableItem,
+                self.__unstableItem,
+                self.__unknownItem,
+                self.__obsoleteItem,
+            ]:
                 url = self.__changeScheme(
-                    itm.data(0, PluginRepositoryWidget.UrlRole),
-                    newScheme)
+                    itm.data(0, PluginRepositoryWidget.UrlRole), newScheme
+                )
                 filename = os.path.join(
                     Preferences.getPluginManager("DownloadPath"),
-                    itm.data(0, PluginRepositoryWidget.FilenameRole))
+                    itm.data(0, PluginRepositoryWidget.FilenameRole),
+                )
                 self.__pluginsToDownload.append((url, filename))
         if self.__pluginsToDownload:
             self.__downloadPlugin()
-    
+
     def __downloadPluginsDone(self):
         """
         Private method called, when the download of the plugins is finished.
@@ -458,14 +496,14 @@
         self.__downloadButton.setEnabled(len(self.__selectedItems()))
         self.__downloadInstallButton.setEnabled(len(self.__selectedItems()))
         self.__installButton.setEnabled(len(self.__selectedItems()))
-        ui = (ericApp().getObject("UserInterface")
-              if not self.__external else None)
+        ui = ericApp().getObject("UserInterface") if not self.__external else None
         if ui is not None:
             ui.showNotification(
                 UI.PixmapCache.getPixmap("plugin48"),
                 self.tr("Download Plugin Files"),
-                self.tr("""The requested plugins were downloaded."""))
-        
+                self.tr("""The requested plugins were downloaded."""),
+            )
+
         if self.__isDownloadInstall:
             self.closeAndInstall.emit()
         else:
@@ -473,21 +511,23 @@
                 EricMessageBox.information(
                     self,
                     self.tr("Download Plugin Files"),
-                    self.tr("""The requested plugins were downloaded."""))
-            
+                    self.tr("""The requested plugins were downloaded."""),
+                )
+
             self.downloadProgress.setValue(0)
-            
+
             # repopulate the list to update the refresh icons
             self.__populateList()
-    
+
     def __resortRepositoryList(self):
         """
         Private method to resort the tree.
         """
         self.repositoryList.sortItems(
             self.repositoryList.sortColumn(),
-            self.repositoryList.header().sortIndicatorOrder())
-    
+            self.repositoryList.header().sortIndicatorOrder(),
+        )
+
     def __populateList(self):
         """
         Private method to populate the list of available plugins.
@@ -497,20 +537,19 @@
         self.__unstableItem = None
         self.__unknownItem = None
         self.__obsoleteItem = None
-        
+
         self.__newItems = 0
         self.__updateLocalItems = 0
         self.__updateRemoteItems = 0
-        
+
         self.downloadProgress.setValue(0)
-        
+
         if os.path.exists(self.pluginRepositoryFile):
             self.__repositoryMissing = False
             f = QFile(self.pluginRepositoryFile)
             if f.open(QIODevice.OpenModeFlag.ReadOnly):
-                from EricXML.PluginRepositoryReader import (
-                    PluginRepositoryReader
-                )
+                from EricXML.PluginRepositoryReader import PluginRepositoryReader
+
                 reader = PluginRepositoryReader(f, self.addEntry)
                 reader.readXML()
                 self.repositoryList.resizeColumnToContents(0)
@@ -526,34 +565,38 @@
                         self.tr(
                             """The URL of the Plugins Repository has"""
                             """ changed. Select the "Update" button to get"""
-                            """ the new repository file."""))
+                            """ the new repository file."""
+                        ),
+                    )
             else:
                 EricMessageBox.critical(
                     self,
                     self.tr("Read plugins repository file"),
-                    self.tr("<p>The plugins repository file <b>{0}</b> "
-                            "could not be read. Select Update</p>")
-                    .format(self.pluginRepositoryFile))
+                    self.tr(
+                        "<p>The plugins repository file <b>{0}</b> "
+                        "could not be read. Select Update</p>"
+                    ).format(self.pluginRepositoryFile),
+                )
         else:
             self.__repositoryMissing = True
             QTreeWidgetItem(
                 self.repositoryList,
-                ["", self.tr(
-                    "No plugin repository file available.\nSelect Update.")
-                 ])
+                ["", self.tr("No plugin repository file available.\nSelect Update.")],
+            )
             self.repositoryList.resizeColumnToContents(1)
-        
-        self.newLabel.setText(self.tr("New: <b>{0}</b>")
-                              .format(self.__newItems))
-        self.updateLocalLabel.setText(self.tr("Local Updates: <b>{0}</b>")
-                                      .format(self.__updateLocalItems))
-        self.updateRemoteLabel.setText(self.tr("Remote Updates: <b>{0}</b>")
-                                       .format(self.__updateRemoteItems))
-    
+
+        self.newLabel.setText(self.tr("New: <b>{0}</b>").format(self.__newItems))
+        self.updateLocalLabel.setText(
+            self.tr("Local Updates: <b>{0}</b>").format(self.__updateLocalItems)
+        )
+        self.updateRemoteLabel.setText(
+            self.tr("Remote Updates: <b>{0}</b>").format(self.__updateRemoteItems)
+        )
+
     def __downloadFile(self, url, filename, doneMethod=None):
         """
         Private slot to download the given file.
-        
+
         @param url URL for the download (string)
         @param filename local name of the file (string)
         @param doneMethod method to be called when done
@@ -565,16 +608,18 @@
             if not self.__integratedWidget:
                 self.__closeButton.setEnabled(False)
             self.__downloadCancelButton.setEnabled(True)
-            
+
             self.statusLabel.setText(url)
-            
+
             request = QNetworkRequest(QUrl(url))
             request.setAttribute(
                 QNetworkRequest.Attribute.CacheLoadControlAttribute,
-                QNetworkRequest.CacheLoadControl.AlwaysNetwork)
+                QNetworkRequest.CacheLoadControl.AlwaysNetwork,
+            )
             reply = self.__networkManager.get(request)
             reply.finished.connect(
-                lambda: self.__downloadFileDone(reply, filename, doneMethod))
+                lambda: self.__downloadFileDone(reply, filename, doneMethod)
+            )
             reply.downloadProgress.connect(self.__downloadProgress)
             self.__replies.append(reply)
         else:
@@ -584,13 +629,14 @@
                 self.tr(
                     """<p>Could not download the requested file"""
                     """ from {0}.</p><p>Error: {1}</p>"""
-                ).format(url, self.tr("No connection to Internet.")))
-    
+                ).format(url, self.tr("No connection to Internet.")),
+            )
+
     def __downloadFileDone(self, reply, fileName, doneMethod):
         """
         Private method called, after the file has been downloaded
         from the Internet.
-        
+
         @param reply reference to the reply object of the download
         @type QNetworkReply
         @param fileName local name of the file
@@ -602,37 +648,33 @@
         if not self.__integratedWidget:
             self.__closeButton.setEnabled(True)
         self.__downloadCancelButton.setEnabled(False)
-        
+
         ok = True
         if reply in self.__replies:
             self.__replies.remove(reply)
         if reply.error() != QNetworkReply.NetworkError.NoError:
             ok = False
-            if (
-                reply.error() !=
-                QNetworkReply.NetworkError.OperationCanceledError
-            ):
+            if reply.error() != QNetworkReply.NetworkError.OperationCanceledError:
                 EricMessageBox.warning(
                     self,
                     self.tr("Error downloading file"),
                     self.tr(
                         """<p>Could not download the requested file"""
                         """ from {0}.</p><p>Error: {1}</p>"""
-                    ).format(reply.url().toString(), reply.errorString())
+                    ).format(reply.url().toString(), reply.errorString()),
                 )
             self.downloadProgress.setValue(0)
             if self.repositoryList.topLevelItemCount():
                 if self.repositoryList.currentItem() is None:
                     self.repositoryList.setCurrentItem(
-                        self.repositoryList.topLevelItem(0))
+                        self.repositoryList.topLevelItem(0)
+                    )
                 else:
-                    self.__downloadButton.setEnabled(
-                        len(self.__selectedItems()))
-                    self.__downloadInstallButton.setEnabled(
-                        len(self.__selectedItems()))
+                    self.__downloadButton.setEnabled(len(self.__selectedItems()))
+                    self.__downloadInstallButton.setEnabled(len(self.__selectedItems()))
             reply.deleteLater()
             return
-        
+
         downloadIODevice = QFile(fileName + ".tmp")
         downloadIODevice.open(QIODevice.OpenModeFlag.WriteOnly)
         # read data in chunks
@@ -647,14 +689,14 @@
             QFile.remove(fileName)
         downloadIODevice.rename(fileName)
         reply.deleteLater()
-        
+
         if doneMethod is not None:
             doneMethod(ok, fileName)
-    
+
     def __downloadCancel(self, reply=None):
         """
         Private slot to cancel the current download.
-        
+
         @param reply reference to the network reply
         @type QNetworkReply
         """
@@ -663,23 +705,24 @@
         self.__pluginsToDownload = []
         if reply is not None:
             reply.abort()
-    
+
     def __downloadProgress(self, done, total):
         """
         Private slot to show the download progress.
-        
+
         @param done number of bytes downloaded so far (integer)
         @param total total bytes to be downloaded (integer)
         """
         if total:
             self.downloadProgress.setMaximum(total)
             self.downloadProgress.setValue(done)
-    
-    def addEntry(self, name, short, description, url, author, version,
-                 filename, status):
+
+    def addEntry(
+        self, name, short, description, url, author, version, filename, status
+    ):
         """
         Public method to add an entry to the list.
-        
+
         @param name data for the name field (string)
         @param short data for the short field (string)
         @param description data for the description field (list of strings)
@@ -692,32 +735,36 @@
         pluginName = filename.rsplit("-", 1)[0]
         if pluginName in self.__hiddenPlugins:
             return
-        
+
         if status == "stable":
             if self.__stableItem is None:
                 self.__stableItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Stable")])
+                    self.repositoryList, [self.tr("Stable")]
+                )
                 self.__stableItem.setExpanded(True)
             parent = self.__stableItem
         elif status == "unstable":
             if self.__unstableItem is None:
                 self.__unstableItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Unstable")])
+                    self.repositoryList, [self.tr("Unstable")]
+                )
                 self.__unstableItem.setExpanded(True)
             parent = self.__unstableItem
         elif status == "obsolete":
             if self.__obsoleteItem is None:
                 self.__obsoleteItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Obsolete")])
+                    self.repositoryList, [self.tr("Obsolete")]
+                )
                 self.__obsoleteItem.setExpanded(True)
             parent = self.__obsoleteItem
         else:
             if self.__unknownItem is None:
                 self.__unknownItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Unknown")])
+                    self.repositoryList, [self.tr("Unknown")]
+                )
                 self.__unknownItem.setExpanded(True)
             parent = self.__unknownItem
-        
+
         if self.__integratedWidget:
             entryFormat = "<b>{0}</b> - Version: <i>{1}</i><br/>{2}"
             itm = QTreeWidgetItem(parent)
@@ -726,12 +773,12 @@
             self.repositoryList.setItemWidget(itm, 0, label)
         else:
             itm = QTreeWidgetItem(parent, [name, version, short])
-        
+
         itm.setData(0, PluginRepositoryWidget.UrlRole, url)
         itm.setData(0, PluginRepositoryWidget.FilenameRole, filename)
         itm.setData(0, PluginRepositoryWidget.AuthorRole, author)
         itm.setData(0, PluginRepositoryWidget.DescrRole, description)
-        
+
         iconColumn = 0 if self.__integratedWidget else 1
         updateStatus = self.__updateStatus(filename, version)
         if updateStatus == PluginRepositoryWidget.PluginStatusUpToDate:
@@ -752,102 +799,97 @@
         elif updateStatus == PluginRepositoryWidget.PluginStatusError:
             itm.setIcon(iconColumn, UI.PixmapCache.getIcon("warning"))
             itm.setToolTip(iconColumn, self.tr("error determining status"))
-    
+
     def __updateStatus(self, filename, version):
         """
         Private method to check the given archive update status.
-        
+
         @param filename data for the filename field (string)
         @param version data for the version field (string)
         @return plug-in update status (integer, one of PluginStatusNew,
             PluginStatusUpToDate, PluginStatusLocalUpdate,
             PluginStatusRemoteUpdate)
         """
-        archive = os.path.join(Preferences.getPluginManager("DownloadPath"),
-                               filename)
-        
+        archive = os.path.join(Preferences.getPluginManager("DownloadPath"), filename)
+
         # check, if it is an update (i.e. we already have archives
         # with the same pattern)
-        archivesPattern = archive.rsplit('-', 1)[0] + "-*.zip"
+        archivesPattern = archive.rsplit("-", 1)[0] + "-*.zip"
         if len(glob.glob(archivesPattern)) == 0:
             # Check against installed/loaded plug-ins
-            pluginName = filename.rsplit('-', 1)[0]
+            pluginName = filename.rsplit("-", 1)[0]
             pluginDetails = self.__pluginManager.getPluginDetails(pluginName)
-            if (
-                pluginDetails is None or
-                pluginDetails["moduleName"] != pluginName
-            ):
+            if pluginDetails is None or pluginDetails["moduleName"] != pluginName:
                 return PluginRepositoryWidget.PluginStatusNew
             if pluginDetails["error"]:
                 return PluginRepositoryWidget.PluginStatusError
-            pluginVersionTuple = Globals.versionToTuple(
-                pluginDetails["version"])[:3]
+            pluginVersionTuple = Globals.versionToTuple(pluginDetails["version"])[:3]
             versionTuple = Globals.versionToTuple(version)[:3]
             if pluginVersionTuple < versionTuple:
                 return PluginRepositoryWidget.PluginStatusRemoteUpdate
             else:
                 return PluginRepositoryWidget.PluginStatusUpToDate
-        
+
         # check, if the archive exists
         if not os.path.exists(archive):
             return PluginRepositoryWidget.PluginStatusRemoteUpdate
-        
+
         # check, if the archive is a valid zip file
         if not zipfile.is_zipfile(archive):
             return PluginRepositoryWidget.PluginStatusRemoteUpdate
-        
+
         zipFile = zipfile.ZipFile(archive, "r")
         try:
             aversion = zipFile.read("VERSION").decode("utf-8")
         except KeyError:
             aversion = ""
         zipFile.close()
-        
+
         if aversion == version:
             # Check against installed/loaded plug-ins
-            pluginName = filename.rsplit('-', 1)[0]
+            pluginName = filename.rsplit("-", 1)[0]
             pluginDetails = self.__pluginManager.getPluginDetails(pluginName)
             if pluginDetails is None:
                 return PluginRepositoryWidget.PluginStatusLocalUpdate
             if (
-                Globals.versionToTuple(pluginDetails["version"])[:3] <
-                Globals.versionToTuple(version)[:3]
+                Globals.versionToTuple(pluginDetails["version"])[:3]
+                < Globals.versionToTuple(version)[:3]
             ):
                 return PluginRepositoryWidget.PluginStatusLocalUpdate
             else:
                 return PluginRepositoryWidget.PluginStatusUpToDate
         else:
             return PluginRepositoryWidget.PluginStatusRemoteUpdate
-    
+
     def __sslErrors(self, reply, errors):
         """
         Private slot to handle SSL errors.
-        
+
         @param reply reference to the reply object (QNetworkReply)
         @param errors list of SSL errors (list of QSslError)
         """
         ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0]
         if ignored == EricSslErrorState.NOT_IGNORED:
             self.__downloadCancel(reply)
-    
+
     def getDownloadedPlugins(self):
         """
         Public method to get the list of recently downloaded plugin files.
-        
+
         @return list of plugin filenames (list of strings)
         """
         return self.__pluginsDownloaded
-    
+
     @pyqtSlot(bool)
     def on_repositoryUrlEditButton_toggled(self, checked):
         """
         Private slot to set the read only status of the repository URL line
         edit.
-        
+
         @param checked state of the push button (boolean)
         """
         self.repositoryUrlEdit.setReadOnly(not checked)
-    
+
     def __closeAndInstall(self):
         """
         Private method to close the dialog and invoke the install dialog.
@@ -856,58 +898,60 @@
             for itm in self.__selectedItems():
                 filename = os.path.join(
                     Preferences.getPluginManager("DownloadPath"),
-                    itm.data(0, PluginRepositoryWidget.FilenameRole))
+                    itm.data(0, PluginRepositoryWidget.FilenameRole),
+                )
                 self.__pluginsDownloaded.append(filename)
         self.closeAndInstall.emit()
-    
+
     def __hidePlugin(self):
         """
         Private slot to hide the current plug-in.
         """
         itm = self.__selectedItems()[0]
-        pluginName = (itm.data(0, PluginRepositoryWidget.FilenameRole)
-                      .rsplit("-", 1)[0])
+        pluginName = itm.data(0, PluginRepositoryWidget.FilenameRole).rsplit("-", 1)[0]
         self.__updateHiddenPluginsList([pluginName])
-    
+
     def __hideSelectedPlugins(self):
         """
         Private slot to hide all selected plug-ins.
         """
         hideList = []
         for itm in self.__selectedItems():
-            pluginName = (itm.data(0, PluginRepositoryWidget.FilenameRole)
-                          .rsplit("-", 1)[0])
+            pluginName = itm.data(0, PluginRepositoryWidget.FilenameRole).rsplit(
+                "-", 1
+            )[0]
             hideList.append(pluginName)
         self.__updateHiddenPluginsList(hideList)
-    
+
     def __showAllPlugins(self):
         """
         Private slot to show all plug-ins.
         """
         self.__hiddenPlugins = []
         self.__updateHiddenPluginsList([])
-    
+
     def __hasHiddenPlugins(self):
         """
         Private method to check, if there are any hidden plug-ins.
-        
+
         @return flag indicating the presence of hidden plug-ins (boolean)
         """
         return bool(self.__hiddenPlugins)
-    
+
     def __updateHiddenPluginsList(self, hideList):
         """
         Private method to store the list of hidden plug-ins to the settings.
-        
+
         @param hideList list of plug-ins to add to the list of hidden ones
             (list of string)
         """
         if hideList:
             self.__hiddenPlugins.extend(
-                [p for p in hideList if p not in self.__hiddenPlugins])
+                [p for p in hideList if p not in self.__hiddenPlugins]
+            )
         Preferences.setPluginManager("HiddenPlugins", self.__hiddenPlugins)
         self.__populateList()
-    
+
     def __cleanupDownloads(self):
         """
         Private slot to cleanup the plug-in downloads area.
@@ -919,10 +963,11 @@
     """
     Class for the dialog variant.
     """
+
     def __init__(self, pluginManager, parent=None):
         """
         Constructor
-        
+
         @param pluginManager reference to the plugin manager object
         @type PluginManager
         @param parent reference to the parent widget
@@ -930,31 +975,31 @@
         """
         super().__init__(parent)
         self.setSizeGripEnabled(True)
-        
+
         self.__layout = QVBoxLayout(self)
         self.__layout.setContentsMargins(0, 0, 0, 0)
         self.setLayout(self.__layout)
-        
+
         self.cw = PluginRepositoryWidget(pluginManager, parent=self)
         size = self.cw.size()
         self.__layout.addWidget(self.cw)
         self.resize(size)
         self.setWindowTitle(self.cw.windowTitle())
-        
+
         self.cw.buttonBox.accepted.connect(self.accept)
         self.cw.buttonBox.rejected.connect(self.reject)
         self.cw.closeAndInstall.connect(self.__closeAndInstall)
-        
+
     def __closeAndInstall(self):
         """
         Private slot to handle the closeAndInstall signal.
         """
         self.done(QDialog.DialogCode.Accepted + 1)
-    
+
     def getDownloadedPlugins(self):
         """
         Public method to get the list of recently downloaded plugin files.
-        
+
         @return list of plugin filenames (list of strings)
         """
         return self.cw.getDownloadedPlugins()
@@ -964,10 +1009,11 @@
     """
     Main window class for the standalone dialog.
     """
+
     def __init__(self, parent=None):
         """
         Constructor
-        
+
         @param parent reference to the parent widget (QWidget)
         """
         super().__init__(parent)
@@ -976,55 +1022,55 @@
         self.setCentralWidget(self.cw)
         self.resize(size)
         self.setWindowTitle(self.cw.windowTitle())
-        
-        self.setStyle(Preferences.getUI("Style"),
-                      Preferences.getUI("StyleSheet"))
-        
+
+        self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet"))
+
         self.cw.buttonBox.accepted.connect(self.close)
         self.cw.buttonBox.rejected.connect(self.close)
         self.cw.closeAndInstall.connect(self.__startPluginInstall)
-    
+
     def __startPluginInstall(self):
         """
         Private slot to start the eric plugin installation dialog.
         """
         proc = QProcess()
         applPath = os.path.join(getConfig("ericDir"), "eric7_plugininstall.py")
-        
+
         args = []
         args.append(applPath)
         args += self.cw.getDownloadedPlugins()
-        
-        if (
-            not os.path.isfile(applPath) or
-            not proc.startDetached(Globals.getPythonExecutable(), args)
+
+        if not os.path.isfile(applPath) or not proc.startDetached(
+            Globals.getPythonExecutable(), args
         ):
             EricMessageBox.critical(
                 self,
-                self.tr('Process Generation Error'),
+                self.tr("Process Generation Error"),
                 self.tr(
-                    '<p>Could not start the process.<br>'
-                    'Ensure that it is available as <b>{0}</b>.</p>'
+                    "<p>Could not start the process.<br>"
+                    "Ensure that it is available as <b>{0}</b>.</p>"
                 ).format(applPath),
-                self.tr('OK'))
-        
+                self.tr("OK"),
+            )
+
         self.close()
 
 
 def PluginRepositoryDownloadCleanup(quiet=False):
     """
     Module function to clean up the plug-in downloads area.
-    
+
     @param quiet flag indicating quiet operations
     @type bool
     """
-    pluginsRegister = []    # list of plug-ins contained in the repository
-    
-    def registerPlugin(name, short, description, url, author, version,
-                       filename, status):
+    pluginsRegister = []  # list of plug-ins contained in the repository
+
+    def registerPlugin(
+        name, short, description, url, author, version, filename, status
+    ):
         """
         Method to register a plug-in's data.
-        
+
         @param name data for the name field (string)
         @param short data for the short field (string)
         @param description data for the description field (list of strings)
@@ -1037,19 +1083,17 @@
         pluginName = os.path.splitext(url.rsplit("/", 1)[1])[0]
         if pluginName not in pluginsRegister:
             pluginsRegister.append(pluginName)
-    
+
     downloadPath = Preferences.getPluginManager("DownloadPath")
     downloads = {}  # plug-in name as key, file name as value
-    
+
     # step 1: extract plug-ins and downloaded files
     for pluginFile in os.listdir(downloadPath):
         if not os.path.isfile(os.path.join(downloadPath, pluginFile)):
             continue
-        
+
         try:
-            pluginName, pluginVersion = (
-                pluginFile.replace(".zip", "").rsplit("-", 1)
-            )
+            pluginName, pluginVersion = pluginFile.replace(".zip", "").rsplit("-", 1)
             pluginVersionList = re.split("[._-]", pluginVersion)
             for index in range(len(pluginVersionList)):
                 try:
@@ -1063,22 +1107,28 @@
             # => assume version 0.0.0
             pluginName = pluginFile.replace(".zip", "")
             pluginVersionList = [0, 0, 0]
-        
+
         if pluginName not in downloads:
             downloads[pluginName] = []
         downloads[pluginName].append((pluginFile, tuple(pluginVersionList)))
-    
+
     # step 2: delete old entries
     hiddenPlugins = Preferences.getPluginManager("HiddenPlugins")
     for pluginName in downloads:
         downloads[pluginName].sort(key=lambda x: x[1])
-    
+
         removeFiles = (
             [f[0] for f in downloads[pluginName]]
-            if (pluginName in hiddenPlugins and
-                not Preferences.getPluginManager("KeepHidden")) else
-            [f[0] for f in downloads[pluginName][
-                :-Preferences.getPluginManager("KeepGenerations")]]
+            if (
+                pluginName in hiddenPlugins
+                and not Preferences.getPluginManager("KeepHidden")
+            )
+            else [
+                f[0]
+                for f in downloads[pluginName][
+                    : -Preferences.getPluginManager("KeepGenerations")
+                ]
+            ]
         )
         for removeFile in removeFiles:
             try:
@@ -1088,24 +1138,25 @@
                     EricMessageBox.critical(
                         None,
                         QCoreApplication.translate(
-                            "PluginRepositoryWidget",
-                            "Cleanup of Plugin Downloads"),
+                            "PluginRepositoryWidget", "Cleanup of Plugin Downloads"
+                        ),
                         QCoreApplication.translate(
                             "PluginRepositoryWidget",
                             """<p>The plugin download <b>{0}</b> could"""
-                            """ not be deleted.</p><p>Reason: {1}</p>""")
-                        .format(removeFile, str(err)))
-    
+                            """ not be deleted.</p><p>Reason: {1}</p>""",
+                        ).format(removeFile, str(err)),
+                    )
+
     # step 3: delete entries of obsolete plug-ins
-    pluginRepositoryFile = os.path.join(Utilities.getConfigDir(),
-                                        "PluginRepository")
+    pluginRepositoryFile = os.path.join(Utilities.getConfigDir(), "PluginRepository")
     if os.path.exists(pluginRepositoryFile):
         f = QFile(pluginRepositoryFile)
         if f.open(QIODevice.OpenModeFlag.ReadOnly):
             from EricXML.PluginRepositoryReader import PluginRepositoryReader
+
             reader = PluginRepositoryReader(f, registerPlugin)
             reader.readXML()
-            
+
             for pluginName in downloads:
                 if pluginName not in pluginsRegister:
                     removeFiles = [f[0] for f in downloads[pluginName]]
@@ -1118,10 +1169,13 @@
                                     None,
                                     QCoreApplication.translate(
                                         "PluginRepositoryWidget",
-                                        "Cleanup of Plugin Downloads"),
+                                        "Cleanup of Plugin Downloads",
+                                    ),
                                     QCoreApplication.translate(
                                         "PluginRepositoryWidget",
                                         "<p>The plugin download <b>{0}</b>"
                                         " could not be deleted.</p>"
-                                        "<p>Reason: {1}</p>""")
-                                    .format(removeFile, str(err)))
+                                        "<p>Reason: {1}</p>"
+                                        "",
+                                    ).format(removeFile, str(err)),
+                                )

eric ide

mercurial