src/eric7/CycloneDXInterface/CycloneDXUtilities.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/CycloneDXInterface/CycloneDXUtilities.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/CycloneDXInterface/CycloneDXUtilities.py	Wed Jul 13 14:55:47 2022 +0200
@@ -18,14 +18,21 @@
 from packageurl import PackageURL
 
 from cyclonedx.model import (
-    ExternalReference, ExternalReferenceType, LicenseChoice,
-    OrganizationalContact, OrganizationalEntity, Tool, XsUri
+    ExternalReference,
+    ExternalReferenceType,
+    LicenseChoice,
+    OrganizationalContact,
+    OrganizationalEntity,
+    Tool,
+    XsUri,
 )
 from cyclonedx.model.bom import Bom
 from cyclonedx.model.component import Component
 from cyclonedx.model.vulnerability import Vulnerability, VulnerabilitySource
 from cyclonedx.output import (
-    OutputFormat, SchemaVersion, get_instance as get_output_instance
+    OutputFormat,
+    SchemaVersion,
+    get_instance as get_output_instance,
 )
 from cyclonedx.parser import BaseParser
 
@@ -33,24 +40,23 @@
 from cyclonedx_py.parser.poetry import PoetryFileParser
 from cyclonedx_py.parser.requirements import RequirementsFileParser
 
-from PipInterface.PipVulnerabilityChecker import (
-    Package, VulnerabilityCheckError
-)
+from PipInterface.PipVulnerabilityChecker import Package, VulnerabilityCheckError
 
 
 class CycloneDXEnvironmentParser(BaseParser):
     """
     Class implementing a parser to get package data for a named environment.
     """
+
     def __init__(self, venvName):
         """
         Constructor
-        
+
         @param venvName name of the virtual environment
         @type str
         """
         super().__init__()
-        
+
         pip = ericApp().getObject("Pip")
         packages = pip.getLicenses(venvName)
         for package in packages:
@@ -60,40 +66,44 @@
                 author=package["Author"],
                 description=package["Description"],
                 purl=PackageURL(
-                    type='pypi',
-                    name=package["Name"],
-                    version=package["Version"]
-                )
+                    type="pypi", name=package["Name"], version=package["Version"]
+                ),
             )
             for lic in package["License"].split(";"):
-                comp.licenses.add(
-                    LicenseChoice(license_expression=lic.strip())
-                )
-            
+                comp.licenses.add(LicenseChoice(license_expression=lic.strip()))
+
             self._components.append(comp)
 
 
 def createCycloneDXFile(venvName):
     """
     Function to create a CyccloneDX SBOM file.
-    
+
     @param venvName name of the virtual environment
     @type str
     @exception RuntimeError raised to indicate illegal creation parameters
     """
     from .CycloneDXConfigDialog import CycloneDXConfigDialog
+
     dlg = CycloneDXConfigDialog(venvName)
     if dlg.exec() == QDialog.DialogCode.Accepted:
-        (inputSource, inputFile, fileFormat, schemaVersion, sbomFile,
-         withVulnerabilities, withDependencies, metadataDict) = dlg.getData()
-        
+        (
+            inputSource,
+            inputFile,
+            fileFormat,
+            schemaVersion,
+            sbomFile,
+            withVulnerabilities,
+            withDependencies,
+            metadataDict,
+        ) = dlg.getData()
+
         # check error conditions first
-        if inputSource not in ("environment", "pipenv", "poetry",
-                               "requirements"):
+        if inputSource not in ("environment", "pipenv", "poetry", "requirements"):
             raise RuntimeError("Unsupported input source given.")
         if fileFormat not in ("XML", "JSON"):
             raise RuntimeError("Unsupported SBOM file format given.")
-        
+
         if inputSource == "environment":
             parser = CycloneDXEnvironmentParser(venvName)
         else:
@@ -102,106 +112,108 @@
                 EricMessageBox.warning(
                     None,
                     QCoreApplication.translate(
-                        "CycloneDX", "CycloneDX - SBOM Creation"),
+                        "CycloneDX", "CycloneDX - SBOM Creation"
+                    ),
                     QCoreApplication.translate(
                         "CycloneDX",
                         "<p>The configured input file <b>{0}</b> does not"
-                        " exist. Aborting...</p>"
-                    ).format(inputFile)
+                        " exist. Aborting...</p>",
+                    ).format(inputFile),
                 )
                 return
-            
+
             if inputSource == "pipenv":
                 parser = PipEnvFileParser(pipenv_lock_filename=inputFile)
             elif inputSource == "poetry":
                 parser = PoetryFileParser(poetry_lock_filename=inputFile)
             elif inputSource == "requirements":
                 parser = RequirementsFileParser(requirements_file=inputFile)
-        
+
         if withVulnerabilities:
             addCycloneDXVulnerabilities(parser)
-        
+
         if withDependencies:
             addCycloneDXDependencies(parser, venvName)
-        
+
         if fileFormat == "XML":
             outputFormat = OutputFormat.XML
         elif fileFormat == "JSON":
             outputFormat = OutputFormat.JSON
-        
+
         if parser.has_warnings():
-            excludedList = ["<li>{0}</li>".format(warning.get_item())
-                            for warning in parser.get_warnings()]
+            excludedList = [
+                "<li>{0}</li>".format(warning.get_item())
+                for warning in parser.get_warnings()
+            ]
             EricMessageBox.warning(
                 None,
-                QCoreApplication.translate(
-                    "CycloneDX", "CycloneDX - SBOM Creation"),
+                QCoreApplication.translate("CycloneDX", "CycloneDX - SBOM Creation"),
                 QCoreApplication.translate(
                     "CycloneDX",
                     "<p>Some of the dependencies do not have pinned version"
                     " numbers.<ul>{0}</ul>The above listed packages will NOT"
                     " be included in the generated CycloneDX SBOM file as"
-                    " version is a mandatory field.</p>"
-                ).format("".join(excludedList))
+                    " version is a mandatory field.</p>",
+                ).format("".join(excludedList)),
             )
-        
+
         bom = Bom.from_parser(parser=parser)
         _amendMetaData(bom.metadata, metadataDict)
         output = get_output_instance(
             bom=bom,
             output_format=outputFormat,
-            schema_version=SchemaVersion['V{0}'.format(
-                schemaVersion.replace('.', '_')
-            )]
+            schema_version=SchemaVersion[
+                "V{0}".format(schemaVersion.replace(".", "_"))
+            ],
         )
         output.output_to_file(filename=sbomFile, allow_overwrite=True)
-        
+
         EricMessageBox.information(
             None,
-            QCoreApplication.translate(
-                "CycloneDX", "CycloneDX - SBOM Creation"),
+            QCoreApplication.translate("CycloneDX", "CycloneDX - SBOM Creation"),
             QCoreApplication.translate(
-                "CycloneDX",
-                "<p>The SBOM data was written to file <b>{0}</b>.</p>"
-            ).format(sbomFile)
+                "CycloneDX", "<p>The SBOM data was written to file <b>{0}</b>.</p>"
+            ).format(sbomFile),
         )
 
 
 def addCycloneDXVulnerabilities(parser):
     """
     Function to add vulnerability data to the list of created components.
-    
+
     @param parser reference to the parser object containing the list of
         components
     @type BaseParser
     """
     components = parser.get_components()
-    
+
     packages = [
         Package(name=component.name, version=component.version)
         for component in components
     ]
-    
+
     pip = ericApp().getObject("Pip")
     error, vulnerabilities = pip.getVulnerabilityChecker().check(packages)
-    
+
     if error == VulnerabilityCheckError.OK:
         for package in vulnerabilities:
             component = findCyccloneDXComponent(components, package)
             if component:
                 for vuln in vulnerabilities[package]:
-                    component.add_vulnerability(Vulnerability(
-                        id=vuln.cve,
-                        description=vuln.advisory,
-                        recommendation="upgrade required",
-                        source=VulnerabilitySource(name="pyup.io")
-                    ))
+                    component.add_vulnerability(
+                        Vulnerability(
+                            id=vuln.cve,
+                            description=vuln.advisory,
+                            recommendation="upgrade required",
+                            source=VulnerabilitySource(name="pyup.io"),
+                        )
+                    )
 
 
 def addCycloneDXDependencies(parser, venvName):
     """
     Function to add dependency data to the list of created components.
-    
+
     @param parser reference to the parser object containing the list of
         components
     @type BaseParser
@@ -209,7 +221,7 @@
     @type str
     """
     components = parser.get_components()
-    
+
     pip = ericApp().getObject("Pip")
     dependencies = pip.getDependencyTree(venvName)
     for dependency in dependencies:
@@ -219,7 +231,7 @@
 def _addCycloneDXDependency(dependency, components):
     """
     Function to add a dependency to the given list of components.
-    
+
     @param dependency dependency to be added
     @type dict
     @param components list of components
@@ -229,8 +241,7 @@
     if component is not None:
         bomRefs = component.dependencies
         for dep in dependency["dependencies"]:
-            depComponent = findCyccloneDXComponent(
-                components, dep["package_name"])
+            depComponent = findCyccloneDXComponent(components, dep["package_name"])
             if depComponent is not None:
                 bomRefs.add(depComponent.bom_ref)
                 # recursively add sub-dependencies
@@ -241,7 +252,7 @@
 def findCyccloneDXComponent(components, name):
     """
     Function to find a component in a given list of components.
-    
+
     @param components list of components to scan
     @type list of Component
     @param name name of the component to search for
@@ -252,19 +263,19 @@
     for component in components:
         if component.name == name:
             return component
-    
+
     return None
 
 
 def _amendMetaData(bomMetaData, metadataDict):
     """
     Function to amend the SBOM meta data according the given data.
-    
+
     The modifications done are:
     <ul>
     <li>add eric7 to the tools</li>
     </ul>
-    
+
     @param bomMetaData reference to the SBOM meta data object
     @type BomMetaData
     @param metadataDict dictionary containing additional meta data
@@ -275,80 +286,74 @@
     # add a Tool entry for eric7
     try:
         from importlib.metadata import version as meta_version
-        __EricToolVersion = str(meta_version('eric-ide'))
+
+        __EricToolVersion = str(meta_version("eric-ide"))
     except Exception:
         from UI.Info import Version
+
         __EricToolVersion = Version
-    
-    EricTool = Tool(vendor='python-projects.org',
-                    name='eric-ide',
-                    version=__EricToolVersion)
-    EricTool.external_references.update([
-        ExternalReference(
-            reference_type=ExternalReferenceType.DISTRIBUTION,
-            url=XsUri(
-                "https://pypi.org/project/eric-ide/"
-            )
-        ),
-        ExternalReference(
-            reference_type=ExternalReferenceType.DOCUMENTATION,
-            url=XsUri(
-                "https://pypi.org/project/eric-ide/"
-            )
-        ),
-        ExternalReference(
-            reference_type=ExternalReferenceType.ISSUE_TRACKER,
-            url=XsUri(
-                "https://tracker.die-offenbachs.homelinux.org"
-            )
-        ),
-        ExternalReference(
-            reference_type=ExternalReferenceType.LICENSE,
-            url=XsUri(
-                "https://hg.die-offenbachs.homelinux.org/eric/file/tip/docs/"
-                "LICENSE.GPL3"
-            )
-        ),
-        ExternalReference(
-            reference_type=ExternalReferenceType.RELEASE_NOTES,
-            url=XsUri(
-                "https://hg.die-offenbachs.homelinux.org/eric/file/tip/docs/"
-                "changelog"
-            )
-        ),
-        ExternalReference(
-            reference_type=ExternalReferenceType.VCS,
-            url=XsUri(
-                "https://hg.die-offenbachs.homelinux.org/eric"
-            )
-        ),
-        ExternalReference(
-            reference_type=ExternalReferenceType.WEBSITE,
-            url=XsUri(
-                "https://eric-ide.python-projects.org"
-            )
-        )
-    ])
+
+    EricTool = Tool(
+        vendor="python-projects.org", name="eric-ide", version=__EricToolVersion
+    )
+    EricTool.external_references.update(
+        [
+            ExternalReference(
+                reference_type=ExternalReferenceType.DISTRIBUTION,
+                url=XsUri("https://pypi.org/project/eric-ide/"),
+            ),
+            ExternalReference(
+                reference_type=ExternalReferenceType.DOCUMENTATION,
+                url=XsUri("https://pypi.org/project/eric-ide/"),
+            ),
+            ExternalReference(
+                reference_type=ExternalReferenceType.ISSUE_TRACKER,
+                url=XsUri("https://tracker.die-offenbachs.homelinux.org"),
+            ),
+            ExternalReference(
+                reference_type=ExternalReferenceType.LICENSE,
+                url=XsUri(
+                    "https://hg.die-offenbachs.homelinux.org/eric/file/tip/docs/"
+                    "LICENSE.GPL3"
+                ),
+            ),
+            ExternalReference(
+                reference_type=ExternalReferenceType.RELEASE_NOTES,
+                url=XsUri(
+                    "https://hg.die-offenbachs.homelinux.org/eric/file/tip/docs/"
+                    "changelog"
+                ),
+            ),
+            ExternalReference(
+                reference_type=ExternalReferenceType.VCS,
+                url=XsUri("https://hg.die-offenbachs.homelinux.org/eric"),
+            ),
+            ExternalReference(
+                reference_type=ExternalReferenceType.WEBSITE,
+                url=XsUri("https://eric-ide.python-projects.org"),
+            ),
+        ]
+    )
     bomMetaData.tools.add(EricTool)
-    
+
     # add the meta data info entered by the user (if any)
     if metadataDict is not None:
         if metadataDict["AuthorName"]:
-            bomMetaData.authors = [OrganizationalContact(
-                name=metadataDict["AuthorName"],
-                email=metadataDict["AuthorEmail"]
-            )]
+            bomMetaData.authors = [
+                OrganizationalContact(
+                    name=metadataDict["AuthorName"], email=metadataDict["AuthorEmail"]
+                )
+            ]
         if metadataDict["Manufacturer"]:
             bomMetaData.manufacture = OrganizationalEntity(
                 name=metadataDict["Manufacturer"]
             )
         if metadataDict["Supplier"]:
-            bomMetaData.supplier = OrganizationalEntity(
-                name=metadataDict["Supplier"])
+            bomMetaData.supplier = OrganizationalEntity(name=metadataDict["Supplier"])
         if metadataDict["License"]:
-            bomMetaData.licenses = [LicenseChoice(
-                license_expression=metadataDict["License"]
-            )]
+            bomMetaData.licenses = [
+                LicenseChoice(license_expression=metadataDict["License"])
+            ]
         if metadataDict["Name"]:
             bomMetaData.component = Component(
                 name=metadataDict["Name"],
@@ -356,9 +361,7 @@
                 version=metadataDict["Version"],
                 description=metadataDict["Description"],
                 author=metadataDict["AuthorName"],
-                licenses=[LicenseChoice(
-                    license_expression=metadataDict["License"]
-                )],
+                licenses=[LicenseChoice(license_expression=metadataDict["License"])],
             )
-    
+
     return bomMetaData

eric ide

mercurial