Leave a dotted key out of the runs export header

_leaves named a column for a key like `-1.0` that _dig can never read
back, so the export showed an always-empty column. Skip such a key.
This commit is contained in:
2026-09-16 16:43:52 +02:00
parent d4f0345e97
commit 02907bbe27
3 changed files with 13 additions and 1 deletions
+6
View File
@@ -441,9 +441,15 @@ def _leaves(value: Any, prefix: str = "") -> Iterator[tuple[str, Any]]:
the numbers arrive inside `final_metrics` — and a record in one cell is
not a column anybody can compare. Lists are left whole: a curve belongs in
the long table, not in a cell of this one.
A key with a dot in its own name — a frequency written `-1.0` — is left
out, and whatever sits under it with it: `_dig` cannot read such a path
back, so naming it would promise a column that is always empty.
"""
if isinstance(value, dict):
for key, inner in value.items():
if "." in str(key):
continue
yield from _leaves(inner, f"{prefix}.{key}" if prefix else str(key))
else:
yield prefix, value
+5
View File
@@ -1121,6 +1121,9 @@ def exported():
"note": "n/a",
"final_metrics": {"train_loss": acc * 2},
"test_metrics": {"known": {"perfect": 1.0}},
# Keyed by a number written with its decimal point,
# which no dotted path can address.
"spectrum": {"-1.0": acc, "0.25": {"mean": acc}},
},
created_at=made + timedelta(seconds=index),
)
@@ -1199,6 +1202,8 @@ def test_an_exported_run_row_carries_every_recorded_input(
assert rows[0]["metric.final_metrics.train_loss"] == 0.5
assert rows[0]["metric.test_metrics.known.perfect"] == 1.0
assert "metric.note" not in rows[0]
# A key holding the separator cannot be read back, so it is not a column.
assert not any(key.startswith("metric.spectrum") for key in rows[0])
named = _lines(export(format="jsonl", metrics="test_metrics.known.perfect"))
assert list(named[0])[-1] == "metric.test_metrics.known.perfect"
+2 -1
View File
@@ -134,7 +134,8 @@ the inputs that *vary* across the selection in `param.` columns (the sweep
axis) unless `?params=` names them, and the run's numbers in `metric.`
columns. Both are dotted paths into whatever a node returned, so
`?metrics=final_metrics.train_loss` selects a field of a record and the
defaults reach every number inside one. The run id is on every row of both, which is what makes an exported
defaults reach every number inside one. A key with a dot in its own name, such
as `-1.0`, cannot be addressed that way and gets no column. The run id is on every row of both, which is what makes an exported
file a join back to the run rather than a loose table.
`compare` answers in the same shape a chart widget draws, so three training