mirror of
https://github.com/esphome/esphome.git
synced 2026-08-30 17:46:01 +00:00
Blanket the summary against nested shapes, reject blank size cells by name, correct the CI-effect comment
This commit is contained in:
@@ -35,7 +35,9 @@ _SIZE_SUFFIXES = {"K": 1024, "M": 1024 * 1024}
|
||||
def _parse_size(token: str) -> int:
|
||||
token = token.strip()
|
||||
if not token:
|
||||
return 0
|
||||
# A blank size cell is a malformed row; naming it beats a
|
||||
# meaningless "from 0 bytes" bar downstream
|
||||
raise ValueError("blank partition size cell")
|
||||
if token.startswith(("0x", "0X")):
|
||||
return int(token, 16)
|
||||
suffix = token[-1].upper()
|
||||
@@ -85,6 +87,15 @@ def print_summary(size_json: Path, partitions_csv: Path | None) -> None:
|
||||
Failures are non-fatal: the build has already succeeded, we just couldn't
|
||||
summarize. Logs the cause at debug level.
|
||||
"""
|
||||
try:
|
||||
_print_summary(size_json, partitions_csv)
|
||||
except Exception as e: # noqa: BLE001 # pylint: disable=broad-exception-caught
|
||||
# The named guards below cover the known shapes; this net keeps the
|
||||
# promise for the rest (nested non-dict values, non-numeric sizes)
|
||||
_LOGGER.debug("Skipping size summary: %s", e)
|
||||
|
||||
|
||||
def _print_summary(size_json: Path, partitions_csv: Path | None) -> None:
|
||||
if not size_json.is_file():
|
||||
_LOGGER.debug("Skipping size summary: %s not found", size_json)
|
||||
return
|
||||
@@ -95,8 +106,8 @@ def print_summary(size_json: Path, partitions_csv: Path | None) -> None:
|
||||
return
|
||||
|
||||
if not isinstance(data, dict):
|
||||
# Valid JSON that is not an object (truncated tool output) must
|
||||
# not raise past a build that already linked
|
||||
# Valid JSON that is not an object (a hand-edited or tool-emitted
|
||||
# array) has no .get; skip with the file named
|
||||
_LOGGER.debug("Skipping size summary: unexpected shape in %s", size_json)
|
||||
return
|
||||
|
||||
@@ -116,8 +127,10 @@ def print_summary(size_json: Path, partitions_csv: Path | None) -> None:
|
||||
_LOGGER.debug("Skipping Flash summary: %s", e)
|
||||
return
|
||||
if app_size <= 0:
|
||||
# A malformed partition row parses to 0; a 0% bar would feed CI's
|
||||
# memory-impact extraction fabricated data
|
||||
# Defensive backstop behind _parse_size's blank-cell rejection: a
|
||||
# "from 0 bytes" denominator is meaningless to a reader. Note the
|
||||
# skip costs CI's memory-impact extraction its Flash match, which
|
||||
# is the loud outcome a broken partition table deserves.
|
||||
_LOGGER.debug("Skipping Flash summary: app partition size is 0")
|
||||
return
|
||||
print(f"Flash: {_format_bar(image_size, app_size)}")
|
||||
|
||||
@@ -177,3 +177,52 @@ def test_print_summary_zero_app_partition_is_skipped(
|
||||
print_summary(size_json, partitions)
|
||||
out = capsys.readouterr().out
|
||||
assert "RAM:" in out and "Flash:" not in out
|
||||
|
||||
|
||||
def test_print_summary_happy_path_prints_both_bars(
|
||||
tmp_path: Path, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
"""A well-formed size report and partition table print both bars."""
|
||||
size_json = tmp_path / "size.json"
|
||||
size_json.write_text(
|
||||
'{"memory_types": {"DRAM": {"used": 1000, "size": 2000}}, "image_size": 100000}'
|
||||
)
|
||||
partitions = tmp_path / "partitions.csv"
|
||||
partitions.write_text("app0, app, ota_0, 0x10000, 0x180000,\n")
|
||||
print_summary(size_json, partitions)
|
||||
out = capsys.readouterr().out
|
||||
assert "RAM:" in out and "Flash:" in out
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"payload",
|
||||
[
|
||||
{"memory_types": []},
|
||||
{"memory_types": {"DRAM": 5}},
|
||||
{"memory_types": {"DRAM": {"used": "x", "size": "y"}}, "image_size": 1},
|
||||
],
|
||||
)
|
||||
def test_print_summary_nested_bad_shapes_never_raise(
|
||||
tmp_path: Path, capsys: pytest.CaptureFixture[str], payload: dict
|
||||
) -> None:
|
||||
"""The blanket guard keeps nested non-dict values and non-numeric sizes
|
||||
from raising past a linked build."""
|
||||
size_json = _write_size_json(tmp_path, payload)
|
||||
print_summary(size_json, None)
|
||||
assert "Traceback" not in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_print_summary_blank_size_cell_names_the_row(
|
||||
tmp_path: Path, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
"""A blank size cell is reported as the malformed input it is, via the
|
||||
ValueError path, instead of parsing to 0."""
|
||||
size_json = _write_size_json(
|
||||
tmp_path,
|
||||
{"memory_types": {"DRAM": {"used": 1, "size": 2}}, "image_size": 100},
|
||||
)
|
||||
partitions = tmp_path / "partitions.csv"
|
||||
partitions.write_text("app0, app, ota_0, 0x10000, ,\n")
|
||||
print_summary(size_json, partitions)
|
||||
out = capsys.readouterr().out
|
||||
assert "RAM:" in out and "Flash:" not in out
|
||||
|
||||
Reference in New Issue
Block a user