mirror of
https://github.com/esphome/esphome.git
synced 2026-08-24 07:06:20 +00:00
Name malformed shapes distinctly, widen the broken-table net, pin the quiet path
A structurally corrupt memory_types warns as malformed instead of posing as a variant without the region; csv.Error joins the broken-table warning arm; the blanket's visible record carries the exception type. The malformed-cell test parametrizes over blank and non-blank junk, the missing-report test pins its warning, and the quiet path asserts its debug record exists with no warning records.
This commit is contained in:
@@ -92,7 +92,9 @@ def print_summary(size_json: Path, partitions_csv: Path | None) -> None:
|
||||
except Exception as e: # noqa: BLE001 # pylint: disable=broad-exception-caught
|
||||
# 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", size_json, e)
|
||||
_LOGGER.warning(
|
||||
"Skipping size summary for %s: %s: %s", size_json, type(e).__name__, e
|
||||
)
|
||||
_LOGGER.debug("Size summary failure detail", exc_info=True)
|
||||
|
||||
|
||||
@@ -111,19 +113,24 @@ def _print_summary(size_json: Path, partitions_csv: Path | None) -> None:
|
||||
return
|
||||
|
||||
memory_types = data.get("memory_types")
|
||||
if not isinstance(memory_types, dict):
|
||||
memory_types = {}
|
||||
ram_region = memory_types.get("DRAM") or memory_types.get("DIRAM")
|
||||
if not isinstance(ram_region, dict):
|
||||
ram_region = {}
|
||||
ram_used = ram_region.get("used")
|
||||
ram_total = ram_region.get("size")
|
||||
ram_region = (
|
||||
memory_types.get("DRAM") or memory_types.get("DIRAM")
|
||||
if isinstance(memory_types, dict)
|
||||
else None
|
||||
)
|
||||
ram_used = ram_region.get("used") if isinstance(ram_region, dict) else None
|
||||
ram_total = ram_region.get("size") if isinstance(ram_region, dict) else None
|
||||
if (
|
||||
isinstance(ram_used, (int, float))
|
||||
and isinstance(ram_total, (int, float))
|
||||
and ram_total > 0
|
||||
):
|
||||
print(f"RAM: {_format_bar(int(ram_used), int(ram_total))}")
|
||||
elif (memory_types is not None and not isinstance(memory_types, dict)) or (
|
||||
ram_region is not None and not isinstance(ram_region, dict)
|
||||
):
|
||||
# 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(
|
||||
"Skipping RAM summary: no usable DRAM/DIRAM region in %s", size_json
|
||||
@@ -148,7 +155,7 @@ def _flash_line(data: dict, partitions_csv: Path | None) -> str | None:
|
||||
return None
|
||||
try:
|
||||
app_size = _find_app_partition_size(partitions_csv)
|
||||
except (ValueError, OSError) as e:
|
||||
except (ValueError, OSError, csv.Error) as e:
|
||||
# The table is there but broken/unreadable: visible, like size 0
|
||||
_LOGGER.warning("Skipping Flash summary: %s", e)
|
||||
return None
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
@@ -125,11 +126,14 @@ def test_print_summary_skips_when_diram_total_collapses(
|
||||
|
||||
|
||||
def test_print_summary_handles_missing_json(
|
||||
tmp_path: Path, capsys: pytest.CaptureFixture[str]
|
||||
tmp_path: Path,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Missing size json is non-fatal and prints nothing."""
|
||||
print_summary(tmp_path / "does_not_exist.json", partitions_csv=None)
|
||||
assert capsys.readouterr().out == ""
|
||||
assert "Skipping size summary" in caplog.text
|
||||
|
||||
|
||||
def test_print_summary_handles_no_memory_types(
|
||||
@@ -250,20 +254,22 @@ def test_print_summary_blanket_guard_catches_the_rest(
|
||||
assert "Skipping size summary for" in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cell", ["", "1.5M", "abc"], ids=["blank", "float", "junk"])
|
||||
def test_print_summary_blank_size_cell_names_the_row(
|
||||
tmp_path: Path,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
cell: str,
|
||||
) -> None:
|
||||
"""A blank size cell raises ValueError instead of parsing to 0."""
|
||||
"""An unparseable size cell raises ValueError instead of parsing to 0."""
|
||||
size_json = _write_size_json(tmp_path, _dram_size_data())
|
||||
partitions = _write_partitions(tmp_path, "")
|
||||
partitions = _write_partitions(tmp_path, cell)
|
||||
print_summary(size_json, partitions)
|
||||
out = capsys.readouterr().out
|
||||
assert "RAM:" in out and "Flash:" not in out
|
||||
# Pins the ValueError path: pre-diff, "" parsed to 0 and the size-0
|
||||
# warning fired instead
|
||||
assert "blank partition size cell" in caplog.text
|
||||
assert "Skipping Flash summary" in caplog.text
|
||||
assert "app0" in caplog.text and str(partitions) in caplog.text
|
||||
|
||||
|
||||
@@ -286,12 +292,17 @@ def test_print_summary_missing_or_appless_partitions_stay_quiet(
|
||||
"""A missing table or one without a qualifying app row is a legitimate
|
||||
layout: the Flash line drops at debug, never at warning."""
|
||||
size_json = _write_size_json(tmp_path, _dram_size_data())
|
||||
print_summary(size_json, tmp_path / "nope.csv")
|
||||
partitions = _write_partitions(tmp_path, "0x1000", ptype="data", subtype="spiffs")
|
||||
print_summary(size_json, partitions)
|
||||
with caplog.at_level(logging.DEBUG, logger="esphome.espidf.size_summary"):
|
||||
print_summary(size_json, tmp_path / "nope.csv")
|
||||
partitions = _write_partitions(
|
||||
tmp_path, "0x1000", ptype="data", subtype="spiffs"
|
||||
)
|
||||
print_summary(size_json, partitions)
|
||||
out = capsys.readouterr().out
|
||||
assert "Flash:" not in out
|
||||
assert "Skipping Flash summary" not in caplog.text
|
||||
# Quiet means debug-logged, not unlogged
|
||||
assert caplog.text.count("Skipping Flash summary: no app partition") == 2
|
||||
assert not [r for r in caplog.records if r.levelno >= logging.WARNING]
|
||||
|
||||
|
||||
def test_print_summary_corrupt_size_json_warns(
|
||||
|
||||
Reference in New Issue
Block a user