Sun, 26 Jun 2022 15:01:48 +0200
Changed code to use the 'trove-classifiers' package instead of a local text file copy or a download from PyPI.
# -*- coding: utf-8 -*- # Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a dialog to edit the metadata of the CycloneDX SBOM. """ from PyQt6.QtCore import pyqtSlot, QCoreApplication from PyQt6.QtWidgets import QDialog, QDialogButtonBox from cyclonedx.model.component import ComponentType import trove_classifiers from .Ui_CycloneDXMetaDataDialog import Ui_CycloneDXMetaDataDialog class CycloneDXMetaDataDialog(QDialog, Ui_CycloneDXMetaDataDialog): """ Class implementing a dialog to edit the metadata of the CycloneDX SBOM. """ ComponentTypeMapping = { ComponentType.APPLICATION: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Application"), ComponentType.CONTAINER: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Container"), ComponentType.DEVICE: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Device"), ComponentType.FILE: QCoreApplication.translate( "CycloneDXMetaDataDialog", "File"), ComponentType.FIRMWARE: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Firmware"), ComponentType.FRAMEWORK: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Framework"), ComponentType.LIBRARY: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Library"), ComponentType.OPERATING_SYSTEM: QCoreApplication.translate( "CycloneDXMetaDataDialog", "Operating System"), } def __init__(self, metadata=None, parent=None): """ Constructor @param metadata dictionary containing metadata to populate the dialog (defaults to None) @type dict (optional) @param parent reference to the parent widget (defaults to None) @type QWidget (optional) """ super().__init__(parent) self.setupUi(self) self.__populateComponentTypeSelector() self.__populateLicenseSelector() if metadata: # populate the dialog from given metadata dictionary self.nameEdit.setText(metadata["Name"]) self.versionEdit.setText(metadata["Version"]) self.descriptionEdit.setPlainText(metadata["Description"]) self.authorEdit.setText(metadata["AuthorName"]) self.emailEdit.setText(metadata["AuthorEmail"]) self.licenseComboBox.setCurrentText(metadata["License"]) self.manufacturerEdit.setText(metadata["Manufacturer"]) self.supplierEdit.setText(metadata["Supplier"]) index = self.typeComboBox.findData(metadata["Type"]) self.typeComboBox.setCurrentIndex(index) self.nameEdit.textChanged.connect(self.__updateOkButton) self.typeComboBox.currentTextChanged.connect(self.__updateOkButton) self.licenseComboBox.currentTextChanged.connect(self.__updateOkButton) self.__updateOkButton() def __populateComponentTypeSelector(self): """ Private method to populate the component type selector. """ self.typeComboBox.addItem("", "") for componentType, displayStr in sorted( CycloneDXMetaDataDialog.ComponentTypeMapping.items(), key=lambda x: x[1] ): self.typeComboBox.addItem(displayStr, componentType) def __populateLicenseSelector(self): """ Private method to populate the license selector with the list of trove license types. """ self.licenseComboBox.addItem("") self.licenseComboBox.addItems(sorted( classifier.split("::")[-1].strip() for classifier in trove_classifiers.classifiers if classifier.startswith("License ::") )) @pyqtSlot() def __updateOkButton(self): """ Private slot to update the enabled state of the OK button. """ self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( bool(self.nameEdit.text()) and bool(self.typeComboBox.currentText()) and bool(self.licenseComboBox.currentText()) ) def getMetaData(self): """ Public method to get the entered data. @return dictionary containing the metadata. @rtype dict """ return { "Name": self.nameEdit.text(), "Type": self.typeComboBox.currentData(), "Version": self.versionEdit.text(), "Description": self.descriptionEdit.toPlainText(), "AuthorName": self.authorEdit.text(), "AuthorEmail": self.emailEdit.text(), "License": self.licenseComboBox.currentText(), "Manufacturer": self.manufacturerEdit.text(), "Supplier": self.supplierEdit.text(), }