Skip to content

Commit 5fee85f

Browse files
committed
fix: better methods for checking if a Component is already represented in the BOM, and the ability to get the existing instance
Signed-off-by: Paul Horton <[email protected]>
1 parent eb3a46b commit 5fee85f

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

cyclonedx/model/bom.py

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

2020
import datetime
2121
import sys
22-
from typing import List
22+
from typing import List, Union
2323
from uuid import uuid4
2424

2525
from . import HashType
@@ -187,7 +187,8 @@ def add_component(self, component: Component):
187187
Returns:
188188
None
189189
"""
190-
self._components.append(component)
190+
if not self.has_component(component=component):
191+
self._components.append(component)
191192

192193
def add_components(self, components: List[Component]):
193194
"""
@@ -211,6 +212,23 @@ def component_count(self) -> int:
211212
"""
212213
return len(self._components)
213214

215+
def get_component_by_purl(self, purl: str) -> Union[Component, None]:
216+
"""
217+
Get a Component already in the Bom by it's PURL
218+
219+
Args:
220+
purl:
221+
Package URL as a `str` to look and find `Component`
222+
223+
Returns:
224+
`Component` or `None`
225+
"""
226+
found = list(filter(lambda x: x.get_purl() == purl, self._components))
227+
if len(found) == 1:
228+
return found[0]
229+
230+
return None
231+
214232
def get_components(self) -> List[Component]:
215233
"""
216234
Get all the Components currently in this Bom.

tests/test_component.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
from packageurl import PackageURL
2424

25+
from cyclonedx.model.bom import Bom
2526
from cyclonedx.model.component import Component
2627

2728

@@ -30,6 +31,7 @@ class TestComponent(TestCase):
3031
@classmethod
3132
def setUpClass(cls) -> None:
3233
cls._component: Component = Component(name='setuptools', version='50.3.2')
34+
cls._component_2: Component = Component(name='setuptools', version='50.3.2')
3335
cls._component_with_qualifiers: Component = Component(name='setuptools', version='50.3.2',
3436
qualifiers='extension=tar.gz')
3537
cls._component_generic_file: Component = Component(
@@ -116,3 +118,23 @@ def test_from_file_with_path_for_bom(self):
116118
)
117119
self.assertEqual(c.to_package_url(), purl)
118120
self.assertEqual(len(c.get_hashes()), 1)
121+
122+
def test_has_component_1(self):
123+
bom = Bom()
124+
bom.add_component(component=TestComponent._component)
125+
bom.add_component(component=TestComponent._component_2)
126+
self.assertEqual(len(bom.get_components()), 1)
127+
self.assertTrue(bom.has_component(component=TestComponent._component_2))
128+
self.assertIsNot(TestComponent._component, TestComponent._component_2)
129+
130+
def test_get_component_by_purl_1(self):
131+
bom = Bom()
132+
bom.add_component(component=TestComponent._component)
133+
bom.add_component(component=TestComponent._component_2)
134+
self.assertEqual(len(bom.get_components()), 1)
135+
self.assertTrue(bom.has_component(component=TestComponent._component))
136+
self.assertTrue(bom.has_component(component=TestComponent._component_2))
137+
self.assertEqual(bom.get_component_by_purl(
138+
purl=TestComponent._component.get_purl()),
139+
TestComponent._component_2
140+
)

0 commit comments

Comments
 (0)