Warn only on corrupt reports, carry the traceback, name the file

Structural corruption at any level (containers or non-numeric leaves)
warns as malformed; a well-shaped report simply lacking DRAM/DIRAM is a
variant difference and stays at debug, so healthy builds on other
targets cannot train users to ignore the warning channel. The backstop
warning carries exc_info so a field report is actionable without -v,
and the image_size warning names its file. Tests pin each message
distinctly.
This commit is contained in:
J. Nick Koston
2026-08-23 15:49:41 -05:00
parent 7475ab8f94
commit 7595baebd2
2 changed files with 36 additions and 9 deletions
+17 -7
View File
@@ -93,9 +93,12 @@ def print_summary(size_json: Path, partitions_csv: Path | None) -> None:
# Backstop for shapes the named guards below miss; warning so a
# regression here cannot go missing indefinitely
_LOGGER.warning(
"Skipping size summary for %s: %s: %s", size_json, type(e).__name__, e
"Skipping size summary for %s: %s: %s",
size_json,
type(e).__name__,
e,
exc_info=True,
)
_LOGGER.debug("Size summary failure detail", exc_info=True)
def _print_summary(size_json: Path, partitions_csv: Path | None) -> None:
@@ -114,7 +117,7 @@ def _print_summary(size_json: Path, partitions_csv: Path | None) -> None:
if (ram := _ram_line(data, size_json)) is not None:
print(ram)
if (flash := _flash_line(data, partitions_csv)) is not None:
if (flash := _flash_line(data, size_json, partitions_csv)) is not None:
print(flash)
@@ -139,17 +142,24 @@ def _ram_line(data: dict, size_json: Path) -> str | None:
total = _dict_get(ram_region, "size")
if _is_number(used) and _is_number(total) and total > 0:
return f"RAM: {_format_bar(int(used), int(total))}"
if _present_but_not_dict(memory_types) or _present_but_not_dict(ram_region):
malformed = (
_present_but_not_dict(memory_types)
or _present_but_not_dict(ram_region)
or any(v is not None and not _is_number(v) for v in (used, total))
)
if malformed:
# A structurally corrupt report, not a variant without the region
_LOGGER.warning("Skipping RAM summary: malformed memory_types in %s", size_json)
else:
_LOGGER.warning(
# A variant may name its RAM region differently; healthy builds
# must not warn
_LOGGER.debug(
"Skipping RAM summary: no usable DRAM/DIRAM region in %s", size_json
)
return None
def _flash_line(data: dict, partitions_csv: Path | None) -> str | None:
def _flash_line(data: dict, size_json: Path, partitions_csv: Path | None) -> str | None:
"""The formatted Flash line, or None (already logged) to skip it.
Owns both sides of the bar, so nothing after a print can raise: the
@@ -157,7 +167,7 @@ def _flash_line(data: dict, partitions_csv: Path | None) -> str | None:
"""
image_size = data.get("image_size")
if not _is_number(image_size):
_LOGGER.warning("Skipping Flash summary: no usable image_size")
_LOGGER.warning("Skipping Flash summary: no usable image_size in %s", size_json)
return None
if partitions_csv is None:
_LOGGER.debug("Skipping Flash summary: no partition table given")
+19 -2
View File
@@ -213,15 +213,32 @@ def test_print_summary_nested_bad_shapes_never_raise(
caplog: pytest.LogCaptureFixture,
payload: dict,
) -> None:
"""Bad nested shapes hit the named RAM guard, not the blanket backstop."""
"""Corrupt nested shapes hit the named malformed guard, not the blanket."""
size_json = _write_size_json(tmp_path, payload)
print_summary(size_json, None)
# No half-formed bar for CI to scrape; every payload fails before printing
assert capsys.readouterr().out == ""
assert "Skipping RAM summary" in caplog.text
assert "malformed memory_types" in caplog.text
assert "Skipping size summary for" not in caplog.text
def test_print_summary_absent_region_stays_quiet(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
caplog: pytest.LogCaptureFixture,
) -> None:
"""A well-shaped report without DRAM/DIRAM is a variant difference, not
a broken artifact: debug, never a per-build warning."""
size_json = _write_size_json(tmp_path, {"memory_types": {}, "image_size": 1})
with caplog.at_level(logging.DEBUG, logger="esphome.espidf.size_summary"):
print_summary(size_json, None)
assert "RAM:" not in capsys.readouterr().out
assert "no usable DRAM/DIRAM region" in caplog.text
assert not [
r for r in caplog.records if r.levelno >= logging.WARNING and "RAM" in r.message
]
def test_print_summary_non_numeric_image_size_warns_by_name(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],