diff --git a/esphome/components/lvgl/helpers.py b/esphome/components/lvgl/helpers.py index 4e41eb900a..2cdbc722d4 100644 --- a/esphome/components/lvgl/helpers.py +++ b/esphome/components/lvgl/helpers.py @@ -16,6 +16,11 @@ def lazy_once(build: Callable[[], T]) -> Callable[[], T]: Used to defer voluptuous schema construction until first validation. Many of the lvgl schemas would otherwise be built at module-import time even for YAMLs that never reach them. + + Not thread-safe — concurrent first-callers would each run ``build``. esphome + config validation is single-threaded so this is fine in practice. If + ``build`` raises, the cache stays empty and the next call retries; there is + no negative-cache. """ cached: list[T] = [] diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index d56aefa769..20e7312b63 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -48,6 +48,7 @@ from ..defines import ( join_enums, literal, ) +from ..helpers import lazy_once from ..lv_validation import lv_int from ..lvcode import ( LvConditional, @@ -80,8 +81,11 @@ def _lazy_update_schema(widget_type: "WidgetType"): voluptuous schemas and is invoked once per WidgetType at import time. The caller (register_action) only needs a validator, so wrap the build in a closure that materialises on the first validation and caches the result. + + The ``from ..schemas import base_update_schema`` import stays inside the + closure because ``schemas`` imports ``WidgetType`` from this module — top- + level would deadlock the import. """ - from ..helpers import lazy_once def build(): from ..schemas import base_update_schema