5 |
5 |
6 """ |
6 """ |
7 Module implementing the pip packages management widget. |
7 Module implementing the pip packages management widget. |
8 """ |
8 """ |
9 |
9 |
|
10 import contextlib |
|
11 import html.parser |
|
12 import os |
10 import textwrap |
13 import textwrap |
11 import os |
|
12 import html.parser |
|
13 import contextlib |
|
14 |
14 |
15 from packaging.specifiers import SpecifierSet |
15 from packaging.specifiers import SpecifierSet |
16 |
16 from PyQt6.QtCore import Qt, QUrl, QUrlQuery, pyqtSlot |
17 from PyQt6.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery |
|
18 from PyQt6.QtGui import QIcon |
17 from PyQt6.QtGui import QIcon |
19 from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest |
18 from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest |
20 from PyQt6.QtWidgets import ( |
19 from PyQt6.QtWidgets import ( |
|
20 QAbstractItemView, |
|
21 QApplication, |
|
22 QDialog, |
|
23 QHeaderView, |
|
24 QMenu, |
|
25 QToolButton, |
|
26 QTreeWidgetItem, |
21 QWidget, |
27 QWidget, |
22 QToolButton, |
|
23 QApplication, |
|
24 QHeaderView, |
|
25 QTreeWidgetItem, |
|
26 QMenu, |
|
27 QDialog, |
|
28 QAbstractItemView, |
|
29 ) |
28 ) |
30 |
29 |
|
30 from eric7 import Globals, Preferences |
|
31 from eric7.EricGui import EricPixmapCache |
|
32 from eric7.EricGui.EricOverrideCursor import EricOverrideCursor |
|
33 from eric7.EricWidgets import EricMessageBox |
31 from eric7.EricWidgets.EricApplication import ericApp |
34 from eric7.EricWidgets.EricApplication import ericApp |
32 from eric7.EricWidgets import EricMessageBox |
|
33 from eric7.EricGui.EricOverrideCursor import EricOverrideCursor |
|
34 |
35 |
35 from .PipVulnerabilityChecker import Package, VulnerabilityCheckError |
36 from .PipVulnerabilityChecker import Package, VulnerabilityCheckError |
36 from .Ui_PipPackagesWidget import Ui_PipPackagesWidget |
37 from .Ui_PipPackagesWidget import Ui_PipPackagesWidget |
37 |
|
38 from eric7.EricGui import EricPixmapCache |
|
39 from eric7 import Globals, Preferences |
|
40 |
38 |
41 |
39 |
42 class PypiSearchResultsParser(html.parser.HTMLParser): |
40 class PypiSearchResultsParser(html.parser.HTMLParser): |
43 """ |
41 """ |
44 Class implementing the parser for the PyPI search result page. |
42 Class implementing the parser for the PyPI search result page. |
1108 @type bool (optional) |
1106 @type bool (optional) |
1109 @param installable flag indicating that the package may be installed |
1107 @param installable flag indicating that the package may be installed |
1110 (defaults to False) |
1108 (defaults to False) |
1111 @type bool (optional) |
1109 @type bool (optional) |
1112 """ |
1110 """ |
|
1111 from .PipPackageDetailsDialog import PipPackageDetailsDialog |
|
1112 |
1113 with EricOverrideCursor(): |
1113 with EricOverrideCursor(): |
1114 packageData = self.__pip.getPackageDetails(packageName, packageVersion) |
1114 packageData = self.__pip.getPackageDetails(packageName, packageVersion) |
1115 |
1115 |
1116 if packageData: |
1116 if packageData: |
1117 from .PipPackageDetailsDialog import PipPackageDetailsDialog |
|
1118 |
|
1119 self.showDetailsButton.setEnabled(True) |
1117 self.showDetailsButton.setEnabled(True) |
1120 |
1118 |
1121 if installable: |
1119 if installable: |
1122 buttonsMode = PipPackageDetailsDialog.ButtonInstall |
1120 buttonsMode = PipPackageDetailsDialog.ButtonInstall |
1123 elif upgradable: |
1121 elif upgradable: |
1332 @pyqtSlot() |
1330 @pyqtSlot() |
1333 def __installPackages(self): |
1331 def __installPackages(self): |
1334 """ |
1332 """ |
1335 Private slot to install packages to be given by the user. |
1333 Private slot to install packages to be given by the user. |
1336 """ |
1334 """ |
|
1335 from .PipPackagesInputDialog import PipPackagesInputDialog |
|
1336 |
1337 venvName = self.environmentsComboBox.currentText() |
1337 venvName = self.environmentsComboBox.currentText() |
1338 if venvName: |
1338 if venvName: |
1339 from .PipPackagesInputDialog import PipPackagesInputDialog |
|
1340 |
|
1341 dlg = PipPackagesInputDialog(self, self.tr("Install Packages")) |
1339 dlg = PipPackagesInputDialog(self, self.tr("Install Packages")) |
1342 if dlg.exec() == QDialog.DialogCode.Accepted: |
1340 if dlg.exec() == QDialog.DialogCode.Accepted: |
1343 packages, user = dlg.getData() |
1341 packages, user = dlg.getData() |
1344 self.executeInstallPackages(packages, userSite=user) |
1342 self.executeInstallPackages(packages, userSite=user) |
1345 |
1343 |
1346 @pyqtSlot() |
1344 @pyqtSlot() |
1347 def __installLocalPackage(self): |
1345 def __installLocalPackage(self): |
1348 """ |
1346 """ |
1349 Private slot to install a package available on local storage. |
1347 Private slot to install a package available on local storage. |
1350 """ |
1348 """ |
|
1349 from .PipFileSelectionDialog import PipFileSelectionDialog |
|
1350 |
1351 venvName = self.environmentsComboBox.currentText() |
1351 venvName = self.environmentsComboBox.currentText() |
1352 if venvName: |
1352 if venvName: |
1353 from .PipFileSelectionDialog import PipFileSelectionDialog |
|
1354 |
|
1355 dlg = PipFileSelectionDialog(self, "package") |
1353 dlg = PipFileSelectionDialog(self, "package") |
1356 if dlg.exec() == QDialog.DialogCode.Accepted: |
1354 if dlg.exec() == QDialog.DialogCode.Accepted: |
1357 package, user = dlg.getData() |
1355 package, user = dlg.getData() |
1358 if package and os.path.exists(package): |
1356 if package and os.path.exists(package): |
1359 self.executeInstallPackages([package], userSite=user) |
1357 self.executeInstallPackages([package], userSite=user) |
1395 @pyqtSlot() |
1393 @pyqtSlot() |
1396 def __generateRequirements(self): |
1394 def __generateRequirements(self): |
1397 """ |
1395 """ |
1398 Private slot to generate the contents for a requirements file. |
1396 Private slot to generate the contents for a requirements file. |
1399 """ |
1397 """ |
|
1398 from .PipFreezeDialog import PipFreezeDialog, PipFreezeDialogModes |
|
1399 |
1400 venvName = self.environmentsComboBox.currentText() |
1400 venvName = self.environmentsComboBox.currentText() |
1401 if venvName: |
1401 if venvName: |
1402 from .PipFreezeDialog import PipFreezeDialog, PipFreezeDialogModes |
|
1403 |
|
1404 self.__freezeDialog = PipFreezeDialog( |
1402 self.__freezeDialog = PipFreezeDialog( |
1405 self.__pip, mode=PipFreezeDialogModes.Requirements, parent=self |
1403 self.__pip, mode=PipFreezeDialogModes.Requirements, parent=self |
1406 ) |
1404 ) |
1407 self.__freezeDialog.show() |
1405 self.__freezeDialog.show() |
1408 self.__freezeDialog.start(venvName) |
1406 self.__freezeDialog.start(venvName) |
1410 @pyqtSlot() |
1408 @pyqtSlot() |
1411 def __generateConstraints(self): |
1409 def __generateConstraints(self): |
1412 """ |
1410 """ |
1413 Private slot to generate the contents for a constraints file. |
1411 Private slot to generate the contents for a constraints file. |
1414 """ |
1412 """ |
|
1413 from .PipFreezeDialog import PipFreezeDialog, PipFreezeDialogModes |
|
1414 |
1415 venvName = self.environmentsComboBox.currentText() |
1415 venvName = self.environmentsComboBox.currentText() |
1416 if venvName: |
1416 if venvName: |
1417 from .PipFreezeDialog import PipFreezeDialog, PipFreezeDialogModes |
|
1418 |
|
1419 self.__freezeDialog = PipFreezeDialog( |
1417 self.__freezeDialog = PipFreezeDialog( |
1420 self.__pip, mode=PipFreezeDialogModes.Constraints, parent=self |
1418 self.__pip, mode=PipFreezeDialogModes.Constraints, parent=self |
1421 ) |
1419 ) |
1422 self.__freezeDialog.show() |
1420 self.__freezeDialog.show() |
1423 self.__freezeDialog.start(venvName) |
1421 self.__freezeDialog.start(venvName) |
1953 @pyqtSlot() |
1951 @pyqtSlot() |
1954 def __createSBOMFile(self): |
1952 def __createSBOMFile(self): |
1955 """ |
1953 """ |
1956 Private slot to create a "Software Bill Of Material" file. |
1954 Private slot to create a "Software Bill Of Material" file. |
1957 """ |
1955 """ |
1958 import CycloneDXInterface |
1956 import CycloneDXInterface # __IGNORE_WARNING_I102__ |
1959 |
1957 |
1960 venvName = self.environmentsComboBox.currentText() |
1958 venvName = self.environmentsComboBox.currentText() |
1961 if venvName == self.__pip.getProjectEnvironmentString(): |
1959 if venvName == self.__pip.getProjectEnvironmentString(): |
1962 venvName = "<project>" |
1960 venvName = "<project>" |
1963 CycloneDXInterface.createCycloneDXFile(venvName) |
1961 CycloneDXInterface.createCycloneDXFile(venvName) |