| 159 | @dataclasses.dataclass(eq=True) |
| 160 | @functools.total_ordering |
| 161 | class ReferenceV2: |
| 162 | reference_id: str = "" |
| 163 | reference_type: str = "" |
| 164 | url: str = "" |
| 165 | |
| 166 | def __post_init__(self): |
| 167 | if not self.url: |
| 168 | raise TypeError("Reference must have a url") |
| 169 | if self.reference_id and not isinstance(self.reference_id, str): |
| 170 | self.reference_id = str(self.reference_id) |
| 171 | |
| 172 | def __lt__(self, other): |
| 173 | if not isinstance(other, ReferenceV2): |
| 174 | return NotImplemented |
| 175 | return self._cmp_key() < other._cmp_key() |
| 176 | |
| 177 | # TODO: Add cache |
| 178 | def _cmp_key(self): |
| 179 | return (self.reference_id, self.reference_type, self.url) |
| 180 | |
| 181 | def to_dict(self): |
| 182 | """Return a normalized dictionary representation""" |
| 183 | return { |
| 184 | "reference_id": self.reference_id, |
| 185 | "reference_type": self.reference_type, |
| 186 | "url": self.url, |
| 187 | } |
| 188 | |
| 189 | @classmethod |
| 190 | def from_dict(cls, ref: dict): |
| 191 | return cls( |
| 192 | reference_id=str(ref["reference_id"]), |
| 193 | reference_type=ref.get("reference_type") or "", |
| 194 | url=ref["url"], |
| 195 | ) |
| 196 | |
| 197 | @classmethod |
| 198 | def from_url(cls, url): |
| 199 | reference_id = get_reference_id(url) |
| 200 | if "GHSA-" in reference_id.upper(): |
| 201 | return cls(reference_id=reference_id, url=url) |
| 202 | if reference_id.startswith(("RHSA-", "RHEA-", "RHBA-")): |
| 203 | return cls(reference_id=reference_id, url=url) |
| 204 | if is_cve(reference_id): |
| 205 | return cls(url=url, reference_id=reference_id.upper()) |
| 206 | return cls(url=url) |
| 207 | |
| 208 | |
| 209 | @dataclasses.dataclass(eq=True) |
no outgoing calls