Relate a Package URL with a range of affected versions and a fixed version. The Package URL must *not* have a version. AffectedPackage must contain either ``affected_version_range`` or ``fixed_version``.
| 318 | @functools.total_ordering |
| 319 | @dataclasses.dataclass(eq=True) |
| 320 | class AffectedPackage: |
| 321 | """ |
| 322 | Relate a Package URL with a range of affected versions and a fixed version. |
| 323 | The Package URL must *not* have a version. |
| 324 | AffectedPackage must contain either ``affected_version_range`` or ``fixed_version``. |
| 325 | """ |
| 326 | |
| 327 | package: PackageURL |
| 328 | affected_version_range: Optional[VersionRange] = None |
| 329 | fixed_version: Optional[Version] = None |
| 330 | |
| 331 | def __post_init__(self): |
| 332 | if self.package.version: |
| 333 | raise ValueError(f"Affected Package URL {self.package!r} cannot have a version.") |
| 334 | |
| 335 | if not (self.affected_version_range or self.fixed_version): |
| 336 | raise ValueError( |
| 337 | f"Affected Package {self.package!r} should have either a fixed version or an " |
| 338 | "affected version range." |
| 339 | ) |
| 340 | |
| 341 | def get_fixed_purl(self): |
| 342 | """ |
| 343 | Return a Package URL corresponding to object's fixed_version |
| 344 | """ |
| 345 | if not self.fixed_version: |
| 346 | raise ValueError(f"Affected Package {self.package!r} does not have a fixed version") |
| 347 | return update_purl_version(purl=self.package, version=str(self.fixed_version)) |
| 348 | |
| 349 | def __lt__(self, other): |
| 350 | if not isinstance(other, AffectedPackage): |
| 351 | return NotImplemented |
| 352 | return self._cmp_key() < other._cmp_key() |
| 353 | |
| 354 | # TODO: Add cache |
| 355 | def _cmp_key(self): |
| 356 | return ( |
| 357 | str(self.package), |
| 358 | str(self.affected_version_range or ""), |
| 359 | str(self.fixed_version or ""), |
| 360 | ) |
| 361 | |
| 362 | @classmethod |
| 363 | def merge( |
| 364 | cls, affected_packages: Iterable |
| 365 | ) -> Tuple[PackageURL, List[VersionRange], List[Version]]: |
| 366 | """ |
| 367 | Return a tuple with all attributes of AffectedPackage as a set |
| 368 | for all values in the given iterable of AffectedPackage |
| 369 | |
| 370 | This is useful where an iterable of AffectedPackage needs to be |
| 371 | converted into one tuple of structure similar to AffectedPackage |
| 372 | but with multiple fixed_versions, ie |
| 373 | package: PackageURL |
| 374 | affected_version_range: set(VersionRange) |
| 375 | fixed_versions: set(Version) |
| 376 | """ |
| 377 | affected_packages = list(affected_packages) |
no outgoing calls