Skip to content

Commit 2551545

Browse files
authored
Merge pull request #214 from CycloneDX/feat/support-bom-dependencies-no-cast
no cast
2 parents f01665e + dec3b70 commit 2551545

File tree

3 files changed

+40
-44
lines changed

3 files changed

+40
-44
lines changed

cyclonedx/output/json.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import json
2121
from abc import abstractmethod
22-
from typing import Any, Dict, List, Optional, Union, cast
22+
from typing import Any, Dict, Iterable, List, Optional, Union
2323

2424
from ..exception.output import FormatNotSupportedException
2525
from ..model.bom import Bom
@@ -56,7 +56,8 @@ def generate(self, force_regeneration: bool = False) -> None:
5656
if self.generated and not force_regeneration:
5757
return
5858

59-
self.get_bom().validate()
59+
bom = self.get_bom()
60+
bom.validate()
6061

6162
schema_uri: Optional[str] = self._get_schema_uri()
6263
if not schema_uri:
@@ -65,32 +66,31 @@ def generate(self, force_regeneration: bool = False) -> None:
6566

6667
extras = {}
6768
if self.bom_supports_dependencies():
68-
dependencies: List[Dict[str, Union[str, List[str]]]] = []
69-
if self.get_bom().metadata.component:
70-
dependencies.append({
71-
'ref': str(cast(Component, self.get_bom().metadata.component).bom_ref),
72-
'dependsOn': [*map(str, cast(Component, self.get_bom().metadata.component).dependencies)]
73-
})
74-
for component in self.get_bom().components:
69+
dep_components: Iterable[Component] = bom.components
70+
if bom.metadata.component:
71+
dep_components = [bom.metadata.component, *dep_components]
72+
dependencies = []
73+
for component in dep_components:
7574
dependencies.append({
7675
'ref': str(component.bom_ref),
7776
'dependsOn': [*map(str, component.dependencies)]
7877
})
7978
if dependencies:
8079
extras["dependencies"] = dependencies
80+
del dep_components
8181

8282
if self.bom_supports_vulnerabilities():
8383
vulnerabilities: List[Dict[Any, Any]] = []
84-
if self.get_bom().components:
85-
for component in cast(List[Component], self.get_bom().components):
84+
if bom.components:
85+
for component in bom.components:
8686
for vulnerability in component.get_vulnerabilities():
8787
vulnerabilities.append(
8888
json.loads(json.dumps(vulnerability, cls=CycloneDxJSONEncoder))
8989
)
9090
if vulnerabilities:
9191
extras["vulnerabilities"] = vulnerabilities
9292

93-
bom_json = json.loads(json.dumps(self.get_bom(), cls=CycloneDxJSONEncoder))
93+
bom_json = json.loads(json.dumps(bom, cls=CycloneDxJSONEncoder))
9494
bom_json = json.loads(self._specialise_output_for_schema_version(bom_json=bom_json))
9595
self._json_output = json.dumps({**self._create_bom_element(), **bom_json, **extras})
9696

cyclonedx/output/xml.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# Copyright (c) OWASP Foundation. All Rights Reserved.
1919

2020
import warnings
21-
from typing import Optional, Set, cast
21+
from typing import Iterable, Optional, Set
2222
from xml.etree import ElementTree
2323

2424
from ..model import (
@@ -67,16 +67,17 @@ def generate(self, force_regeneration: bool = False) -> None:
6767
elif self.generated:
6868
return
6969

70-
self.get_bom().validate()
70+
bom = self.get_bom()
71+
bom.validate()
7172

7273
if self.bom_supports_metadata():
7374
self._add_metadata_element()
7475

75-
components_element = ElementTree.SubElement(self._root_bom_element, 'components')
76-
7776
has_vulnerabilities: bool = False
78-
if self.get_bom().components:
79-
for component in self.get_bom().components:
77+
78+
components_element = ElementTree.SubElement(self._root_bom_element, 'components')
79+
if bom.components:
80+
for component in bom.components:
8081
component_element = self._add_component_element(component=component)
8182
components_element.append(component_element)
8283
if self.bom_supports_vulnerabilities_via_extension() and component.has_vulnerabilities():
@@ -96,41 +97,35 @@ def generate(self, force_regeneration: bool = False) -> None:
9697
elif component.has_vulnerabilities():
9798
has_vulnerabilities = True
9899

99-
if self.bom_supports_services():
100-
if self.get_bom().services:
101-
services_element = ElementTree.SubElement(self._root_bom_element, 'services')
102-
for service in self.get_bom().services:
103-
services_element.append(self._add_service_element(service=service))
104-
105-
if self.bom_supports_external_references():
106-
if self.get_bom().external_references:
107-
self._add_external_references_to_element(
108-
ext_refs=self.get_bom().external_references,
109-
element=self._root_bom_element
110-
)
100+
if self.bom_supports_services() and bom.services:
101+
services_element = ElementTree.SubElement(self._root_bom_element, 'services')
102+
for service in bom.services:
103+
services_element.append(self._add_service_element(service=service))
104+
105+
if self.bom_supports_external_references() and bom.external_references:
106+
self._add_external_references_to_element(
107+
ext_refs=bom.external_references,
108+
element=self._root_bom_element
109+
)
111110

112-
if self.bom_supports_dependencies() and (self.get_bom().metadata.component or self.get_bom().components):
111+
if self.bom_supports_dependencies() and (bom.metadata.component or bom.components):
112+
dep_components: Iterable[Component] = bom.components
113+
if bom.metadata.component:
114+
dep_components = [bom.metadata.component, *dep_components]
113115
dependencies_element = ElementTree.SubElement(self._root_bom_element, 'dependencies')
114-
if self.get_bom().metadata.component:
115-
dependency_element = ElementTree.SubElement(dependencies_element, 'dependency', {
116-
'ref': str(cast(Component, self.get_bom().metadata.component).bom_ref)
117-
})
118-
for dependency in cast(Component, self.get_bom().metadata.component).dependencies:
119-
ElementTree.SubElement(dependency_element, 'dependency', {
120-
'ref': str(dependency)
121-
})
122-
for component in self.get_bom().components:
116+
for component in dep_components:
123117
dependency_element = ElementTree.SubElement(dependencies_element, 'dependency', {
124118
'ref': str(component.bom_ref)
125119
})
126120
for dependency in component.dependencies:
127121
ElementTree.SubElement(dependency_element, 'dependency', {
128122
'ref': str(dependency)
129123
})
124+
del dep_components
130125

131126
if self.bom_supports_vulnerabilities() and has_vulnerabilities:
132127
vulnerabilities_element = ElementTree.SubElement(self._root_bom_element, 'vulnerabilities')
133-
for component in self.get_bom().components:
128+
for component in bom.components:
134129
for vulnerability in component.get_vulnerabilities():
135130
vulnerabilities_element.append(
136131
self._get_vulnerability_as_xml_element_post_1_4(vulnerability=vulnerability)
@@ -147,13 +142,14 @@ def get_target_namespace(self) -> str:
147142

148143
# Builder Methods
149144
def _create_bom_element(self) -> ElementTree.Element:
145+
bom = self.get_bom()
150146
root_attributes = {
151147
'xmlns': self.get_target_namespace(),
152148
'version': '1',
153-
'serialNumber': self.get_bom().get_urn_uuid()
149+
'serialNumber': bom.get_urn_uuid()
154150
}
155151

156-
if self.bom_supports_vulnerabilities_via_extension() and self.get_bom().has_vulnerabilities():
152+
if self.bom_supports_vulnerabilities_via_extension() and bom.has_vulnerabilities():
157153
root_attributes['xmlns:v'] = Xml.VULNERABILITY_EXTENSION_NAMESPACE
158154
ElementTree.register_namespace('v', Xml.VULNERABILITY_EXTENSION_NAMESPACE)
159155

tests/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def assertValidAgainstSchema(self, bom_xml: str, schema_version: SchemaVersion)
134134
def assertEqualXml(self, a: str, b: str) -> None:
135135
diff_results = main.diff_texts(a, b, diff_options={'F': 0.5})
136136
diff_results = list(filter(lambda o: not isinstance(o, MoveNode), diff_results))
137-
self.assertEqual(len(diff_results), 0, f'There are XML differences: {diff_results}')
137+
self.assertEqual(len(diff_results), 0, f'There are XML differences: {diff_results}\n- {a}\n+ {b}')
138138

139139
def assertEqualXmlBom(self, a: str, b: str, namespace: str) -> None:
140140
"""

0 commit comments

Comments
 (0)