Skip to content

Commit 342c4ed

Browse files
committed
fix(golden): never write Infinity or NaN into a snapshot file
Symptom: after a pull request replaced DIVIDE() with the / operator and the denominator collapsed to zero, 'semantic-diff snapshot' wrote a golden file containing '"value": -Infinity'. Python read it back without complaint, so every local check passed, but the file is not valid JSON: node, jq and any other consumer reject it. A snapshot the CI job cannot parse is worse than no snapshot, because the gate reports a tooling error instead of the regression that caused it. Root cause: json.dumps emits the non standard literals Infinity, -Infinity and NaN by default, and compute_snapshot passed the raw float through from DuckDB. Fix: non finite results are recorded as blank with an explicit reason, which the comparator already treats as a value movement, so the regression is still caught.
1 parent ca85966 commit 342c4ed

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

‎src/semantic_diff/golden.py‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,25 @@ def compute_snapshot(
125125
name, False, reason=f"SQL execution failed: {exc}", sql=translation.sql
126126
)
127127
continue
128-
value = None if raw is None else float(raw)
128+
if raw is None:
129+
snapshot.values[name] = MeasureValue(name, True, value=None, sql=translation.sql)
130+
continue
131+
value = float(raw)
132+
if not math.isfinite(value):
133+
# Infinity and NaN are not valid JSON. Writing them produced a snapshot
134+
# file that Python could read back and every other parser rejected.
135+
snapshot.values[name] = MeasureValue(
136+
name,
137+
True,
138+
value=None,
139+
reason=(
140+
f"evaluated to the non finite value {value!r}, recorded as blank so the "
141+
"snapshot stays valid JSON; the usual cause is a / operator dividing by zero"
142+
),
143+
sql=translation.sql,
144+
)
145+
log.warning("non finite measure value", extra={"measure": name, "value": str(value)})
146+
continue
129147
snapshot.values[name] = MeasureValue(name, True, value=value, sql=translation.sql)
130148
eval_seconds = time.perf_counter() - eval_start
131149

0 commit comments

Comments
 (0)