80 """ |
80 """ |
81 from .CycloneDXConfigDialog import CycloneDXConfigDialog |
81 from .CycloneDXConfigDialog import CycloneDXConfigDialog |
82 dlg = CycloneDXConfigDialog(venvName) |
82 dlg = CycloneDXConfigDialog(venvName) |
83 if dlg.exec() == QDialog.DialogCode.Accepted: |
83 if dlg.exec() == QDialog.DialogCode.Accepted: |
84 (inputSource, inputFile, fileFormat, schemaVersion, sbomFile, |
84 (inputSource, inputFile, fileFormat, schemaVersion, sbomFile, |
85 withVulnerabilities) = dlg.getData() |
85 withVulnerabilities, withDependencies) = dlg.getData() |
86 |
86 |
87 # check error conditions first |
87 # check error conditions first |
88 if inputSource not in ("environment", "pipenv", "poetry", |
88 if inputSource not in ("environment", "pipenv", "poetry", |
89 "requirements"): |
89 "requirements"): |
90 raise RuntimeError("Unsupported input source given.") |
90 raise RuntimeError("Unsupported input source given.") |
116 parser = RequirementsFileParser(requirements_file=inputFile) |
116 parser = RequirementsFileParser(requirements_file=inputFile) |
117 |
117 |
118 if withVulnerabilities: |
118 if withVulnerabilities: |
119 addCycloneDXVulnerabilities(parser) |
119 addCycloneDXVulnerabilities(parser) |
120 |
120 |
|
121 if withDependencies: |
|
122 addCycloneDXDependencies(parser, venvName) |
|
123 |
121 if fileFormat == "XML": |
124 if fileFormat == "XML": |
122 outputFormat = OutputFormat.XML |
125 outputFormat = OutputFormat.XML |
123 elif fileFormat == "JSON": |
126 elif fileFormat == "JSON": |
124 outputFormat = OutputFormat.JSON |
127 outputFormat = OutputFormat.JSON |
125 |
128 |
189 recommendation="upgrade required", |
192 recommendation="upgrade required", |
190 source=VulnerabilitySource(name="pyup.io") |
193 source=VulnerabilitySource(name="pyup.io") |
191 )) |
194 )) |
192 |
195 |
193 |
196 |
|
197 def addCycloneDXDependencies(parser, venvName): |
|
198 """ |
|
199 Function to add dependency data to the list of created components. |
|
200 |
|
201 @param parser reference to the parser object containing the list of |
|
202 components |
|
203 @type BaseParser |
|
204 @param venvName name of the virtual environment |
|
205 @type str |
|
206 """ |
|
207 components = parser.get_components() |
|
208 |
|
209 pip = ericApp().getObject("Pip") |
|
210 dependencies = pip.getDependencyTree(venvName) |
|
211 for dependency in dependencies: |
|
212 _addCycloneDXDependency(dependency, components) |
|
213 |
|
214 |
|
215 def _addCycloneDXDependency(dependency, components): |
|
216 """ |
|
217 Function to add a dependency to the given list of components. |
|
218 |
|
219 @param dependency dependency to be added |
|
220 @type dict |
|
221 @param components list of components |
|
222 @type list of Component |
|
223 """ |
|
224 component = findCyccloneDXComponent(components, dependency["package_name"]) |
|
225 if component is not None: |
|
226 bomRefs = component.dependencies |
|
227 for dep in dependency["dependencies"]: |
|
228 depComponent = findCyccloneDXComponent( |
|
229 components, dep["package_name"]) |
|
230 if depComponent is not None: |
|
231 bomRefs.add(depComponent.bom_ref) |
|
232 # recursively add sub-dependencies |
|
233 _addCycloneDXDependency(dep, components) |
|
234 component.dependencies = bomRefs |
|
235 |
|
236 |
194 def findCyccloneDXComponent(components, name): |
237 def findCyccloneDXComponent(components, name): |
195 """ |
238 """ |
196 Function to find a component in a given list of components. |
239 Function to find a component in a given list of components. |
197 |
240 |
198 @param components list of components to scan |
241 @param components list of components to scan |