[light] Keep the effect list in a flash table (#20204)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2026-10-09 15:55:09 -10:00
committed by GitHub
co-authored by pre-commit-ci-lite[bot]
parent 6b03d68fac
commit 41cc96bbb8
19 changed files with 207 additions and 80 deletions
@@ -2,6 +2,14 @@
from collections.abc import Callable
from pathlib import Path
import re
import pytest
import esphome.codegen as cg
from esphome.components import light
from esphome.components.light import types as light_types
from esphome.core import ID, EsphomeError
def test_default_flash_length_and_empty_effects_are_not_emitted(
@@ -16,4 +24,20 @@ def test_default_flash_length_and_empty_effects_are_not_emitted(
assert "bare_light->set_flash_transition_length(" not in main_cpp
assert "bare_light->add_effects(" not in main_cpp
assert "fancy_light->set_flash_transition_length(500);" in main_cpp
assert "fancy_light->add_effects({" in main_cpp
call = re.search(r"fancy_light->add_effects\((\w+), (\d+)\);", main_cpp)
assert call is not None
# The effect pointers form a flash table; they are address constants, not constexpr
assert re.search(
rf"static light::LightEffect \* const {call.group(1)}\[\] PROGMEM = \{{[^}}]+\}};",
main_cpp,
)
def test_effect_assigned_in_setup_is_rejected() -> None:
"""A pointer assigned in setup() would make the flash table need dynamic init."""
dynamic_effect = cg.Pvariable(
ID("dynamic_effect", is_declaration=True, type=light_types.LightEffect),
cg.RawExpression("make_effect()"),
)
with pytest.raises(EsphomeError, match="dynamic_effect"):
light._effects_table([dynamic_effect])