src/eric7/PipInterface/PipPackagesWidget.py

branch
eric7-maintenance
changeset 10222
1146cc8fbf5d
parent 10148
31ba20629af4
parent 10210
7d0e5ca7eb3e
child 10460
3b34efa2857c
diff -r dce4b2b95c3f -r 1146cc8fbf5d src/eric7/PipInterface/PipPackagesWidget.py
--- a/src/eric7/PipInterface/PipPackagesWidget.py	Fri Sep 01 10:26:51 2023 +0200
+++ b/src/eric7/PipInterface/PipPackagesWidget.py	Thu Oct 05 09:59:53 2023 +0200
@@ -274,6 +274,8 @@
         self.viewsStackWidget.setCurrentWidget(self.packagesPage)
         self.on_packagesList_currentItemChanged(None, None)
 
+        self.preferencesChanged()  # perform preferences dependent configuration
+
     @pyqtSlot()
     def __projectOpened(self):
         """
@@ -292,10 +294,10 @@
         @type bool
         """
         if not shutdown:
+            # the project entry is always at index 1
             if self.environmentsComboBox.currentIndex() == 1:
                 self.environmentsComboBox.setCurrentIndex(0)
 
-            # the project entry is always at index 1
             self.environmentsComboBox.removeItem(1)
 
     def __populateEnvironments(self):
@@ -441,7 +443,6 @@
 
                 with EricOverrideCursor():
                     # 1. populate with installed packages
-                    self.packagesList.setUpdatesEnabled(False)
                     installedPackages = self.__pip.getInstalledPackages(
                         venvName,
                         localPackages=self.localCheckBox.isChecked(),
@@ -450,40 +451,60 @@
                     )
                     for package, version in installedPackages:
                         QTreeWidgetItem(self.packagesList, [package, version, "", ""])
-                    self.packagesList.setUpdatesEnabled(True)
+                    self.packagesList.sortItems(
+                        PipPackagesWidget.PackageColumn, Qt.SortOrder.AscendingOrder
+                    )
+                    self.packagesList.resizeColumnToContents(
+                        PipPackagesWidget.PackageColumn
+                    )
+                    self.packagesList.resizeColumnToContents(
+                        PipPackagesWidget.InstalledVersionColumn
+                    )
+                    QApplication.processEvents()
+
+                    # 2. update with vulnerability information
+                    if self.vulnerabilityCheckBox.isChecked():
+                        self.__updateVulnerabilityData()
+                        self.packagesList.resizeColumnToContents(
+                            PipPackagesWidget.VulnerabilityColumn
+                        )
                     self.statusLabel.setText(self.tr("Getting outdated packages..."))
                     QApplication.processEvents()
 
-                    # 2. update with update information
-                    self.packagesList.setUpdatesEnabled(False)
-                    outdatedPackages = self.__pip.getOutdatedPackages(
+                    # 3. update with update information
+                    self.__pip.getOutdatedPackages(
                         venvName,
                         localPackages=self.localCheckBox.isChecked(),
                         notRequired=self.notRequiredCheckBox.isChecked(),
                         usersite=self.userCheckBox.isChecked(),
+                        callback=self.__updateOutdatedInfo,
                     )
-                    for package, _version, latest in outdatedPackages:
-                        items = self.packagesList.findItems(
-                            package,
-                            Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive,
-                        )
-                        if items:
-                            itm = items[0]
-                            itm.setText(
-                                PipPackagesWidget.AvailableVersionColumn, latest
-                            )
+
+        else:
+            self.__updateActionButtons()
+            self.__updateSearchActionButtons()
+            self.__updateSearchButton()
+            self.__updateSearchMoreButton(False)
+
+    def __updateOutdatedInfo(self, outdatedPackages):
+        """
+        Private method to process the list of outdated packages.
 
-                    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()
+        @param outdatedPackages list of tuples containing the package name,
+            installed version and available version
+        @type list of tuple of (str, str, str)
+        """
+        for package, _version, latest in outdatedPackages:
+            items = self.packagesList.findItems(
+                package,
+                Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive,
+            )
+            if items:
+                items[0].setText(PipPackagesWidget.AvailableVersionColumn, latest)
+        self.packagesList.resizeColumnToContents(
+            PipPackagesWidget.AvailableVersionColumn
+        )
+        self.statusLabel.hide()
 
         self.__updateActionButtons()
         self.__updateSearchActionButtons()
@@ -610,6 +631,8 @@
             self.vulnerabilitiesInfoWidget.clear()
             self.infoWidget.tabBar().hide()
 
+        self.__updateActionButtons()
+
     @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
     def on_packagesList_currentItemChanged(self, curr, prev):
         """
@@ -1316,7 +1339,7 @@
             self.tr("Check Vulnerabilities"), self.__checkVulnerability
         )
         # updateVulnerabilityDbAct
-        self.__pipMenu.addAction(
+        self.__updateVulnerabilitiesAct = self.__pipMenu.addAction(
             self.tr("Update Vulnerability Database"), self.__updateVulnerabilityDbCache
         )
         self.__pipMenu.addSeparator()
@@ -1364,7 +1387,12 @@
         self.__editVirtualenvConfigAct.setEnabled(enable)
 
         self.__checkVulnerabilityAct.setEnabled(
-            enable & self.vulnerabilityCheckBox.isEnabled()
+            enable
+            and self.vulnerabilityCheckBox.isEnabled()
+            and Preferences.getPip("VulnerabilityCheckEnabled")
+        )
+        self.__updateVulnerabilitiesAct.setEnabled(
+            enable and Preferences.getPip("VulnerabilityCheckEnabled")
         )
 
         self.__cyclonedxAct.setEnabled(enable)
@@ -1589,6 +1617,7 @@
             if dlg.result() == QDialog.DialogCode.Accepted:
                 dlg.setPreferences()
                 Preferences.syncPreferences()
+                self.preferencesChanged()
 
     @pyqtSlot()
     def __showCacheInfo(self):
@@ -1631,6 +1660,22 @@
     ##################################################################
 
     @pyqtSlot(bool)
+    def setVulnerabilityEnabled(self, enable):
+        """
+        Public slot to set the enabled state of the vulnerability checks.
+
+        @param enable vulnerability checks enabled state
+        @type bool
+        """
+        self.vulnerabilityCheckBox.setChecked(enable)
+        self.vulnerabilityCheckBox.setEnabled(enable)
+        self.packagesList.setColumnHidden(
+            PipPackagesWidget.VulnerabilityColumn, not enable
+        )
+        if not enable:
+            self.__clearVulnerabilityInfo()
+
+    @pyqtSlot(bool)
     def on_vulnerabilityCheckBox_clicked(self, checked):
         """
         Private slot handling a change of the automatic vulnerability checks.
@@ -1640,6 +1685,8 @@
         """
         if checked:
             self.__updateVulnerabilityData(clearFirst=True)
+        else:
+            self.__clearVulnerabilityInfo()
 
         self.packagesList.header().setSectionHidden(
             PipPackagesWidget.VulnerabilityColumn, not checked
@@ -1691,37 +1738,37 @@
                 )
             )
 
-        error, vulnerabilities = self.__pip.getVulnerabilityChecker().check(packages)
-        if error == VulnerabilityCheckError.OK:
-            for package in vulnerabilities:
-                items = self.packagesList.findItems(
-                    package, Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive
-                )
-                if items:
-                    itm = items[0]
-                    itm.setData(
-                        PipPackagesWidget.VulnerabilityColumn,
-                        PipPackagesWidget.VulnerabilityRole,
-                        vulnerabilities[package],
+        if packages:
+            error, vulnerabilities = self.__pip.getVulnerabilityChecker().check(
+                packages
+            )
+            if error == VulnerabilityCheckError.OK:
+                for package in vulnerabilities:
+                    items = self.packagesList.findItems(
+                        package,
+                        Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive,
                     )
-                    affected = {v.spec for v in vulnerabilities[package]}
-                    itm.setText(
-                        PipPackagesWidget.VulnerabilityColumn, ", ".join(affected)
-                    )
-                    itm.setIcon(
-                        PipPackagesWidget.VulnerabilityColumn,
-                        EricPixmapCache.getIcon("securityLow"),
-                    )
+                    if items:
+                        itm = items[0]
+                        itm.setData(
+                            PipPackagesWidget.VulnerabilityColumn,
+                            PipPackagesWidget.VulnerabilityRole,
+                            vulnerabilities[package],
+                        )
+                        affected = {v.spec for v in vulnerabilities[package]}
+                        itm.setText(
+                            PipPackagesWidget.VulnerabilityColumn, ", ".join(affected)
+                        )
+                        itm.setIcon(
+                            PipPackagesWidget.VulnerabilityColumn,
+                            EricPixmapCache.getIcon("securityLow"),
+                        )
 
-        elif error in (
-            VulnerabilityCheckError.FullDbUnavailable,
-            VulnerabilityCheckError.SummaryDbUnavailable,
-        ):
-            self.vulnerabilityCheckBox.setChecked(False)
-            self.vulnerabilityCheckBox.setEnabled(False)
-            self.packagesList.setColumnHidden(
-                PipPackagesWidget.VulnerabilityColumn, True
-            )
+            elif error in (
+                VulnerabilityCheckError.FullDbUnavailable,
+                VulnerabilityCheckError.SummaryDbUnavailable,
+            ):
+                self.setVulnerabilityEnabled(False)
 
     @pyqtSlot()
     def __updateVulnerabilityDbCache(self):
@@ -2102,3 +2149,22 @@
         if venvName == self.__pip.getProjectEnvironmentString():
             venvName = "<project>"
         CycloneDXInterface.createCycloneDXFile(venvName)
+
+    ##################################################################
+    ## Interface to preferences
+    ##################################################################
+
+    @pyqtSlot()
+    def preferencesChanged(self):
+        """
+        Public slot to handle a change of preferences.
+        """
+        enable = self.setVulnerabilityEnabled(
+            Preferences.getPip("VulnerabilityCheckEnabled")
+        )
+        if enable != self.vulnerabilityCheckBox.isEnabled():
+            # only if status changes because it is an expensive operation
+            if self.vulnerabilityCheckBox.isChecked():
+                self.__updateVulnerabilityData(clearFirst=True)
+            else:
+                self.__clearVulnerabilityInfo()

eric ide

mercurial