Skip to content

Commit 20d7d4a

Browse files
committed
feat: updated model to complete support for Component #155
Signed-off-by: Paul Horton <[email protected]>
1 parent 0ce5de6 commit 20d7d4a

File tree

2 files changed

+864
-19
lines changed

2 files changed

+864
-19
lines changed

cyclonedx/model/__init__.py

+138-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
#
1515
# SPDX-License-Identifier: Apache-2.0
1616
#
17-
1817
import hashlib
1918
import re
2019
import sys
2120
import warnings
21+
from datetime import datetime
2222
from enum import Enum
2323
from typing import List, Optional, Union
2424

@@ -129,6 +129,17 @@ class Encoding(Enum):
129129
"""
130130
BASE_64 = 'base64'
131131

132+
def __eq__(self, other: object) -> bool:
133+
if isinstance(other, Encoding):
134+
return hash(other) == hash(self)
135+
return False
136+
137+
def __hash__(self) -> int:
138+
return hash(self.value)
139+
140+
def __repr__(self) -> str:
141+
return f'<Encoding name={self.name}, value={self.value}>'
142+
132143

133144
class AttachedText:
134145
"""
@@ -191,6 +202,17 @@ def content(self) -> str:
191202
def content(self, content: str) -> None:
192203
self._content = content
193204

205+
def __eq__(self, other: object) -> bool:
206+
if isinstance(other, AttachedText):
207+
return hash(other) == hash(self)
208+
return False
209+
210+
def __hash__(self) -> int:
211+
return hash((self.content, self.content_type, self.encoding))
212+
213+
def __repr__(self) -> str:
214+
return f'<AttachedText content-type={self.content_type}, encoding={self.encoding}>'
215+
194216

195217
class HashAlgorithm(Enum):
196218
"""
@@ -322,11 +344,14 @@ def __init__(self, uri: str) -> None:
322344

323345
def __eq__(self, other: object) -> bool:
324346
if isinstance(other, XsUri):
325-
return str(self) == str(other)
347+
return hash(other) == hash(self)
326348
return False
327349

350+
def __hash__(self) -> int:
351+
return hash(self._uri)
352+
328353
def __repr__(self) -> str:
329-
return self._uri
354+
return f'<XsUri uri={self._uri}>'
330355

331356

332357
class ExternalReference:
@@ -880,6 +905,116 @@ def __repr__(self) -> str:
880905
return '<Tool {}:{}:{}>'.format(self._vendor, self._name, self._version)
881906

882907

908+
class IdentifiableAction:
909+
"""
910+
This is out internal representation of the `identifiableActionType` complex type.
911+
912+
.. note::
913+
See the CycloneDX specification: https://cyclonedx.org/docs/1.4/xml/#type_identifiableActionType
914+
"""
915+
916+
def __init__(self, timestamp: Optional[datetime] = None, name: Optional[str] = None,
917+
email: Optional[str] = None) -> None:
918+
if not timestamp and not name and not email:
919+
raise NoPropertiesProvidedException(
920+
'At least one of `timestamp`, `name` or `email` must be provided for an `IdentifiableAction`.'
921+
)
922+
923+
self.timestamp = timestamp
924+
self.name = name
925+
self.email = email
926+
927+
@property
928+
def timestamp(self) -> Optional[datetime]:
929+
"""
930+
The timestamp in which the action occurred.
931+
932+
Returns:
933+
`datetime` if set else `None`
934+
"""
935+
return self._timestamp
936+
937+
@timestamp.setter
938+
def timestamp(self, timestamp: Optional[datetime]) -> None:
939+
self._timestamp = timestamp
940+
941+
@property
942+
def name(self) -> Optional[str]:
943+
"""
944+
The name of the individual who performed the action.
945+
946+
Returns:
947+
`str` if set else `None`
948+
"""
949+
return self._name
950+
951+
@name.setter
952+
def name(self, name: Optional[str]) -> None:
953+
self._name = name
954+
955+
@property
956+
def email(self) -> Optional[str]:
957+
"""
958+
The email address of the individual who performed the action.
959+
960+
Returns:
961+
`str` if set else `None`
962+
"""
963+
return self._email
964+
965+
@email.setter
966+
def email(self, email: Optional[str]) -> None:
967+
self._email = email
968+
969+
def __eq__(self, other: object) -> bool:
970+
if isinstance(other, IdentifiableAction):
971+
return hash(other) == hash(self)
972+
return False
973+
974+
def __hash__(self) -> int:
975+
return hash((hash(self.timestamp), self.name, self.email))
976+
977+
def __repr__(self) -> str:
978+
return f'<IdentifiableAction name={self.name}, email={self.email}>'
979+
980+
981+
class Copyright:
982+
"""
983+
This is out internal representation of the `copyrightsType` complex type.
984+
985+
.. note::
986+
See the CycloneDX specification: https://cyclonedx.org/docs/1.4/xml/#type_copyrightsType
987+
"""
988+
989+
def __init__(self, text: str) -> None:
990+
self.text = text
991+
992+
@property
993+
def text(self) -> str:
994+
"""
995+
Copyright statement.
996+
997+
Returns:
998+
`str` if set else `None`
999+
"""
1000+
return self._text
1001+
1002+
@text.setter
1003+
def text(self, text: str) -> None:
1004+
self._text = text
1005+
1006+
def __eq__(self, other: object) -> bool:
1007+
if isinstance(other, Copyright):
1008+
return hash(other) == hash(self)
1009+
return False
1010+
1011+
def __hash__(self) -> int:
1012+
return hash(self.text)
1013+
1014+
def __repr__(self) -> str:
1015+
return f'<Copyright text={self.text}>'
1016+
1017+
8831018
if sys.version_info >= (3, 8):
8841019
from importlib.metadata import version as meta_version
8851020
else:

0 commit comments

Comments
 (0)