eric7/PipInterface/PipPackagesWidget.py

branch
eric7
changeset 8977
663521af48b2
parent 8881
54e42bc2437a
child 8978
38c3ddf21537
equal deleted inserted replaced
8976:ca442cd49b9e 8977:663521af48b2
11 import os 11 import os
12 import html.parser 12 import html.parser
13 import contextlib 13 import contextlib
14 14
15 from PyQt6.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery 15 from PyQt6.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery
16 from PyQt6.QtGui import QIcon
16 from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest 17 from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
17 from PyQt6.QtWidgets import ( 18 from PyQt6.QtWidgets import (
18 QWidget, QToolButton, QApplication, QHeaderView, QTreeWidgetItem, 19 QWidget, QToolButton, QApplication, QHeaderView, QTreeWidgetItem,
19 QMenu, QDialog 20 QMenu, QDialog
20 ) 21 )
146 ShowProcessClassifiersMode = 1 147 ShowProcessClassifiersMode = 1
147 ShowProcessEntryPointsMode = 2 148 ShowProcessEntryPointsMode = 2
148 ShowProcessFilesListMode = 3 149 ShowProcessFilesListMode = 3
149 150
150 SearchVersionRole = Qt.ItemDataRole.UserRole + 1 151 SearchVersionRole = Qt.ItemDataRole.UserRole + 1
152 VulnerabilityRole = Qt.ItemDataRole.UserRole + 2
153
154 PackageColumn = 0
155 InstalledVersionColumn = 1
156 AvailableVersionColumn = 2
157 VulnerabilityColumn = 3
151 158
152 def __init__(self, pip, parent=None): 159 def __init__(self, pip, parent=None):
153 """ 160 """
154 Constructor 161 Constructor
155 162
187 self.showDetailsButton.setIcon(UI.PixmapCache.getIcon("info")) 194 self.showDetailsButton.setIcon(UI.PixmapCache.getIcon("info"))
188 195
189 self.__pip = pip 196 self.__pip = pip
190 197
191 self.packagesList.header().setSortIndicator( 198 self.packagesList.header().setSortIndicator(
192 0, Qt.SortOrder.AscendingOrder) 199 PipPackagesWidget.PackageColumn, Qt.SortOrder.AscendingOrder)
193 200
194 self.__infoLabels = { 201 self.__infoLabels = {
195 "name": self.tr("Name:"), 202 "name": self.tr("Name:"),
196 "version": self.tr("Version:"), 203 "version": self.tr("Version:"),
197 "location": self.tr("Location:"), 204 "location": self.tr("Location:"),
322 @return list of selected items that can be updated 329 @return list of selected items that can be updated
323 @rtype list of QTreeWidgetItem 330 @rtype list of QTreeWidgetItem
324 """ 331 """
325 return [ 332 return [
326 itm for itm in self.packagesList.selectedItems() 333 itm for itm in self.packagesList.selectedItems()
327 if bool(itm.text(2)) 334 if bool(itm.text(PipPackagesWidget.AvailableVersionColumn))
328 ] 335 ]
329 336
330 def __allUpdateableItems(self): 337 def __allUpdateableItems(self):
331 """ 338 """
332 Private method to get a list of all items that can be updated. 339 Private method to get a list of all items that can be updated.
335 @rtype list of QTreeWidgetItem 342 @rtype list of QTreeWidgetItem
336 """ 343 """
337 updateableItems = [] 344 updateableItems = []
338 for index in range(self.packagesList.topLevelItemCount()): 345 for index in range(self.packagesList.topLevelItemCount()):
339 itm = self.packagesList.topLevelItem(index) 346 itm = self.packagesList.topLevelItem(index)
340 if itm.text(2): 347 if itm.text(PipPackagesWidget.AvailableVersionColumn):
341 updateableItems.append(itm) 348 updateableItems.append(itm)
342 349
343 return updateableItems 350 return updateableItems
344 351
345 def __updateActionButtons(self): 352 def __updateActionButtons(self):
382 localPackages=self.localCheckBox.isChecked(), 389 localPackages=self.localCheckBox.isChecked(),
383 notRequired=self.notRequiredCheckBox.isChecked(), 390 notRequired=self.notRequiredCheckBox.isChecked(),
384 usersite=self.userCheckBox.isChecked(), 391 usersite=self.userCheckBox.isChecked(),
385 ) 392 )
386 for package, version in installedPackages: 393 for package, version in installedPackages:
387 QTreeWidgetItem(self.packagesList, [package, version]) 394 QTreeWidgetItem(self.packagesList,
395 [package, version, "", ""])
388 self.packagesList.setUpdatesEnabled(True) 396 self.packagesList.setUpdatesEnabled(True)
389 self.statusLabel.setText( 397 self.statusLabel.setText(
390 self.tr("Getting outdated packages...")) 398 self.tr("Getting outdated packages..."))
391 QApplication.processEvents() 399 QApplication.processEvents()
392 400
404 Qt.MatchFlag.MatchExactly | 412 Qt.MatchFlag.MatchExactly |
405 Qt.MatchFlag.MatchCaseSensitive 413 Qt.MatchFlag.MatchCaseSensitive
406 ) 414 )
407 if items: 415 if items:
408 itm = items[0] 416 itm = items[0]
409 itm.setText(2, latest) 417 itm.setText(
418 PipPackagesWidget.AvailableVersionColumn,
419 latest)
410 420
411 self.packagesList.sortItems(0, Qt.SortOrder.AscendingOrder) 421 self.packagesList.sortItems(
422 PipPackagesWidget.PackageColumn,
423 Qt.SortOrder.AscendingOrder)
412 for col in range(self.packagesList.columnCount()): 424 for col in range(self.packagesList.columnCount()):
413 self.packagesList.resizeColumnToContents(col) 425 self.packagesList.resizeColumnToContents(col)
414 self.packagesList.setUpdatesEnabled(True) 426 self.packagesList.setUpdatesEnabled(True)
427
428 # 3. update with vulnerability information
429 if self.vulnerabilityCheckBox.isChecked():
430 self.__updateVulnerabilityData()
415 self.statusLabel.hide() 431 self.statusLabel.hide()
416 432
417 self.__updateActionButtons() 433 self.__updateActionButtons()
418 self.__updateSearchActionButtons() 434 self.__updateSearchActionButtons()
419 self.__updateSearchButton() 435 self.__updateSearchButton()
426 @param index index of the selected Python environment 442 @param index index of the selected Python environment
427 @type int 443 @type int
428 """ 444 """
429 self.__refreshPackagesList() 445 self.__refreshPackagesList()
430 446
431 @pyqtSlot(bool) 447 @pyqtSlot()
432 def on_localCheckBox_clicked(self, checked): 448 def on_localCheckBox_clicked(self):
433 """ 449 """
434 Private slot handling the switching of the local mode. 450 Private slot handling the switching of the local mode.
435
436 @param checked state of the local check box
437 @type bool
438 """ 451 """
439 self.__refreshPackagesList() 452 self.__refreshPackagesList()
440 453
441 @pyqtSlot(bool) 454 @pyqtSlot()
442 def on_notRequiredCheckBox_clicked(self, checked): 455 def on_notRequiredCheckBox_clicked(self):
443 """ 456 """
444 Private slot handling the switching of the 'not required' mode. 457 Private slot handling the switching of the 'not required' mode.
445
446 @param checked state of the 'not required' check box
447 @type bool
448 """ 458 """
449 self.__refreshPackagesList() 459 self.__refreshPackagesList()
450 460
451 @pyqtSlot(bool) 461 @pyqtSlot()
452 def on_userCheckBox_clicked(self, checked): 462 def on_userCheckBox_clicked(self):
453 """ 463 """
454 Private slot handling the switching of the 'user-site' mode. 464 Private slot handling the switching of the 'user-site' mode.
455
456 @param checked state of the 'user-site' check box
457 @type bool
458 """ 465 """
459 self.__refreshPackagesList() 466 self.__refreshPackagesList()
460 467
461 @pyqtSlot() 468 @pyqtSlot()
462 def on_packagesList_itemSelectionChanged(self): 469 def on_packagesList_itemSelectionChanged(self):
614 @pyqtSlot() 621 @pyqtSlot()
615 def on_uninstallButton_clicked(self): 622 def on_uninstallButton_clicked(self):
616 """ 623 """
617 Private slot to remove selected packages of the selected environment. 624 Private slot to remove selected packages of the selected environment.
618 """ 625 """
619 packages = [itm.text(0) for itm in self.packagesList.selectedItems()] 626 packages = [itm.text(PipPackagesWidget.PackageColumn)
627 for itm in self.packagesList.selectedItems()]
620 self.executeUninstallPackages(packages) 628 self.executeUninstallPackages(packages)
621 629
622 def executeUninstallPackages(self, packages): 630 def executeUninstallPackages(self, packages):
623 """ 631 """
624 Public method to uninstall the given list of packages. 632 Public method to uninstall the given list of packages.
651 """ 659 """
652 Private slot to show information for the selected package. 660 Private slot to show information for the selected package.
653 """ 661 """
654 item = self.packagesList.selectedItems()[0] 662 item = self.packagesList.selectedItems()[0]
655 if item: 663 if item:
656 packageName = item.text(0) 664 packageName = item.text(PipPackagesWidget.PackageColumn)
657 upgradable = bool(item.text(2)) 665 upgradable = bool(item.text(2))
658 # show details for available version or installed one 666 # show details for available version or installed one
659 if item.text(2): 667 if item.text(2):
660 packageVersion = item.text(2) 668 packageVersion = item.text(2)
661 else: 669 else:
1135 @pyqtSlot() 1143 @pyqtSlot()
1136 def __reinstallPackages(self): 1144 def __reinstallPackages(self):
1137 """ 1145 """
1138 Private slot to force a re-installation of the selected packages. 1146 Private slot to force a re-installation of the selected packages.
1139 """ 1147 """
1140 packages = [itm.text(0) for itm in self.packagesList.selectedItems()] 1148 packages = [itm.text(PipPackagesWidget.PackageColumn)
1149 for itm in self.packagesList.selectedItems()]
1141 venvName = self.environmentsComboBox.currentText() 1150 venvName = self.environmentsComboBox.currentText()
1142 if venvName and packages: 1151 if venvName and packages:
1143 self.__pip.installPackages(packages, venvName=venvName, 1152 self.__pip.installPackages(packages, venvName=venvName,
1144 forceReinstall=True) 1153 forceReinstall=True)
1145 self.on_refreshButton_clicked() 1154 self.on_refreshButton_clicked()
1281 Private slot to empty the pip cache. 1290 Private slot to empty the pip cache.
1282 """ 1291 """
1283 venvName = self.environmentsComboBox.currentText() 1292 venvName = self.environmentsComboBox.currentText()
1284 if venvName: 1293 if venvName:
1285 self.__pip.cachePurge(venvName) 1294 self.__pip.cachePurge(venvName)
1295
1296 ##################################################################
1297 ## Interface to the vulnerability checks below
1298 ##################################################################
1299
1300 @pyqtSlot(bool)
1301 def on_vulnerabilityCheckBox_clicked(self, checked):
1302 """
1303 Private slot handling a change of the automatic vulnerability checks.
1304
1305 @param checked flag indicating the state of the check box
1306 @type bool
1307 """
1308 if checked:
1309 self.__updateVulnerabilityData(clearFirst=True)
1310
1311 @pyqtSlot()
1312 def __clearVulnerabilityInfo(self):
1313 """
1314 Private slot to clear the vulnerability info.
1315 """
1316 for row in range(self.packagesList.topLevelItemCount()):
1317 itm = self.packagesList.topLevelItem(row)
1318 itm.setText(PipPackagesWidget.VulnerabilityColumn, "")
1319 itm.setToolTip(PipPackagesWidget.VulnerabilityColumn, "")
1320 itm.setIcon(PipPackagesWidget.VulnerabilityColumn, QIcon())
1321 itm.setData(PipPackagesWidget.VulnerabilityColumn,
1322 PipPackagesWidget.VulnerabilityRole,
1323 None)
1324
1325 @pyqtSlot()
1326 def __updateVulnerabilityData(self, clearFirst=True):
1327 """
1328 Private slot to update the shown vulnerability info.
1329
1330 @param clearFirst flag indicating to clear the vulnerability info first
1331 (defaults to True)
1332 @type bool (optional)
1333 """
1334 if clearFirst:
1335 self.__clearVulnerabilityInfo()
1336
1337 packages = [] # TODO: fill this list with real data
1338
1339 error, vulnerabilities = (
1340 self.__pip.getVulnerabilityChecker().check(packages)
1341 )

eric ide

mercurial