Skip to content

Commit 63def0b

Browse files
committed
chore(lint): tidy imports/types and wrap lines; finalize CLI UX
1 parent 770ece1 commit 63def0b

File tree

2 files changed

+43
-34
lines changed

2 files changed

+43
-34
lines changed

src/diff_risk_dashboard/cli.py

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
import argparse
44
import json
55
import os
6-
from typing import Dict, Iterable, List, Mapping, Tuple
6+
from collections.abc import Iterable, Mapping
7+
from typing import Any
78

89
from rich.console import Console
910
from rich.panel import Panel
1011
from rich.table import Table
1112

12-
from .report import Summary, SEVERITIES, to_markdown
13+
from .report import SEVERITIES, Summary, to_markdown
1314

14-
15-
SEV_ORDER: Tuple[str, ...] = tuple(SEVERITIES)
16-
SEV_TO_COLOR: Dict[str, str] = {
15+
SEV_ORDER: tuple[str, ...] = tuple(SEVERITIES)
16+
SEV_TO_COLOR: dict[str, str] = {
1717
"CRITICAL": "bold bright_red",
1818
"HIGH": "red3",
1919
"MEDIUM": "yellow3",
@@ -26,8 +26,10 @@ def _normalize(sev: str) -> str:
2626
return sev.strip().upper()
2727

2828

29-
def _count_by_severity_from_list(items: Iterable[Mapping[str, object]]) -> Dict[str, int]:
30-
counts: Dict[str, int] = {k: 0 for k in SEVERITIES}
29+
def _count_by_severity_from_list(
30+
items: Iterable[Mapping[str, Any]],
31+
) -> dict[str, int]:
32+
counts: dict[str, int] = {k: 0 for k in SEVERITIES}
3133
for it in items:
3234
raw = it.get("severity") or it.get("level") or ""
3335
sev = _normalize(str(raw))
@@ -37,10 +39,10 @@ def _count_by_severity_from_list(items: Iterable[Mapping[str, object]]) -> Dict[
3739

3840

3941
def _build_summary(apv_obj: object) -> Summary:
40-
# Soportar dos formas:
42+
# Soporta:
4143
# 1) {"by_severity": {"HIGH": 1, ...}}
42-
# 2) [ {"severity": "HIGH"}, ... ]
43-
counts: Dict[str, int] = {k: 0 for k in SEVERITIES}
44+
# 2) [{"severity": "HIGH"}, ...] o en "findings"/"items"
45+
counts: dict[str, int] = {k: 0 for k in SEVERITIES}
4446

4547
if isinstance(apv_obj, Mapping):
4648
bs = apv_obj.get("by_severity")
@@ -52,36 +54,34 @@ def _build_summary(apv_obj: object) -> Summary:
5254
counts[kk] += int(v) # type: ignore[arg-type]
5355
except Exception:
5456
pass
55-
# fallback: lista en "findings" / "items"
5657
items = apv_obj.get("findings") or apv_obj.get("items")
5758
if isinstance(items, list) and not any(counts.values()):
5859
counts = _count_by_severity_from_list(items) # type: ignore[arg-type]
5960
elif isinstance(apv_obj, list):
6061
counts = _count_by_severity_from_list(apv_obj) # type: ignore[arg-type]
6162

6263
total = sum(counts.values())
63-
# peor severidad
64+
6465
worst = "INFO"
6566
for sev in SEV_ORDER:
6667
if counts.get(sev, 0) > 0:
6768
worst = sev
6869
break
69-
# nivel de riesgo
70-
risk = "green"
70+
7171
if worst in ("CRITICAL", "HIGH"):
7272
risk = "red"
7373
elif worst in ("MEDIUM", "LOW"):
7474
risk = "yellow"
75+
else:
76+
risk = "green"
7577

7678
return Summary(total=total, by_severity=counts, worst=worst, risk_level=risk)
7779

7880

7981
def _load_input(s: str) -> object:
80-
# Si existe ruta -> JSON desde archivo
8182
if os.path.isfile(s):
82-
with open(s, "r", encoding="utf-8") as fh:
83+
with open(s, encoding="utf-8") as fh:
8384
return json.load(fh)
84-
# Si parece JSON inline ({ o [) -> parsear
8585
if s.lstrip().startswith("{") or s.lstrip().startswith("["):
8686
return json.loads(s)
8787
raise SystemExit(f"✗ Not found and not JSON: {s}")
@@ -90,13 +90,21 @@ def _load_input(s: str) -> object:
9090
def _render_table(summary: Summary, console: Console) -> None:
9191
if summary.total == 0:
9292
console.print(
93-
Panel.fit("✅ No findings", border_style="green", title="Diff Risk Dashboard")
93+
Panel.fit(
94+
"✅ No findings",
95+
border_style="green",
96+
title="Diff Risk Dashboard",
97+
)
9498
)
9599
return
96100

97-
title_dot = (
98-
"🔴" if summary.risk_level == "red" else "🟡" if summary.risk_level == "yellow" else "🟢"
99-
)
101+
if summary.risk_level == "red":
102+
title_dot = "🔴"
103+
elif summary.risk_level == "yellow":
104+
title_dot = "🟡"
105+
else:
106+
title_dot = "🟢"
107+
100108
table = Table(
101109
title=f"Diff Risk Dashboard {title_dot} — Worst: {summary.worst}",
102110
title_justify="center",
@@ -110,7 +118,6 @@ def _render_table(summary: Summary, console: Console) -> None:
110118
table.add_column("Bar")
111119

112120
total = max(1, summary.total)
113-
# ancho aproximado para barra proporcional
114121
bar_width = max(10, min(48, console.size.width - 60))
115122

116123
for sev in SEVERITIES:
@@ -122,7 +129,10 @@ def _render_table(summary: Summary, console: Console) -> None:
122129

123130
table.add_row("TOTAL", str(summary.total), "100%" if summary.total else "0%", "")
124131
console.print(table)
125-
console.print("Tip: usa -f md para reporte Markdown o -f json para máquinas.", style="dim")
132+
console.print(
133+
"Tip: usa -f md para reporte Markdown o -f json para máquinas.",
134+
style="dim",
135+
)
126136

127137

128138
def _render_bars(summary: Summary) -> None:
@@ -138,10 +148,9 @@ def _render_bars(summary: Summary) -> None:
138148

139149

140150
def main() -> None:
141-
p = argparse.ArgumentParser(
142-
prog="diff_risk_dashboard", description="Diff Risk Dashboard (APV JSON -> summary)"
143-
)
144-
p.add_argument("input", help="File path or inline JSON from ai-patch-verifier")
151+
desc = "Diff Risk Dashboard (APV JSON -> summary)"
152+
p = argparse.ArgumentParser(prog="diff_risk_dashboard", description=desc)
153+
p.add_argument("input", help="File path or inline JSON")
145154
p.add_argument(
146155
"-f",
147156
"--format",
@@ -151,7 +160,9 @@ def main() -> None:
151160
)
152161
p.add_argument("-o", "--output", default="-", help="Output file; '-' = stdout")
153162
p.add_argument(
154-
"--no-exit-by-risk", action="store_true", help="Do not set exit code by risk level"
163+
"--no-exit-by-risk",
164+
action="store_true",
165+
help="Do not set exit code by risk level",
155166
)
156167
args = p.parse_args()
157168

@@ -183,11 +194,10 @@ def main() -> None:
183194
elif args.format == "bar":
184195
_render_bars(summary)
185196

186-
else: # table (TTY pretty)
197+
else: # table
187198
console = Console(force_jupyter=False, force_terminal=None, soft_wrap=False)
188199
_render_table(summary, console)
189200

190-
# Exit code unless overridden
191201
if not args.no_exit_by_risk:
192202
if summary.risk_level == "red":
193203
raise SystemExit(2)

src/diff_risk_dashboard/report.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
from dataclasses import dataclass
2-
from typing import Dict, List
32

4-
SEVERITIES: List[str] = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]
3+
SEVERITIES: list[str] = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]
54

65

76
@dataclass
87
class Summary:
98
total: int
10-
by_severity: Dict[str, int]
9+
by_severity: dict[str, int]
1110
worst: str
1211
risk_level: str # "red" | "yellow" | "green"
1312

@@ -22,7 +21,7 @@ def to_markdown(s: Summary) -> str:
2221
)
2322

2423
dot = "🔴" if s.risk_level == "red" else "🟡" if s.risk_level == "yellow" else "🟢"
25-
lines = [
24+
lines: list[str] = [
2625
f"# Diff Risk Dashboard {dot} — Worst: **{s.worst}**",
2726
"",
2827
"| Severity | Count |",

0 commit comments

Comments
 (0)