Make setup_entity work as both decorator and direct call

Address review feedback: support both @setup_entity("sensor")
decorator mode and await setup_entity(var, config, "camera")
direct-call mode to maintain backward compatibility with external
components that use the direct-call API.

Simplify esp32_camera to use the direct-call form instead of
a no-op decorated wrapper function.
This commit is contained in:
J. Nick Koston
2026-03-02 07:12:19 -10:00
parent 0f9c71714e
commit c0c02e5c57
2 changed files with 28 additions and 22 deletions
+1 -6
View File
@@ -368,16 +368,11 @@ SETTERS = {
}
@setup_entity("camera")
async def _setup_esp32_camera(var, config):
pass
async def to_code(config):
cg.add_define("USE_CAMERA")
socket.require_wake_loop_threadsafe()
var = cg.new_Pvariable(config[CONF_ID])
await _setup_esp32_camera(var, config)
await setup_entity(var, config, "camera")
await cg.register_component(var, config)
for key, setter in SETTERS.items():
+27 -16
View File
@@ -236,33 +236,44 @@ def get_base_entity_object_id(
return sanitize(snake_case(base_str))
def setup_entity(platform: str) -> Callable:
"""Decorator for component setup functions.
def setup_entity(var_or_platform, config=None, platform=None):
"""Set up entity properties — works as both decorator and direct call.
Wraps the function to:
1. Set up common entity properties (name, icon, etc.)
2. Run the wrapped function (which may call setup_device_class, etc.)
3. Finalize entity strings (pack dc/uom/icon indices into uint32_t)
Usage::
Decorator mode::
@setup_entity("sensor")
async def setup_sensor_core_(var, config):
setup_device_class(config)
setup_unit_of_measurement(config)
...
Direct call mode (for entities with no extra string properties)::
await setup_entity(var, config, "camera")
"""
if isinstance(var_or_platform, str) and config is None:
# Decorator mode: @setup_entity("sensor")
platform = var_or_platform
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
async def wrapper(var: MockObj, config: ConfigType, *args, **kwargs) -> None:
await _setup_entity_impl(var, config, platform)
await func(var, config, *args, **kwargs)
finalize_entity_strings(var, config)
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
async def wrapper(
var: MockObj, config: ConfigType, *args, **kwargs
) -> None:
await _setup_entity_impl(var, config, platform)
await func(var, config, *args, **kwargs)
finalize_entity_strings(var, config)
return wrapper
return wrapper
return decorator
return decorator
# Direct call mode: await setup_entity(var, config, "camera")
async def _do():
await _setup_entity_impl(var_or_platform, config, platform)
finalize_entity_strings(var_or_platform, config)
return _do()
async def _setup_entity_impl(var: MockObj, config: ConfigType, platform: str) -> None: