Skip to content

Commit 62ad85c

Browse files
committed
impov
Signed-off-by: Jan Kowalleck <[email protected]>
1 parent 604e278 commit 62ad85c

File tree

2 files changed

+91
-67
lines changed

2 files changed

+91
-67
lines changed

cyclonedx/model/definition.py

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import serializable
2222
from sortedcontainers import SortedSet
2323

24-
from .._internal.bom_ref import bom_ref_from_str
24+
from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str
2525
from .._internal.compare import ComparableTuple as _ComparableTuple
2626
from ..exception.model import InvalidCreIdException
2727
from ..exception.serialization import SerializationOfUnexpectedValueException
@@ -69,7 +69,7 @@ def deserialize(cls, o: Any) -> 'CreId':
6969

7070
def __eq__(self, other: Any) -> bool:
7171
if isinstance(other, CreId):
72-
return hash(other) == hash(self)
72+
return self._id == other._id
7373
return False
7474

7575
def __lt__(self, other: Any) -> bool:
@@ -105,20 +105,28 @@ def __init__(
105105
properties: Optional[Iterable[Property]] = None,
106106
external_references: Optional[Iterable[ExternalReference]] = None,
107107
) -> None:
108-
self._bom_ref = bom_ref_from_str(bom_ref)
108+
self._bom_ref = _bom_ref_from_str(bom_ref)
109109
self.identifier = identifier
110110
self.title = title
111111
self.text = text
112-
self.descriptions = descriptions or [] # type:ignore[assignment]
113-
self.open_cre = open_cre or [] # type:ignore[assignment]
114-
self.parent = bom_ref_from_str(parent)
115-
self.properties = properties or [] # type:ignore[assignment]
116-
self.external_references = external_references or [] # type:ignore[assignment]
112+
self.descriptions = descriptions or () # type:ignore[assignment]
113+
self.open_cre = open_cre or () # type:ignore[assignment]
114+
self.parent = parent
115+
self.properties = properties or () # type:ignore[assignment]
116+
self.external_references = external_references or () # type:ignore[assignment]
117117

118118
def __lt__(self, other: Any) -> bool:
119119
if isinstance(other, Requirement):
120-
return (_ComparableTuple((self.bom_ref, self.identifier))
121-
< _ComparableTuple((other.bom_ref, other.title)))
120+
# all properties are optional - so need to compare all, in hope that one is unique
121+
return _ComparableTuple((
122+
self.bom_ref, self.identifier, self.title, self.text, _ComparableTuple(self.descriptions),
123+
_ComparableTuple(self.open_cre), self.parent, _ComparableTuple(self.properties),
124+
_ComparableTuple(self.external_references)
125+
)) < _ComparableTuple((
126+
other.bom_ref, other.identifier, other.title, other.text, _ComparableTuple(other.descriptions),
127+
_ComparableTuple(other.open_cre), other.parent, _ComparableTuple(other.properties),
128+
_ComparableTuple(other.external_references)
129+
))
122130
return NotImplemented
123131

124132
def __eq__(self, other: object) -> bool:
@@ -127,14 +135,15 @@ def __eq__(self, other: object) -> bool:
127135
return False
128136

129137
def __hash__(self) -> int:
138+
# all properties are optional - so need to apply all, in hope that one is unique
130139
return hash((
131140
self.bom_ref, self.identifier, self.title, self.text, tuple(self.descriptions),
132141
tuple(self.open_cre), self.parent, tuple(self.properties), tuple(self.external_references)
133142
))
134143

135144
def __repr__(self) -> str:
136-
return f'<Requirement bom-ref={self.bom_ref}, identifier={self.identifier}, title={self.title}, ' \
137-
f'text={self.text}, parent={self.parent}>'
145+
return f'<Requirement bom-ref={self._bom_ref}, identifier={self._identifier}, title={self._title}, ' \
146+
f'text={self._text}, parent={self._parent}>'
138147

139148
@property
140149
@serializable.json_name('bom-ref')
@@ -237,7 +246,7 @@ def parent(self) -> Optional[BomRef]:
237246

238247
@parent.setter
239248
def parent(self, parent: Optional[Union[str, BomRef]]) -> None:
240-
self._parent = bom_ref_from_str(parent)
249+
self._parent = _bom_ref_from_str(parent)
241250

242251
@property
243252
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property')
@@ -288,16 +297,20 @@ def __init__(
288297
description: Optional[str] = None,
289298
requirements: Optional[Iterable[Union[str, BomRef]]] = None,
290299
) -> None:
291-
self._bom_ref = bom_ref_from_str(bom_ref)
300+
self._bom_ref = _bom_ref_from_str(bom_ref)
292301
self.identifier = identifier
293302
self.title = title
294303
self.description = description
295-
self.requirements = requirements or [] # type:ignore[assignment]
304+
self.requirements = requirements or () # type:ignore[assignment]
296305

297306
def __lt__(self, other: Any) -> bool:
298307
if isinstance(other, Level):
299-
return (_ComparableTuple((self.bom_ref, self.identifier))
300-
< _ComparableTuple((other.bom_ref, other.identifier)))
308+
# all properties are optional - so need to compare all, in hope that one is unique
309+
return _ComparableTuple((
310+
self.bom_ref, self.identifier, self.title, self.description, _ComparableTuple(self.requirements)
311+
)) < _ComparableTuple((
312+
other.bom_ref, other.identifier, other.title, other.description, _ComparableTuple(other.requirements)
313+
))
301314
return NotImplemented
302315

303316
def __eq__(self, other: object) -> bool:
@@ -306,6 +319,7 @@ def __eq__(self, other: object) -> bool:
306319
return False
307320

308321
def __hash__(self) -> int:
322+
# all properties are optional - so need to compare all, in hope that one is unique
309323
return hash((
310324
self.bom_ref, self.identifier, self.title, self.description, tuple(self.requirements)
311325
))
@@ -380,7 +394,7 @@ def requirements(self) -> 'SortedSet[BomRef]':
380394

381395
@requirements.setter
382396
def requirements(self, requirements: Iterable[Union[str, BomRef]]) -> None:
383-
self._requirements = SortedSet(map(lambda x: bom_ref_from_str(x), requirements))
397+
self._requirements = SortedSet(map(_bom_ref_from_str, requirements))
384398

385399

386400
@serializable.serializable_class
@@ -401,19 +415,27 @@ def __init__(
401415
levels: Optional[Iterable[Level]] = None,
402416
external_references: Optional[Iterable['ExternalReference']] = None
403417
) -> None:
404-
self._bom_ref = bom_ref_from_str(bom_ref)
418+
self._bom_ref = _bom_ref_from_str(bom_ref)
405419
self.name = name
406420
self.version = version
407421
self.description = description
408422
self.owner = owner
409-
self.requirements = requirements or [] # type:ignore[assignment]
410-
self.levels = levels or [] # type:ignore[assignment]
411-
self.external_references = external_references or [] # type:ignore[assignment]
423+
self.requirements = requirements or () # type:ignore[assignment]
424+
self.levels = levels or () # type:ignore[assignment]
425+
self.external_references = external_references or () # type:ignore[assignment]
412426

413427
def __lt__(self, other: Any) -> bool:
414428
if isinstance(other, Standard):
415-
return (_ComparableTuple((self.bom_ref, self.name, self.version))
416-
< _ComparableTuple((other.bom_ref, other.name, other.version)))
429+
# all properties are optional - so need to apply all, in hope that one is unique
430+
return _ComparableTuple((
431+
self.bom_ref, self.name, self.version, self.description, self.owner,
432+
_ComparableTuple(self.requirements), _ComparableTuple(self.levels),
433+
_ComparableTuple(self.external_references)
434+
)) < _ComparableTuple((
435+
self.bom_ref, self.name, self.version, self.description, self.owner,
436+
_ComparableTuple(self.requirements), _ComparableTuple(self.levels),
437+
_ComparableTuple(self.external_references)
438+
))
417439
return NotImplemented
418440

419441
def __eq__(self, other: object) -> bool:
@@ -422,8 +444,10 @@ def __eq__(self, other: object) -> bool:
422444
return False
423445

424446
def __hash__(self) -> int:
447+
# all properties are optional - so need to apply all, in hope that one is unique
425448
return hash((
426-
self.bom_ref, self.name, self.version, self.description, self.owner, tuple(self.external_references)
449+
self.bom_ref, self.name, self.version, self.description, self.owner,
450+
tuple(self.requirements), tuple(self.levels), tuple(self.external_references)
427451
))
428452

429453
def __repr__(self) -> str:
@@ -570,19 +594,19 @@ def __bool__(self) -> bool:
570594
return len(self._standards) > 0
571595

572596
def __eq__(self, other: object) -> bool:
573-
if not isinstance(other, Definitions):
574-
return False
575-
576-
return self._standards == other._standards
597+
if isinstance(other, Definitions):
598+
return hash(self) == hash(other)
599+
return False
577600

578601
def __hash__(self) -> int:
579-
return hash((tuple(self._standards)))
602+
# all properties are optional - so need to apply all, in hope that one is unique
603+
return hash(tuple(self._standards))
580604

581605
def __lt__(self, other: Any) -> bool:
582606
if isinstance(other, Definitions):
583-
return (_ComparableTuple(self._standards)
584-
< _ComparableTuple(other.standards))
607+
# all properties are optional - so need to apply all, in hope that one is unique
608+
return _ComparableTuple(self._standards) < _ComparableTuple(other._standards)
585609
return NotImplemented
586610

587611
def __repr__(self) -> str:
588-
return '<Definitions>'
612+
return f'<Definitions hash={hash(self)}>'

tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.xml.bin

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,6 @@
99
</properties>
1010
<definitions>
1111
<standards>
12-
<standard bom-ref="other-standard">
13-
<name>Other Standard</name>
14-
<version>1.0.0</version>
15-
<description>Other description</description>
16-
<owner>Other Owner</owner>
17-
<requirements>
18-
<requirement bom-ref="req-3">
19-
<identifier>REQ-3</identifier>
20-
<title>Requirement 3</title>
21-
<text>some requirement text</text>
22-
<descriptions>
23-
<description>Requirement 3 described here</description>
24-
<description>and here</description>
25-
</descriptions>
26-
<openCre>CRE:5-6</openCre>
27-
<openCre>CRE:7-8</openCre>
28-
<properties>
29-
<property name="key3">val3</property>
30-
</properties>
31-
</requirement>
32-
</requirements>
33-
<levels>
34-
<level bom-ref="lvl-3">
35-
<identifier>LVL-3</identifier>
36-
<title>Level 3</title>
37-
<description>Level 3 description</description>
38-
</level>
39-
</levels>
40-
<externalReferences>
41-
<reference type="website">
42-
<url>https://cyclonedx.org</url>
43-
</reference>
44-
</externalReferences>
45-
</standard>
4612
<standard bom-ref="some-standard">
4713
<name>Some Standard</name>
4814
<version>1.2.3</version>
@@ -99,6 +65,40 @@
9965
</reference>
10066
</externalReferences>
10167
</standard>
68+
<standard bom-ref="other-standard">
69+
<name>Other Standard</name>
70+
<version>1.0.0</version>
71+
<description>Other description</description>
72+
<owner>Other Owner</owner>
73+
<requirements>
74+
<requirement bom-ref="req-3">
75+
<identifier>REQ-3</identifier>
76+
<title>Requirement 3</title>
77+
<text>some requirement text</text>
78+
<descriptions>
79+
<description>Requirement 3 described here</description>
80+
<description>and here</description>
81+
</descriptions>
82+
<openCre>CRE:5-6</openCre>
83+
<openCre>CRE:7-8</openCre>
84+
<properties>
85+
<property name="key3">val3</property>
86+
</properties>
87+
</requirement>
88+
</requirements>
89+
<levels>
90+
<level bom-ref="lvl-3">
91+
<identifier>LVL-3</identifier>
92+
<title>Level 3</title>
93+
<description>Level 3 description</description>
94+
</level>
95+
</levels>
96+
<externalReferences>
97+
<reference type="website">
98+
<url>https://cyclonedx.org</url>
99+
</reference>
100+
</externalReferences>
101+
</standard>
102102
</standards>
103103
</definitions>
104104
</bom>

0 commit comments

Comments
 (0)