diff --git a/esphome/automation.py b/esphome/automation.py index a75fcf35a4..990c50b2f7 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -102,6 +102,23 @@ StatelessLambdaCondition = cg.esphome_ns.class_("StatelessLambdaCondition", Cond ForCondition = cg.esphome_ns.class_("ForCondition", Condition, cg.Component) +def use_stateless_lambda_if_applicable(id_obj, lambda_expr, stateless_class): + """Replace ID type with stateless lambda class if lambda has no capture. + + Args: + id_obj: The ID object (action_id, condition_id, or filter_id) + lambda_expr: The lambda expression object + stateless_class: The stateless class to use (StatelessLambdaAction, StatelessLambdaCondition, or StatelessLambdaFilter) + + Returns: + The original ID or a copy with type replaced to use the stateless class + """ + if lambda_expr.capture == "": + id_obj = id_obj.copy() + id_obj.type = stateless_class + return id_obj + + def validate_automation(extra_schema=None, extra_validators=None, single=False): if extra_schema is None: extra_schema = {} @@ -242,11 +259,9 @@ async def lambda_condition_to_code( args: TemplateArgsType, ) -> MockObj: lambda_ = await cg.process_lambda(config, args, return_type=bool) - # Use optimized StatelessLambdaCondition for lambdas with no capture - if lambda_.capture == "": - # Override the condition_id type to use StatelessLambdaCondition - condition_id = condition_id.copy() - condition_id.type = StatelessLambdaCondition + condition_id = use_stateless_lambda_if_applicable( + condition_id, lambda_, StatelessLambdaCondition + ) return cg.new_Pvariable(condition_id, template_arg, lambda_) @@ -413,11 +428,9 @@ async def lambda_action_to_code( args: TemplateArgsType, ) -> MockObj: lambda_ = await cg.process_lambda(config, args, return_type=cg.void) - # Use optimized StatelessLambdaAction for lambdas with no capture - if lambda_.capture == "": - # Override the action_id type to use StatelessLambdaAction - action_id = action_id.copy() - action_id.type = StatelessLambdaAction + action_id = use_stateless_lambda_if_applicable( + action_id, lambda_, StatelessLambdaAction + ) return cg.new_Pvariable(action_id, template_arg, lambda_) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 9e87adf1d1..5fb1ee6667 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -300,10 +300,9 @@ async def lambda_filter_to_code(config, filter_id): lambda_ = await cg.process_lambda( config, [(bool, "x")], return_type=cg.optional.template(bool) ) - # Use optimized StatelessLambdaFilter for lambdas with no capture - if lambda_.capture == "": - filter_id = filter_id.copy() - filter_id.type = StatelessLambdaFilter + filter_id = automation.use_stateless_lambda_if_applicable( + filter_id, lambda_, StatelessLambdaFilter + ) return cg.new_Pvariable(filter_id, lambda_) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 61c9ef5051..2ae6a7fc38 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -430,10 +430,9 @@ async def logger_log_action_to_code(config, action_id, template_arg, args): text = str(cg.statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args_))) lambda_ = await cg.process_lambda(Lambda(text), args, return_type=cg.void) - # Use optimized StatelessLambdaAction for lambdas with no capture - if lambda_.capture == "": - action_id = action_id.copy() - action_id.type = StatelessLambdaAction + action_id = automation.use_stateless_lambda_if_applicable( + action_id, lambda_, StatelessLambdaAction + ) return cg.new_Pvariable(action_id, template_arg, lambda_) @@ -459,10 +458,9 @@ async def logger_set_level_to_code(config, action_id, template_arg, args): text = str(cg.statement(logger.set_log_level(level))) lambda_ = await cg.process_lambda(Lambda(text), args, return_type=cg.void) - # Use optimized StatelessLambdaAction for lambdas with no capture - if lambda_.capture == "": - action_id = action_id.copy() - action_id.type = StatelessLambdaAction + action_id = automation.use_stateless_lambda_if_applicable( + action_id, lambda_, StatelessLambdaAction + ) return cg.new_Pvariable(action_id, template_arg, lambda_) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 41e9eb63d5..ffa33d521c 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -574,10 +574,9 @@ async def lambda_filter_to_code(config, filter_id): lambda_ = await cg.process_lambda( config, [(float, "x")], return_type=cg.optional.template(float) ) - # Use optimized StatelessLambdaFilter for lambdas with no capture - if lambda_.capture == "": - filter_id = filter_id.copy() - filter_id.type = StatelessLambdaFilter + filter_id = automation.use_stateless_lambda_if_applicable( + filter_id, lambda_, StatelessLambdaFilter + ) return cg.new_Pvariable(filter_id, lambda_) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index afd9fc1733..47259667f4 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -71,10 +71,9 @@ async def lambda_filter_to_code(config, filter_id): lambda_ = await cg.process_lambda( config, [(cg.std_string, "x")], return_type=cg.optional.template(cg.std_string) ) - # Use optimized StatelessLambdaFilter for lambdas with no capture - if lambda_.capture == "": - filter_id = filter_id.copy() - filter_id.type = StatelessLambdaFilter + filter_id = automation.use_stateless_lambda_if_applicable( + filter_id, lambda_, StatelessLambdaFilter + ) return cg.new_Pvariable(filter_id, lambda_)