|
14 | 14 | #
|
15 | 15 | # SPDX-License-Identifier: Apache-2.0
|
16 | 16 | #
|
17 |
| - |
18 | 17 | import hashlib
|
19 | 18 | import re
|
20 | 19 | import sys
|
21 | 20 | import warnings
|
| 21 | +from datetime import datetime |
22 | 22 | from enum import Enum
|
23 | 23 | from typing import List, Optional, Union
|
24 | 24 |
|
@@ -129,6 +129,17 @@ class Encoding(Enum):
|
129 | 129 | """
|
130 | 130 | BASE_64 = 'base64'
|
131 | 131 |
|
| 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 | + |
132 | 143 |
|
133 | 144 | class AttachedText:
|
134 | 145 | """
|
@@ -191,6 +202,17 @@ def content(self) -> str:
|
191 | 202 | def content(self, content: str) -> None:
|
192 | 203 | self._content = content
|
193 | 204 |
|
| 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 | + |
194 | 216 |
|
195 | 217 | class HashAlgorithm(Enum):
|
196 | 218 | """
|
@@ -322,11 +344,14 @@ def __init__(self, uri: str) -> None:
|
322 | 344 |
|
323 | 345 | def __eq__(self, other: object) -> bool:
|
324 | 346 | if isinstance(other, XsUri):
|
325 |
| - return str(self) == str(other) |
| 347 | + return hash(other) == hash(self) |
326 | 348 | return False
|
327 | 349 |
|
| 350 | + def __hash__(self) -> int: |
| 351 | + return hash(self._uri) |
| 352 | + |
328 | 353 | def __repr__(self) -> str:
|
329 |
| - return self._uri |
| 354 | + return f'<XsUri uri={self._uri}>' |
330 | 355 |
|
331 | 356 |
|
332 | 357 | class ExternalReference:
|
@@ -880,6 +905,116 @@ def __repr__(self) -> str:
|
880 | 905 | return '<Tool {}:{}:{}>'.format(self._vendor, self._name, self._version)
|
881 | 906 |
|
882 | 907 |
|
| 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 | + |
883 | 1018 | if sys.version_info >= (3, 8):
|
884 | 1019 | from importlib.metadata import version as meta_version
|
885 | 1020 | else:
|
|
0 commit comments