Skip to content

Commit 8ca9e10

Browse files
committed
Fix date serialization
1 parent 466ae86 commit 8ca9e10

2 files changed

Lines changed: 34 additions & 7 deletions

File tree

scripts/generate_dashboard.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def run(self: Dashboard) -> None:
139139
metric, start_t = futs[fut]
140140
try:
141141
rows, headers = fut.result()
142+
rows = self._convert_rows(rows)
142143
except Exception as exc: # pragma: no cover - passthrough
143144
raise RuntimeError(f"error in metric '{metric.slug}': {exc}") from exc
144145
logging.info(
@@ -195,17 +196,25 @@ def _fetch_rows(self: Dashboard, sql: str) -> tuple[list[tuple], list[str]]:
195196
cur.execute(sql)
196197
rows = cur.fetchall()
197198
headers = [d[0] for d in cur.description]
198-
# Convert Decimal values to plain Python types for JSON serialisation
199-
converted: list[tuple] = []
200-
for row in rows:
201-
converted.append(
202-
tuple(float(val) if isinstance(val, Decimal) else val for val in row)
203-
)
204-
rows = converted
205199
finally:
206200
self.pool.putconn(conn)
207201
return rows, headers
208202

203+
def _convert_rows(self: Dashboard, rows: list[tuple]) -> list[tuple]:
204+
"""Convert non-JSON serialisable types to basic Python types."""
205+
converted: list[tuple] = []
206+
for row in rows:
207+
new_row = []
208+
for val in row:
209+
if isinstance(val, Decimal):
210+
new_row.append(float(val))
211+
elif isinstance(val, (dt.date, dt.datetime)):
212+
new_row.append(val.isoformat())
213+
else:
214+
new_row.append(val)
215+
converted.append(tuple(new_row))
216+
return converted
217+
209218
def _update_history(self: Dashboard, slug: str, value: int) -> None:
210219
path = self.history_dir / f"{slug}.csv"
211220
is_new = not path.exists()

tests/test_dashboard.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,24 @@ def test_run_handles_decimal_results(tmp_path):
123123
assert os.path.exists(index)
124124

125125

126+
def test_run_handles_date_results(tmp_path):
127+
cfg = make_config(tmp_path)
128+
metric_dir = cfg["paths"]["metrics_dir"]
129+
with open(os.path.join(metric_dir, "date.sql"), "w", encoding="utf-8") as fh:
130+
fh.write("-- Title: D\n-- Description: d\nselect CURRENT_DATE as col;\n")
131+
dash = make_dashboard(cfg)
132+
from datetime import date
133+
134+
with patch.object(
135+
dash,
136+
"_fetch_rows",
137+
return_value=([(date.today(), 1)], ["col", "num"]),
138+
):
139+
dash.run()
140+
index = os.path.join(cfg["paths"]["output_dir"], "index.html")
141+
assert os.path.exists(index)
142+
143+
126144
def test_metrics_sorted_zero_last(tmp_path):
127145
cfg = make_config(tmp_path)
128146
metric_dir = cfg["paths"]["metrics_dir"]

0 commit comments

Comments
 (0)