diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index b778257d66..5c15c68db7 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -87,7 +87,7 @@ HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({ cv.string: cv.string, }), cv.Optional(CONF_VARIABLES): cv.Schema({ - cv.string: cv.lambda_, + cv.string: cv.returning_lambda, }), }) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 336870392d..70a6ce0c58 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -70,7 +70,7 @@ def delayed_off_filter_to_code(config, filter_id): yield var -@FILTER_REGISTRY.register('lambda', LambdaFilter, cv.lambda_) +@FILTER_REGISTRY.register('lambda', LambdaFilter, cv.returning_lambda) def lambda_filter_to_code(config, filter_id): lambda_ = yield cg.process_lambda(config, [(bool, 'x')], return_type=cg.optional.template(bool)) yield cg.new_Pvariable(filter_id, lambda_) diff --git a/esphome/components/custom/binary_sensor/__init__.py b/esphome/components/custom/binary_sensor/__init__.py index b08988cc5a..83b4a3dad8 100644 --- a/esphome/components/custom/binary_sensor/__init__.py +++ b/esphome/components/custom/binary_sensor/__init__.py @@ -8,7 +8,7 @@ CustomBinarySensorConstructor = custom_ns.class_('CustomBinarySensorConstructor' CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Required(CONF_BINARY_SENSORS): cv.ensure_list(binary_sensor.BINARY_SENSOR_SCHEMA), }) diff --git a/esphome/components/custom/output/__init__.py b/esphome/components/custom/output/__init__.py index cc4391d4ae..46abee91c8 100644 --- a/esphome/components/custom/output/__init__.py +++ b/esphome/components/custom/output/__init__.py @@ -9,7 +9,7 @@ CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor') BINARY_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Required(CONF_TYPE): 'binary', cv.Required(CONF_OUTPUTS): cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({ @@ -19,7 +19,7 @@ BINARY_SCHEMA = cv.Schema({ FLOAT_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Required(CONF_TYPE): 'float', cv.Required(CONF_OUTPUTS): cv.ensure_list(output.FLOAT_OUTPUT_SCHEMA.extend({ diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index 622d347d8a..e6da4a733c 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -8,7 +8,7 @@ CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor') CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomSensorConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA), }) diff --git a/esphome/components/custom/switch/__init__.py b/esphome/components/custom/switch/__init__.py index dc5cb325bd..fd619e6769 100644 --- a/esphome/components/custom/switch/__init__.py +++ b/esphome/components/custom/switch/__init__.py @@ -8,7 +8,7 @@ CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor') CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomSwitchConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Required(CONF_SWITCHES): cv.ensure_list(switch.SWITCH_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(switch.Switch), diff --git a/esphome/components/custom/text_sensor/__init__.py b/esphome/components/custom/text_sensor/__init__.py index 38675da142..58db2a3f9e 100644 --- a/esphome/components/custom/text_sensor/__init__.py +++ b/esphome/components/custom/text_sensor/__init__.py @@ -8,7 +8,7 @@ CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor') CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Required(CONF_TEXT_SENSORS): cv.ensure_list(text_sensor.TEXT_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), diff --git a/esphome/components/custom_component/__init__.py b/esphome/components/custom_component/__init__.py index 0dcbb163c8..198aa6a9ec 100644 --- a/esphome/components/custom_component/__init__.py +++ b/esphome/components/custom_component/__init__.py @@ -8,7 +8,7 @@ CustomComponentConstructor = custom_component_ns.class_('CustomComponentConstruc MULTI_CONF = True CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CustomComponentConstructor), - cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Required(CONF_LAMBDA): cv.returning_lambda, cv.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({ cv.GenerateID(): cv.declare_id(cg.Component) }).extend(cv.COMPONENT_SCHEMA)), diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 0fe0fc6bca..43f0cefd56 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -148,7 +148,7 @@ def exponential_moving_average_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config[CONF_ALPHA], config[CONF_SEND_EVERY]) -@FILTER_REGISTRY.register('lambda', LambdaFilter, cv.lambda_) +@FILTER_REGISTRY.register('lambda', LambdaFilter, cv.returning_lambda) def lambda_filter_to_code(config, filter_id): lambda_ = yield cg.process_lambda(config, [(float, 'x')], return_type=cg.optional.template(float)) diff --git a/esphome/components/template/binary_sensor/__init__.py b/esphome/components/template/binary_sensor/__init__.py index 9c1fb549e6..14f9f23ec2 100644 --- a/esphome/components/template/binary_sensor/__init__.py +++ b/esphome/components/template/binary_sensor/__init__.py @@ -10,7 +10,7 @@ TemplateBinarySensor = template_ns.class_('TemplateBinarySensor', binary_sensor. CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(TemplateBinarySensor), - cv.Optional(CONF_LAMBDA): cv.lambda_, + cv.Optional(CONF_LAMBDA): cv.returning_lambda, }).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/template/cover/__init__.py b/esphome/components/template/cover/__init__.py index 0eccb9fc73..33b3b62870 100644 --- a/esphome/components/template/cover/__init__.py +++ b/esphome/components/template/cover/__init__.py @@ -18,7 +18,7 @@ RESTORE_MODES = { CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(TemplateCover), - cv.Optional(CONF_LAMBDA): cv.lambda_, + cv.Optional(CONF_LAMBDA): cv.returning_lambda, cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True), diff --git a/esphome/components/template/sensor/__init__.py b/esphome/components/template/sensor/__init__.py index 788520877a..3fc71cf9de 100644 --- a/esphome/components/template/sensor/__init__.py +++ b/esphome/components/template/sensor/__init__.py @@ -9,7 +9,7 @@ TemplateSensor = template_ns.class_('TemplateSensor', sensor.Sensor, cg.PollingC CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1).extend({ cv.GenerateID(): cv.declare_id(TemplateSensor), - cv.Optional(CONF_LAMBDA): cv.lambda_, + cv.Optional(CONF_LAMBDA): cv.returning_lambda, }).extend(cv.polling_component_schema('60s')) diff --git a/esphome/components/template/switch/__init__.py b/esphome/components/template/switch/__init__.py index ac27770d47..783f5a1922 100644 --- a/esphome/components/template/switch/__init__.py +++ b/esphome/components/template/switch/__init__.py @@ -10,7 +10,7 @@ TemplateSwitch = template_ns.class_('TemplateSwitch', switch.Switch, cg.Componen CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(TemplateSwitch), - cv.Optional(CONF_LAMBDA): cv.lambda_, + cv.Optional(CONF_LAMBDA): cv.returning_lambda, cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, cv.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(single=True), diff --git a/esphome/components/template/text_sensor/__init__.py b/esphome/components/template/text_sensor/__init__.py index 23b71a3974..dae99dc9bc 100644 --- a/esphome/components/template/text_sensor/__init__.py +++ b/esphome/components/template/text_sensor/__init__.py @@ -11,7 +11,7 @@ TemplateTextSensor = template_ns.class_('TemplateTextSensor', text_sensor.TextSe CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(TemplateTextSensor), - cv.Optional(CONF_LAMBDA): cv.lambda_, + cv.Optional(CONF_LAMBDA): cv.returning_lambda, }).extend(cv.polling_component_schema('60s')) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 56fb260679..e591a5d951 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -333,7 +333,7 @@ def templatable(other_validators): def validator(value): if isinstance(value, Lambda): - return lambda_(value) + return returning_lambda(value) if isinstance(other_validators, dict): return schema(value) return schema(value) @@ -974,6 +974,20 @@ def lambda_(value): return value +def returning_lambda(value): + """Coerce this configuration option to a lambda. + + Additionally, make sure the lambda returns something. + """ + value = lambda_(value) + if u'return' not in value.value: + raise Invalid("Lambda doesn't contain a 'return' statement, but the lambda " + "is expected to return a value. \n" + "Please make sure the lambda contains at least one " + "return statement.") + return value + + def dimensions(value): if isinstance(value, list): if len(value) != 2: