| 50 | @dataclasses.dataclass(eq=True) |
| 51 | @functools.total_ordering |
| 52 | class VulnerabilitySeverity: |
| 53 | # FIXME: this should be named scoring_system, like in the model |
| 54 | system: ScoringSystem |
| 55 | value: str |
| 56 | scoring_elements: str = "" |
| 57 | published_at: Optional[datetime.datetime] = None |
| 58 | url: Optional[str] = None |
| 59 | |
| 60 | def __post_init__(self): |
| 61 | if not self.system: |
| 62 | raise ValueError("system is required for VulnerabilitySeverity") |
| 63 | |
| 64 | if not isinstance(self.system, ScoringSystem): |
| 65 | raise TypeError(f"system must be a ScoringSystem, got {type(self.system)!r}") |
| 66 | |
| 67 | if not isinstance(self.value, str): |
| 68 | self.value = str(self.value) |
| 69 | |
| 70 | def to_dict(self): |
| 71 | data = { |
| 72 | "system": self.system.identifier, |
| 73 | "value": self.value, |
| 74 | "scoring_elements": self.scoring_elements, |
| 75 | } |
| 76 | if self.published_at: |
| 77 | if isinstance(self.published_at, datetime.datetime): |
| 78 | data["published_at"] = self.published_at.isoformat() |
| 79 | else: |
| 80 | data["published_at"] = self.published_at |
| 81 | return data |
| 82 | |
| 83 | def __lt__(self, other): |
| 84 | if not isinstance(other, VulnerabilitySeverity): |
| 85 | return NotImplemented |
| 86 | return self._cmp_key() < other._cmp_key() |
| 87 | |
| 88 | # TODO: Add cache |
| 89 | def _cmp_key(self): |
| 90 | return (self.system.identifier, self.value, self.scoring_elements, self.published_at) |
| 91 | |
| 92 | @classmethod |
| 93 | def from_dict(cls, severity: dict): |
| 94 | """ |
| 95 | Return a VulnerabilitySeverity object from a ``severity`` mapping of |
| 96 | VulnerabilitySeverity data. |
| 97 | """ |
| 98 | return cls( |
| 99 | system=SCORING_SYSTEMS[severity["system"]], |
| 100 | value=severity["value"], |
| 101 | scoring_elements=severity.get("scoring_elements", ""), |
| 102 | published_at=severity.get("published_at"), |
| 103 | ) |
| 104 | |
| 105 | |
| 106 | @dataclasses.dataclass(eq=True) |
no outgoing calls