Skip to content

Commit a32e5f6

Browse files
committed
wip
Signed-off-by: Jan Kowalleck <[email protected]>
1 parent 8c14a87 commit a32e5f6

File tree

6 files changed

+124
-118
lines changed

6 files changed

+124
-118
lines changed

cyclonedx/model/bom.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
from .service import Service
4949
from .tool import Tool, ToolRepository, _ToolRepositoryHelper
5050
from .vulnerability import Vulnerability
51+
from .._internal.compare import ComparableTuple as _ComparableTuple
52+
5153

5254
if TYPE_CHECKING: # pragma: no cover
5355
from packageurl import PackageURL
@@ -293,16 +295,20 @@ def properties(self) -> 'SortedSet[Property]':
293295
def properties(self, properties: Iterable[Property]) -> None:
294296
self._properties = SortedSet(properties)
295297

298+
def __comparable_tuple(self) -> _ComparableTuple:
299+
return _ComparableTuple((
300+
_ComparableTuple(self.authors), self.component, _ComparableTuple(self.licenses), self.manufacture,
301+
_ComparableTuple(self.properties),
302+
_ComparableTuple(self.lifecycles), self.supplier, self.timestamp, self.tools, self.manufacturer
303+
))
304+
296305
def __eq__(self, other: object) -> bool:
297306
if isinstance(other, BomMetaData):
298-
return hash(other) == hash(self)
307+
return self.__comparable_tuple() == other.__comparable_tuple()
299308
return False
300309

301310
def __hash__(self) -> int:
302-
return hash((
303-
tuple(self.authors), self.component, tuple(self.licenses), self.manufacture, tuple(self.properties),
304-
tuple(self.lifecycles), self.supplier, self.timestamp, self.tools, self.manufacturer
305-
))
311+
return hash(self.__comparable_tuple())
306312

307313
def __repr__(self) -> str:
308314
return f'<BomMetaData timestamp={self.timestamp}, component={self.component}>'
@@ -722,17 +728,20 @@ def validate(self) -> bool:
722728

723729
return True
724730

731+
def __comparable_tuple(self) -> _ComparableTuple:
732+
return _ComparableTuple((
733+
self.serial_number, self.version, self.metadata, _ComparableTuple(self.components), _ComparableTuple(self.services),
734+
_ComparableTuple(self.external_references), _ComparableTuple(self.dependencies), _ComparableTuple(self.properties),
735+
_ComparableTuple(self.vulnerabilities),
736+
))
737+
725738
def __eq__(self, other: object) -> bool:
726739
if isinstance(other, Bom):
727-
return hash(other) == hash(self)
740+
return self.__comparable_tuple() == other.__comparable_tuple()
728741
return False
729742

730743
def __hash__(self) -> int:
731-
return hash((
732-
self.serial_number, self.version, self.metadata, tuple(self.components), tuple(self.services),
733-
tuple(self.external_references), tuple(self.dependencies), tuple(self.properties),
734-
tuple(self.vulnerabilities),
735-
))
744+
return hash(self.__comparable_tuple())
736745

737746
def __repr__(self) -> str:
738747
return f'<Bom uuid={self.serial_number}, hash={hash(self)}>'

cyclonedx/model/component.py

Lines changed: 50 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,23 @@ def message(self) -> Optional[str]:
171171
def message(self, message: Optional[str]) -> None:
172172
self._message = message
173173

174+
def __comparable_tuple(self) -> _ComparableTuple:
175+
return _ComparableTuple((
176+
self.uid, self.url, self.author, self.committer, self.message
177+
))
178+
174179
def __eq__(self, other: object) -> bool:
175180
if isinstance(other, Commit):
176-
return hash(other) == hash(self)
181+
return self.__comparable_tuple() == other.__comparable_tuple()
177182
return False
178183

179184
def __lt__(self, other: Any) -> bool:
180185
if isinstance(other, Commit):
181-
return _ComparableTuple((
182-
self.uid, self.url, self.author, self.committer, self.message
183-
)) < _ComparableTuple((
184-
other.uid, other.url, other.author, other.committer, other.message
185-
))
186+
return self.__comparable_tuple() < other.__comparable_tuple()
186187
return NotImplemented
187188

188189
def __hash__(self) -> int:
189-
return hash((self.uid, self.url, self.author, self.committer, self.message))
190+
return hash(self.__comparable_tuple())
190191

191192
def __repr__(self) -> str:
192193
return f'<Commit uid={self.uid}, url={self.url}, message={self.message}>'
@@ -281,13 +282,19 @@ def copyright(self) -> 'SortedSet[Copyright]':
281282
def copyright(self, copyright: Iterable[Copyright]) -> None:
282283
self._copyright = SortedSet(copyright)
283284

285+
def __comparable_tuple(self) -> _ComparableTuple:
286+
return _ComparableTuple((
287+
_ComparableTuple(self.licenses),
288+
_ComparableTuple(self.copyright),
289+
))
290+
284291
def __eq__(self, other: object) -> bool:
285292
if isinstance(other, ComponentEvidence):
286-
return hash(other) == hash(self)
293+
return self.__comparable_tuple() == other.__comparable_tuple()
287294
return False
288295

289296
def __hash__(self) -> int:
290-
return hash((tuple(self.licenses), tuple(self.copyright)))
297+
return hash(self.__comparable_tuple())
291298

292299
def __repr__(self) -> str:
293300
return f'<ComponentEvidence id={id(self)}>'
@@ -478,22 +485,23 @@ def url(self) -> Optional[XsUri]:
478485
def url(self, url: Optional[XsUri]) -> None:
479486
self._url = url
480487

488+
def __comparable_tuple(self) -> _ComparableTuple:
489+
return _ComparableTuple((
490+
self.text, self.url
491+
))
492+
481493
def __eq__(self, other: object) -> bool:
482494
if isinstance(other, Diff):
483-
return hash(other) == hash(self)
495+
return self.__comparable_tuple() == other.__comparable_tuple()
484496
return False
485497

486498
def __lt__(self, other: Any) -> bool:
487499
if isinstance(other, Diff):
488-
return _ComparableTuple((
489-
self.url, self.text
490-
)) < _ComparableTuple((
491-
other.url, other.text
492-
))
500+
return self.__comparable_tuple() < other.__comparable_tuple()
493501
return NotImplemented
494502

495503
def __hash__(self) -> int:
496-
return hash((self.text, self.url))
504+
return hash(self.__comparable_tuple())
497505

498506
def __repr__(self) -> str:
499507
return f'<Diff url={self.url}>'
@@ -580,22 +588,23 @@ def resolves(self) -> 'SortedSet[IssueType]':
580588
def resolves(self, resolves: Iterable[IssueType]) -> None:
581589
self._resolves = SortedSet(resolves)
582590

591+
def __comparable_tuple(self) -> _ComparableTuple:
592+
return _ComparableTuple((
593+
self.type, self.diff, _ComparableTuple(self.resolves)
594+
))
595+
583596
def __eq__(self, other: object) -> bool:
584597
if isinstance(other, Patch):
585-
return hash(other) == hash(self)
598+
return self.__comparable_tuple() == other.__comparable_tuple()
586599
return False
587600

588601
def __lt__(self, other: Any) -> bool:
589602
if isinstance(other, Patch):
590-
return _ComparableTuple((
591-
self.type, self.diff, _ComparableTuple(self.resolves)
592-
)) < _ComparableTuple((
593-
other.type, other.diff, _ComparableTuple(other.resolves)
594-
))
603+
return self.__comparable_tuple() < other.__comparable_tuple()
595604
return NotImplemented
596605

597606
def __hash__(self) -> int:
598-
return hash((self.type, self.diff, tuple(self.resolves)))
607+
return hash(self.__comparable_tuple())
599608

600609
def __repr__(self) -> str:
601610
return f'<Patch type={self.type}, id={id(self)}>'
@@ -1741,52 +1750,33 @@ def get_pypi_url(self) -> str:
17411750
else:
17421751
return f'https://pypi.org/project/{self.name}'
17431752

1753+
def __comparable_tuple(self) -> _ComparableTuple:
1754+
return _ComparableTuple((
1755+
self.type, self.group, self.name, self.version,
1756+
self.mime_type, self.supplier, self.author, self.publisher,
1757+
self.description, self.scope, _ComparableTuple(self.hashes),
1758+
_ComparableTuple(self.licenses), self.copyright, self.cpe,
1759+
None if self.purl is None else _ComparablePackageURL(self.purl),
1760+
self.swid, self.pedigree,
1761+
_ComparableTuple(self.external_references), _ComparableTuple(self.properties),
1762+
_ComparableTuple(self.components), self.evidence, self.release_notes, self.modified,
1763+
_ComparableTuple(self.authors), _ComparableTuple(self.omnibor_ids), self.manufacturer,
1764+
_ComparableTuple(self.swhids), self.crypto_properties, _ComparableTuple(self.tags),
1765+
))
1766+
17441767
def __eq__(self, other: object) -> bool:
17451768
if isinstance(other, Component):
1746-
return hash(other) == hash(self)
1769+
return self.__comparable_tuple() == other.__comparable_tuple()
17471770
return False
17481771

17491772
def __lt__(self, other: Any) -> bool:
17501773
if isinstance(other, Component):
1751-
return _ComparableTuple((
1752-
self.type, self.group, self.name, self.version,
1753-
self.mime_type, self.supplier, self.author, self.publisher,
1754-
self.description, self.scope, _ComparableTuple(self.hashes),
1755-
_ComparableTuple(self.licenses), self.copyright, self.cpe,
1756-
None if self.purl is None else _ComparablePackageURL(self.purl),
1757-
self.swid, self.pedigree,
1758-
_ComparableTuple(self.external_references), _ComparableTuple(self.properties),
1759-
_ComparableTuple(self.components), self.evidence, self.release_notes, self.modified,
1760-
_ComparableTuple(self.authors), _ComparableTuple(self.omnibor_ids), self.manufacturer,
1761-
_ComparableTuple(self.swhids), self.crypto_properties, _ComparableTuple(self.tags)
1762-
)) < _ComparableTuple((
1763-
other.type, other.group, other.name, other.version,
1764-
other.mime_type, other.supplier, other.author, other.publisher,
1765-
other.description, other.scope, _ComparableTuple(other.hashes),
1766-
_ComparableTuple(other.licenses), other.copyright, other.cpe,
1767-
None if other.purl is None else _ComparablePackageURL(other.purl),
1768-
other.swid, other.pedigree,
1769-
_ComparableTuple(other.external_references), _ComparableTuple(other.properties),
1770-
_ComparableTuple(other.components), other.evidence, other.release_notes, other.modified,
1771-
_ComparableTuple(other.authors), _ComparableTuple(other.omnibor_ids), other.manufacturer,
1772-
_ComparableTuple(other.swhids), other.crypto_properties, _ComparableTuple(other.tags)
1773-
))
1774+
return self.__comparable_tuple() < other.__comparable_tuple()
17741775
return NotImplemented
17751776

17761777
def __hash__(self) -> int:
1777-
return hash((
1778-
self.type, self.group, self.name, self.version,
1779-
self.mime_type, self.supplier, self.author, self.publisher,
1780-
self.description, self.scope, tuple(self.hashes),
1781-
tuple(self.licenses), self.copyright, self.cpe,
1782-
self.purl,
1783-
self.swid, self.pedigree,
1784-
tuple(self.external_references), tuple(self.properties),
1785-
tuple(self.components), self.evidence, self.release_notes, self.modified,
1786-
tuple(self.authors), tuple(self.omnibor_ids), self.manufacturer,
1787-
tuple(self.swhids), self.crypto_properties, tuple(self.tags)
1788-
))
1778+
return hash(self.__comparable_tuple())
17891779

17901780
def __repr__(self) -> str:
17911781
return f'<Component bom-ref={self.bom_ref!r}, group={self.group}, name={self.name}, ' \
1792-
f'version={self.version}, type={self.type}>'
1782+
f'version={self.version}, type={self.type}>'

cyclonedx/model/contact.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,25 +163,26 @@ def street_address(self) -> Optional[str]:
163163
def street_address(self, street_address: Optional[str]) -> None:
164164
self._street_address = street_address
165165

166+
def __comparable_tuple(self) -> _ComparableTuple:
167+
return _ComparableTuple((
168+
self.bom_ref,
169+
self.country, self.region, self.locality, self.postal_code,
170+
self.post_office_box_number,
171+
self.street_address
172+
))
173+
166174
def __eq__(self, other: object) -> bool:
167175
if isinstance(other, PostalAddress):
168-
return hash(other) == hash(self)
176+
return self.__comparable_tuple() == other.__comparable_tuple()
169177
return False
170178

171179
def __lt__(self, other: Any) -> bool:
172180
if isinstance(other, PostalAddress):
173-
return _ComparableTuple((
174-
self.bom_ref, self.country, self.region, self.locality, self.post_office_box_number, self.postal_code,
175-
self.street_address
176-
)) < _ComparableTuple((
177-
other.bom_ref, other.country, other.region, other.locality, other.post_office_box_number,
178-
other.postal_code, other.street_address
179-
))
181+
return self.__comparable_tuple() < other.__comparable_tuple()
180182
return NotImplemented
181183

182184
def __hash__(self) -> int:
183-
return hash((self.bom_ref, self.country, self.region, self.locality, self.post_office_box_number,
184-
self.postal_code, self.street_address))
185+
return hash(self.__comparable_tuple())
185186

186187
def __repr__(self) -> str:
187188
return f'<PostalAddress bom-ref={self.bom_ref}, street_address={self.street_address}, country={self.country}>'

cyclonedx/model/definition.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,26 @@ def __init__(
5353
self.owner = owner
5454
self.external_references = external_references or [] # type:ignore[assignment]
5555

56+
def __comparable_tuple(self) -> _ComparableTuple:
57+
return _ComparableTuple((
58+
self.bom_ref,
59+
self.name, self.version,
60+
self.description, self.owner,
61+
_ComparableTuple(self.external_references)
62+
))
63+
5664
def __lt__(self, other: Any) -> bool:
5765
if isinstance(other, Standard):
58-
return (_ComparableTuple((self.bom_ref, self.name, self.version))
59-
< _ComparableTuple((other.bom_ref, other.name, other.version)))
66+
return self.__comparable_tuple() < other.__comparable_tuple()
6067
return NotImplemented
6168

6269
def __eq__(self, other: object) -> bool:
6370
if isinstance(other, Standard):
64-
return hash(other) == hash(self)
71+
return self.__comparable_tuple() == other.__comparable_tuple()
6572
return False
6673

6774
def __hash__(self) -> int:
68-
return hash((
69-
self.bom_ref, self.name, self.version, self.description, self.owner, tuple(self.external_references)
70-
))
75+
return hash(self.__comparable_tuple())
7176

7277
def __repr__(self) -> str:
7378
return f'<Standard bom-ref={self.bom_ref}, name={self.name}, version={self.version}, ' \
@@ -212,20 +217,21 @@ def standards(self, standards: Iterable[Standard]) -> None:
212217
def __bool__(self) -> bool:
213218
return len(self._standards) > 0
214219

215-
def __eq__(self, other: object) -> bool:
216-
if not isinstance(other, Definitions):
217-
return False
218-
219-
return self._standards == other._standards
220+
def __comparable_tuple(self) -> _ComparableTuple:
221+
return _ComparableTuple(self._standards)
220222

221-
def __hash__(self) -> int:
222-
return hash((tuple(self._standards)))
223+
def __eq__(self, other: object) -> bool:
224+
if isinstance(other, Definitions):
225+
return self.__comparable_tuple() == other.__comparable_tuple()
226+
return False
223227

224228
def __lt__(self, other: Any) -> bool:
225229
if isinstance(other, Definitions):
226-
return (_ComparableTuple(self._standards)
227-
< _ComparableTuple(other.standards))
230+
return self.__comparable_tuple() < other.__comparable_tuple()
228231
return NotImplemented
229232

233+
def __hash__(self) -> int:
234+
return hash(self.__comparable_tuple())
235+
230236
def __repr__(self) -> str:
231237
return '<Definitions>'

cyclonedx/model/service.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -354,26 +354,26 @@ def release_notes(self) -> Optional[ReleaseNotes]:
354354
def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None:
355355
self._release_notes = release_notes
356356

357+
def __comparable_tuple(self) -> _ComparableTuple:
358+
return _ComparableTuple((
359+
self.authenticated, _ComparableTuple(self.data), self.description, _ComparableTuple(self.endpoints),
360+
_ComparableTuple(self.external_references), self.group, _ComparableTuple(self.licenses), self.name,
361+
_ComparableTuple(self.properties), self.provider, self.release_notes, _ComparableTuple(self.services), self.version,
362+
self.x_trust_boundary
363+
))
364+
357365
def __eq__(self, other: object) -> bool:
358366
if isinstance(other, Service):
359-
return hash(other) == hash(self)
367+
return self.__comparable_tuple() == other.__comparable_tuple()
360368
return False
361369

362370
def __lt__(self, other: Any) -> bool:
363371
if isinstance(other, Service):
364-
return _ComparableTuple((
365-
self.group, self.name, self.version
366-
)) < _ComparableTuple((
367-
other.group, other.name, other.version
368-
))
372+
return self.__comparable_tuple() < other.__comparable_tuple()
369373
return NotImplemented
370374

371375
def __hash__(self) -> int:
372-
return hash((
373-
self.authenticated, tuple(self.data), self.description, tuple(self.endpoints),
374-
tuple(self.external_references), self.group, tuple(self.licenses), self.name, tuple(self.properties),
375-
self.provider, self.release_notes, tuple(self.services), self.version, self.x_trust_boundary
376-
))
376+
return hash(self.__comparable_tuple())
377377

378378
def __repr__(self) -> str:
379379
return f'<Service bom-ref={self.bom_ref}, group={self.group}, name={self.name}, version={self.version}>'

0 commit comments

Comments
 (0)