Skip to content

Commit be24d03

Browse files
committed
Changed: Refactors criterion plotting script for clarity
Refactors the criterion plotting script to improve readability and maintainability. It replaces the `Row` tuple with a `Row` dataclass for structured data handling and introduces `ReadmeMarkerError` for better error context when handling README markers. The script now uses named attributes, enhancing code clarity. (internal)
1 parent 732480a commit be24d03

2 files changed

Lines changed: 78 additions & 18 deletions

File tree

scripts/criterion_dim_plot.py

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,22 @@ class PlotRequest:
4343
log_y: bool
4444

4545

46-
Row = tuple[int, float, float, float, float, float, float, float, float, float]
46+
@dataclass(frozen=True, slots=True)
47+
class Row:
48+
dim: int
49+
la_time: float
50+
la_lo: float
51+
la_hi: float
52+
na_time: float
53+
na_lo: float
54+
na_hi: float
55+
fa_time: float
56+
fa_lo: float
57+
fa_hi: float
58+
59+
60+
class ReadmeMarkerError(ValueError):
61+
"""Raised when README markers are missing, duplicated, or out of order."""
4762

4863

4964
METRICS: Final[dict[str, Metric]] = {
@@ -143,8 +158,8 @@ def _write_csv(out_csv: Path, rows: list[Row]) -> None:
143158
out_csv.parent.mkdir(parents=True, exist_ok=True)
144159
with out_csv.open("w", encoding="utf-8") as f:
145160
f.write("D,la_stack,la_lo,la_hi,nalgebra,na_lo,na_hi,faer,fa_lo,fa_hi\n")
146-
for d, la, la_lo, la_hi, na, na_lo, na_hi, fa, fa_lo, fa_hi in rows:
147-
f.write(f"{d},{la},{la_lo},{la_hi},{na},{na_lo},{na_hi},{fa},{fa_lo},{fa_hi}\n")
161+
for row in rows:
162+
f.write(f"{row.dim},{row.la_time},{row.la_lo},{row.la_hi},{row.na_time},{row.na_lo},{row.na_hi},{row.fa_time},{row.fa_lo},{row.fa_hi}\n")
148163

149164

150165
def _pct_reduction(baseline: float, value: float) -> str:
@@ -161,10 +176,10 @@ def _markdown_table(rows: list[Row], stat: str) -> str:
161176
"|---:|--------------------:|--------------------:|----------------:|---------------------:|----------------:|",
162177
]
163178

164-
for d, la, _la_lo, _la_hi, na, _na_lo, _na_hi, fa, _fa_lo, _fa_hi in rows:
165-
pct_vs_na = _pct_reduction(na, la)
166-
pct_vs_fa = _pct_reduction(fa, la)
167-
lines.append(f"| {d} | {la:,.3f} | {na:,.3f} | {fa:,.3f} | {pct_vs_na} | {pct_vs_fa} |")
179+
for row in rows:
180+
pct_vs_na = _pct_reduction(row.na_time, row.la_time)
181+
pct_vs_fa = _pct_reduction(row.fa_time, row.la_time)
182+
lines.append(f"| {row.dim} | {row.la_time:,.3f} | {row.na_time:,.3f} | {row.fa_time:,.3f} | {pct_vs_na} | {pct_vs_fa} |")
168183

169184
return "\n".join(lines)
170185

@@ -181,13 +196,13 @@ def _update_readme_table(readme_path: Path, marker_begin: str, marker_end: str,
181196
end_indices = [i for i, line in enumerate(lines) if line.strip() == marker_end]
182197

183198
if len(begin_indices) != 1 or len(end_indices) != 1:
184-
raise ValueError(f"README markers not found or not unique. Expected exactly one of each:\n {marker_begin}\n {marker_end}\n")
199+
raise ReadmeMarkerError(f"README markers not found or not unique. Expected exactly one of each:\n {marker_begin}\n {marker_end}\n")
185200

186201
begin_idx = begin_indices[0]
187202
end_idx = end_indices[0]
188203
if begin_idx >= end_idx:
189204
msg = "README markers are out of order."
190-
raise ValueError(msg)
205+
raise ReadmeMarkerError(msg)
191206

192207
table_lines = [line + "\n" for line in table_md.strip("\n").splitlines()]
193208
new_lines = [
@@ -347,7 +362,20 @@ def _collect_rows(criterion_dir: Path, dims: list[int], metric: Metric, stat: st
347362
la, la_lo, la_hi = _read_estimate(la_est, stat)
348363
na, na_lo, na_hi = _read_estimate(na_est, stat)
349364
fa, fa_lo, fa_hi = _read_estimate(fa_est, stat)
350-
rows.append((d, la, la_lo, la_hi, na, na_lo, na_hi, fa, fa_lo, fa_hi))
365+
rows.append(
366+
Row(
367+
dim=d,
368+
la_time=la,
369+
la_lo=la_lo,
370+
la_hi=la_hi,
371+
na_time=na,
372+
na_lo=na_lo,
373+
na_hi=na_hi,
374+
fa_time=fa,
375+
fa_lo=fa_lo,
376+
fa_hi=fa_hi,
377+
)
378+
)
351379

352380
return (rows, skipped)
353381

@@ -431,7 +459,7 @@ def main(argv: list[str] | None = None) -> int:
431459
if rc != 0:
432460
return rc
433461

434-
dims_present = [d for (d, *_rest) in rows]
462+
dims_present = [row.dim for row in rows]
435463

436464
title = f"{metric.title}: {args.stat} time vs dimension"
437465
req = PlotRequest(

scripts/tests/test_criterion_dim_plot.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,30 @@ def test_readme_table_markers_are_stable() -> None:
1919

2020
def test_markdown_table_formats_values_and_pct() -> None:
2121
rows = [
22-
# (D, la, la_lo, la_hi, na, na_lo, na_hi, fa, fa_lo, fa_hi)
23-
(2, 50.0, 0.0, 0.0, 100.0, 0.0, 0.0, 200.0, 0.0, 0.0), # +50.0% vs na, +75.0% vs fa
24-
(64, 1_000.0, 0.0, 0.0, 900.0, 0.0, 0.0, 800.0, 0.0, 0.0), # -11.1% vs na, -25.0% vs fa
22+
criterion_dim_plot.Row(
23+
dim=2,
24+
la_time=50.0,
25+
la_lo=0.0,
26+
la_hi=0.0,
27+
na_time=100.0,
28+
na_lo=0.0,
29+
na_hi=0.0,
30+
fa_time=200.0,
31+
fa_lo=0.0,
32+
fa_hi=0.0,
33+
), # +50.0% vs na, +75.0% vs fa
34+
criterion_dim_plot.Row(
35+
dim=64,
36+
la_time=1_000.0,
37+
la_lo=0.0,
38+
la_hi=0.0,
39+
na_time=900.0,
40+
na_lo=0.0,
41+
na_hi=0.0,
42+
fa_time=800.0,
43+
fa_lo=0.0,
44+
fa_hi=0.0,
45+
), # -11.1% vs na, -25.0% vs fa
2546
]
2647

2748
table = criterion_dim_plot._markdown_table(rows, stat="median")
@@ -35,7 +56,18 @@ def test_markdown_table_formats_values_and_pct() -> None:
3556
def test_markdown_table_handles_zero_nalgebra_time() -> None:
3657
rows = [
3758
# nalgebra time of 0 indicates missing/corrupt data; ensure we don't crash.
38-
(2, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 0.0, 0.0),
59+
criterion_dim_plot.Row(
60+
dim=2,
61+
la_time=10.0,
62+
la_lo=0.0,
63+
la_hi=0.0,
64+
na_time=0.0,
65+
na_lo=0.0,
66+
na_hi=0.0,
67+
fa_time=100.0,
68+
fa_lo=0.0,
69+
fa_hi=0.0,
70+
),
3971
]
4072

4173
table = criterion_dim_plot._markdown_table(rows, stat="median")
@@ -114,7 +146,7 @@ def test_update_readme_table_errors_on_missing_markers(tmp_path: Path) -> None:
114146
readme = tmp_path / "README.md"
115147
readme.write_text("# Title\n", encoding="utf-8")
116148

117-
with pytest.raises(ValueError, match=r"README markers not found"):
149+
with pytest.raises(criterion_dim_plot.ReadmeMarkerError, match=r"README markers not found"):
118150
criterion_dim_plot._update_readme_table(
119151
readme,
120152
"<!-- BENCH_TABLE:lu_solve:median:new:BEGIN -->",
@@ -129,7 +161,7 @@ def test_update_readme_table_errors_on_out_of_order_markers(tmp_path: Path) -> N
129161
readme = tmp_path / "README.md"
130162
readme.write_text("\n".join([marker_end, marker_begin, ""]), encoding="utf-8")
131163

132-
with pytest.raises(ValueError, match=r"out of order"):
164+
with pytest.raises(criterion_dim_plot.ReadmeMarkerError, match=r"out of order"):
133165
criterion_dim_plot._update_readme_table(readme, marker_begin, marker_end, "| x |")
134166

135167

@@ -149,7 +181,7 @@ def test_update_readme_table_errors_on_non_unique_markers(tmp_path: Path) -> Non
149181
encoding="utf-8",
150182
)
151183

152-
with pytest.raises(ValueError, match=r"not found or not unique"):
184+
with pytest.raises(criterion_dim_plot.ReadmeMarkerError, match=r"not found or not unique"):
153185
criterion_dim_plot._update_readme_table(readme, marker_begin, marker_end, "| x |")
154186

155187

0 commit comments

Comments
 (0)