Count a reservation against the store its own in_flash selects

This commit is contained in:
J. Nick Koston
2026-10-13 15:44:47 -10:00
parent 5893f4565d
commit f60c662a5b
3 changed files with 28 additions and 14 deletions
+15 -10
View File
@@ -52,8 +52,16 @@ def preference_words(value_bytes: int) -> int:
return (value_bytes + 3) // 4 + 1
def reserve_preferences(count: int, value_bytes: int, in_flash: bool = False) -> None:
"""Record saved values a component creates; check_preferences_fit() adds them all up."""
def reserve_preferences(
count: int, value_bytes: int, in_flash: bool | None = None
) -> None:
"""Record saved values a component creates; check_preferences_fit() adds them all up.
in_flash is the value's own storage, as passed to make_preference(); None is the two-argument
form, which follows restore_from_flash.
"""
if in_flash is None:
in_flash = CORE.config[KEY_ESP8266][CONF_RESTORE_FROM_FLASH]
reservations = CORE.data.setdefault(KEY_ESP8266, {}).setdefault(KEY_PREFERENCES, [])
reservations.extend([(preference_words(value_bytes), in_flash)] * count)
@@ -75,15 +83,12 @@ def _rtc_values_can_split(values: list[int]) -> bool:
@coroutine_with_priority(CoroPriority.FINAL)
async def check_preferences_fit() -> None:
"""Fail the build when the reserved saved values cannot fit the space preferences.cpp has."""
restore_from_flash = CORE.config[KEY_ESP8266][CONF_RESTORE_FROM_FLASH]
flash_store = preferences_flash_words(restore_from_flash)
reservations = CORE.data[KEY_ESP8266].get(KEY_PREFERENCES, [])
flash_words = sum(
w for w, in_flash in reservations if in_flash or restore_from_flash
flash_store = preferences_flash_words(
CORE.config[KEY_ESP8266][CONF_RESTORE_FROM_FLASH]
)
rtc_values = [
w for w, in_flash in reservations if not (in_flash or restore_from_flash)
]
reservations = CORE.data[KEY_ESP8266].get(KEY_PREFERENCES, [])
flash_words = sum(w for w, in_flash in reservations if in_flash)
rtc_values = [w for w, in_flash in reservations if not in_flash]
if flash_words > flash_store:
raise EsphomeError(
f"Saved values need {flash_words} words but the ESP8266 flash store has {flash_store}; "
+8 -2
View File
@@ -104,8 +104,14 @@ def is_in_flash(value: str) -> bool:
return in_flash
def reserve_preferences(count: int, value_bytes: int, in_flash: bool = False) -> None:
"""Reserve saved values from to_code so a platform with a small store can check they all fit."""
def reserve_preferences(
count: int, value_bytes: int, in_flash: bool | None = None
) -> None:
"""Reserve saved values from to_code so a platform with a small store can check they all fit.
in_flash is the value's own storage (is_in_flash(config[CONF_STORAGE])); leave it None for a
component that calls the two-argument make_preference() and takes the platform default.
"""
if CORE.is_esp8266:
from esphome.components.esp8266.const import reserve_preferences as reserve
@@ -42,14 +42,17 @@ def test_preference_words_rounds_up_and_adds_the_checksum(
# 25 words each: 3 in the 78-word region and 1 in the 32-word one
(False, False, 4, "RTC memory has 110"),
# 125 of 128 flash words
(True, False, 5, "flash store has 128"),
(False, None, 4, "RTC memory has 110"),
# an explicit RTC value stays in RTC whatever restore_from_flash says
(True, False, 4, "RTC memory has 110"),
(True, None, 5, "flash store has 128"),
(True, True, 5, "flash store has 128"),
# explicit flash values without restore_from_flash use the 64-word store
(False, True, 2, "flash store has 64"),
],
)
def test_reservations_add_up_against_the_store_they_land_in(
restore_from_flash: bool, in_flash: bool, fitting: int, match: str
restore_from_flash: bool, in_flash: bool | None, fitting: int, match: str
) -> None:
CORE.config[KEY_ESP8266]["restore_from_flash"] = restore_from_flash
reserve_preferences(fitting - 1, 94, in_flash) # one component