eric7/PipInterface/PipPackagesWidget.py

branch
eric7
changeset 8977
663521af48b2
parent 8881
54e42bc2437a
child 8978
38c3ddf21537
diff -r ca442cd49b9e -r 663521af48b2 eric7/PipInterface/PipPackagesWidget.py
--- a/eric7/PipInterface/PipPackagesWidget.py	Sun Mar 13 15:20:26 2022 +0100
+++ b/eric7/PipInterface/PipPackagesWidget.py	Sun Mar 13 19:59:03 2022 +0100
@@ -13,6 +13,7 @@
 import contextlib
 
 from PyQt6.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery
+from PyQt6.QtGui import QIcon
 from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import (
     QWidget, QToolButton, QApplication, QHeaderView, QTreeWidgetItem,
@@ -148,6 +149,12 @@
     ShowProcessFilesListMode = 3
     
     SearchVersionRole = Qt.ItemDataRole.UserRole + 1
+    VulnerabilityRole = Qt.ItemDataRole.UserRole + 2
+    
+    PackageColumn = 0
+    InstalledVersionColumn = 1
+    AvailableVersionColumn = 2
+    VulnerabilityColumn = 3
     
     def __init__(self, pip, parent=None):
         """
@@ -189,7 +196,7 @@
         self.__pip = pip
         
         self.packagesList.header().setSortIndicator(
-            0, Qt.SortOrder.AscendingOrder)
+            PipPackagesWidget.PackageColumn, Qt.SortOrder.AscendingOrder)
         
         self.__infoLabels = {
             "name": self.tr("Name:"),
@@ -324,7 +331,7 @@
         """
         return [
             itm for itm in self.packagesList.selectedItems()
-            if bool(itm.text(2))
+            if bool(itm.text(PipPackagesWidget.AvailableVersionColumn))
         ]
     
     def __allUpdateableItems(self):
@@ -337,7 +344,7 @@
         updateableItems = []
         for index in range(self.packagesList.topLevelItemCount()):
             itm = self.packagesList.topLevelItem(index)
-            if itm.text(2):
+            if itm.text(PipPackagesWidget.AvailableVersionColumn):
                 updateableItems.append(itm)
         
         return updateableItems
@@ -384,7 +391,8 @@
                         usersite=self.userCheckBox.isChecked(),
                     )
                     for package, version in installedPackages:
-                        QTreeWidgetItem(self.packagesList, [package, version])
+                        QTreeWidgetItem(self.packagesList,
+                                        [package, version, "", ""])
                     self.packagesList.setUpdatesEnabled(True)
                     self.statusLabel.setText(
                         self.tr("Getting outdated packages..."))
@@ -406,12 +414,20 @@
                         )
                         if items:
                             itm = items[0]
-                            itm.setText(2, latest)
+                            itm.setText(
+                                PipPackagesWidget.AvailableVersionColumn,
+                                latest)
                     
-                    self.packagesList.sortItems(0, Qt.SortOrder.AscendingOrder)
+                    self.packagesList.sortItems(
+                        PipPackagesWidget.PackageColumn,
+                        Qt.SortOrder.AscendingOrder)
                     for col in range(self.packagesList.columnCount()):
                         self.packagesList.resizeColumnToContents(col)
                     self.packagesList.setUpdatesEnabled(True)
+                    
+                    # 3. update with vulnerability information
+                    if self.vulnerabilityCheckBox.isChecked():
+                        self.__updateVulnerabilityData()
                 self.statusLabel.hide()
         
         self.__updateActionButtons()
@@ -428,33 +444,24 @@
         """
         self.__refreshPackagesList()
     
-    @pyqtSlot(bool)
-    def on_localCheckBox_clicked(self, checked):
+    @pyqtSlot()
+    def on_localCheckBox_clicked(self):
         """
         Private slot handling the switching of the local mode.
-        
-        @param checked state of the local check box
-        @type bool
         """
         self.__refreshPackagesList()
     
-    @pyqtSlot(bool)
-    def on_notRequiredCheckBox_clicked(self, checked):
+    @pyqtSlot()
+    def on_notRequiredCheckBox_clicked(self):
         """
         Private slot handling the switching of the 'not required' mode.
-        
-        @param checked state of the 'not required' check box
-        @type bool
         """
         self.__refreshPackagesList()
     
-    @pyqtSlot(bool)
-    def on_userCheckBox_clicked(self, checked):
+    @pyqtSlot()
+    def on_userCheckBox_clicked(self):
         """
         Private slot handling the switching of the 'user-site' mode.
-        
-        @param checked state of the 'user-site' check box
-        @type bool
         """
         self.__refreshPackagesList()
     
@@ -616,7 +623,8 @@
         """
         Private slot to remove selected packages of the selected environment.
         """
-        packages = [itm.text(0) for itm in self.packagesList.selectedItems()]
+        packages = [itm.text(PipPackagesWidget.PackageColumn)
+                    for itm in self.packagesList.selectedItems()]
         self.executeUninstallPackages(packages)
     
     def executeUninstallPackages(self, packages):
@@ -653,7 +661,7 @@
         """
         item = self.packagesList.selectedItems()[0]
         if item:
-            packageName = item.text(0)
+            packageName = item.text(PipPackagesWidget.PackageColumn)
             upgradable = bool(item.text(2))
             # show details for available version or installed one
             if item.text(2):
@@ -1137,7 +1145,8 @@
         """
         Private slot to force a re-installation of the selected packages.
         """
-        packages = [itm.text(0) for itm in self.packagesList.selectedItems()]
+        packages = [itm.text(PipPackagesWidget.PackageColumn)
+                    for itm in self.packagesList.selectedItems()]
         venvName = self.environmentsComboBox.currentText()
         if venvName and packages:
             self.__pip.installPackages(packages, venvName=venvName,
@@ -1283,3 +1292,50 @@
         venvName = self.environmentsComboBox.currentText()
         if venvName:
             self.__pip.cachePurge(venvName)
+    
+    ##################################################################
+    ## Interface to the vulnerability checks below
+    ##################################################################
+    
+    @pyqtSlot(bool)
+    def on_vulnerabilityCheckBox_clicked(self, checked):
+        """
+        Private slot handling a change of the automatic vulnerability checks.
+        
+        @param checked flag indicating the state of the check box
+        @type bool
+        """
+        if checked:
+            self.__updateVulnerabilityData(clearFirst=True)
+    
+    @pyqtSlot()
+    def __clearVulnerabilityInfo(self):
+        """
+        Private slot to clear the vulnerability info.
+        """
+        for row in range(self.packagesList.topLevelItemCount()):
+            itm = self.packagesList.topLevelItem(row)
+            itm.setText(PipPackagesWidget.VulnerabilityColumn, "")
+            itm.setToolTip(PipPackagesWidget.VulnerabilityColumn, "")
+            itm.setIcon(PipPackagesWidget.VulnerabilityColumn, QIcon())
+            itm.setData(PipPackagesWidget.VulnerabilityColumn,
+                        PipPackagesWidget.VulnerabilityRole,
+                        None)
+    
+    @pyqtSlot()
+    def __updateVulnerabilityData(self, clearFirst=True):
+        """
+        Private slot to update the shown vulnerability info.
+        
+        @param clearFirst flag indicating to clear the vulnerability info first
+            (defaults to True)
+        @type bool (optional)
+        """
+        if clearFirst:
+            self.__clearVulnerabilityInfo()
+        
+        packages = []       # TODO: fill this list with real data
+        
+        error, vulnerabilities = (
+            self.__pip.getVulnerabilityChecker().check(packages)
+        )

eric ide

mercurial