Coverage for lintro / parsers / cargo_deny / cargo_deny_issue.py: 100%
32 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Models for cargo-deny issues."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from typing import ClassVar
8from lintro.parsers.base_issue import BaseIssue
11@dataclass
12class CargoDenyIssue(BaseIssue):
13 """Represents a cargo-deny check issue.
15 cargo-deny checks for:
16 - License violations (L codes)
17 - Security advisories (A codes)
18 - Banned dependencies (B codes)
19 - Duplicate dependencies (D codes)
20 - Source violations (S codes)
22 Attributes:
23 DISPLAY_FIELD_MAP: Mapping of display field names to attribute names.
24 code: Issue code (e.g., L001, A001, B001), empty string if not present.
25 severity: Severity level (error, warning).
26 crate_name: Name of the affected crate.
27 crate_version: Version of the affected crate.
28 advisory_id: RUSTSEC advisory ID (for security advisories).
29 advisory_severity: Advisory severity (for security advisories).
30 patched_versions: List of patched versions (for security advisories).
31 """
33 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = {
34 **BaseIssue.DISPLAY_FIELD_MAP,
35 "severity": "severity",
36 "code": "code",
37 }
39 code: str = field(default="")
40 severity: str | None = field(default=None)
41 crate_name: str | None = field(default=None)
42 crate_version: str | None = field(default=None)
43 advisory_id: str | None = field(default=None)
44 advisory_severity: str | None = field(default=None)
45 patched_versions: list[str] | None = field(default=None)
47 def __post_init__(self) -> None:
48 """Initialize the message field from issue details."""
49 if not self.message:
50 self.message = self._build_message()
52 def _build_message(self) -> str:
53 """Build a formatted message from issue details.
55 Returns:
56 Formatted message string.
57 """
58 parts: list[str] = []
60 if self.crate_name:
61 crate_info = self.crate_name
62 if self.crate_version:
63 crate_info = f"{crate_info}@{self.crate_version}"
64 parts.append(f"crate {crate_info}")
66 if self.advisory_id:
67 advisory_info = self.advisory_id
68 if self.advisory_severity:
69 advisory_info = f"{advisory_info} ({self.advisory_severity})"
70 parts.append(advisory_info)
72 if self.patched_versions:
73 parts.append(f"patched in: {', '.join(self.patched_versions)}")
75 return "; ".join(parts) if parts else ""