Remove optional validation when creating conditions (#60481)

This commit is contained in:
Erik Montnemery 2021-11-28 14:54:07 +01:00 committed by GitHub
parent 76b047dd12
commit caf5ee2fab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 486 additions and 580 deletions

View file

@ -104,12 +104,8 @@ async def async_get_conditions(
return conditions return conditions
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == CONDITION_TRIGGERED: if config[CONF_TYPE] == CONDITION_TRIGGERED:
state = STATE_ALARM_TRIGGERED state = STATE_ALARM_TRIGGERED
elif config[CONF_TYPE] == CONDITION_DISARMED: elif config[CONF_TYPE] == CONDITION_DISARMED:

View file

@ -714,7 +714,7 @@ async def _async_process_if(hass, name, config, p_config):
checks = [] checks = []
for if_config in if_configs: for if_config in if_configs:
try: try:
checks.append(await condition.async_from_config(hass, if_config, False)) checks.append(await condition.async_from_config(hass, if_config))
except HomeAssistantError as ex: except HomeAssistantError as ex:
LOGGER.warning("Invalid condition: %s", ex) LOGGER.warning("Invalid condition: %s", ex)
return None return None

View file

@ -264,12 +264,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Evaluate state based on configuration.""" """Evaluate state based on configuration."""
if config_validation:
config = CONDITION_SCHEMA(config)
condition_type = config[CONF_TYPE] condition_type = config[CONF_TYPE]
if condition_type in IS_ON: if condition_type in IS_ON:
stat = "on" stat = "on"
@ -282,6 +278,7 @@ def async_condition_from_config(
} }
if CONF_FOR in config: if CONF_FOR in config:
state_config[CONF_FOR] = config[CONF_FOR] state_config[CONF_FOR] = config[CONF_FOR]
state_config = cv.STATE_CONDITION_SCHEMA(state_config)
return condition.state_from_config(state_config) return condition.state_from_config(state_config)

View file

@ -70,13 +70,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_hvac_mode": if config[CONF_TYPE] == "is_hvac_mode":
attribute = const.ATTR_HVAC_MODE attribute = const.ATTR_HVAC_MODE
else: else:

View file

@ -119,13 +119,8 @@ async def async_get_condition_capabilities(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] in STATE_CONDITION_TYPES: if config[CONF_TYPE] in STATE_CONDITION_TYPES:
if config[CONF_TYPE] == "is_open": if config[CONF_TYPE] == "is_open":
state = STATE_OPEN state = STATE_OPEN

View file

@ -141,6 +141,7 @@ def async_condition_from_config(config: ConfigType) -> condition.ConditionChecke
if CONF_FOR in config: if CONF_FOR in config:
state_config[CONF_FOR] = config[CONF_FOR] state_config[CONF_FOR] = config[CONF_FOR]
state_config = cv.STATE_CONDITION_SCHEMA(state_config)
return condition.state_from_config(state_config) return condition.state_from_config(state_config)

View file

@ -55,13 +55,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
reverse = config[CONF_TYPE] == "is_not_home" reverse = config[CONF_TYPE] == "is_not_home"
@callback @callback

View file

@ -55,12 +55,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_on": if config[CONF_TYPE] == "is_on":
state = STATE_ON state = STATE_ON
else: else:

View file

@ -65,13 +65,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_mode": if config[CONF_TYPE] == "is_mode":
attribute = ATTR_MODE attribute = ATTR_MODE
else: else:

View file

@ -19,12 +19,8 @@ CONDITION_SCHEMA = toggle_entity.CONDITION_SCHEMA.extend(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> ConditionCheckerType:
"""Evaluate state based on configuration.""" """Evaluate state based on configuration."""
if config_validation:
config = CONDITION_SCHEMA(config)
return toggle_entity.async_condition_from_config(config) return toggle_entity.async_condition_from_config(config)

View file

@ -67,12 +67,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_jammed": if config[CONF_TYPE] == "is_jammed":
state = STATE_JAMMED state = STATE_JAMMED
elif config[CONF_TYPE] == "is_locking": elif config[CONF_TYPE] == "is_locking":

View file

@ -59,12 +59,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_playing": if config[CONF_TYPE] == "is_playing":
state = STATE_PLAYING state = STATE_PLAYING
elif config[CONF_TYPE] == "is_idle": elif config[CONF_TYPE] == "is_idle":

View file

@ -19,12 +19,8 @@ CONDITION_SCHEMA = toggle_entity.CONDITION_SCHEMA.extend(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> ConditionCheckerType:
"""Evaluate state based on configuration.""" """Evaluate state based on configuration."""
if config_validation:
config = CONDITION_SCHEMA(config)
return toggle_entity.async_condition_from_config(config) return toggle_entity.async_condition_from_config(config)

View file

@ -52,12 +52,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
@callback @callback
def test_is_state(hass: HomeAssistant, variables: TemplateVarsType) -> bool: def test_is_state(hass: HomeAssistant, variables: TemplateVarsType) -> bool:

View file

@ -186,12 +186,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Evaluate state based on configuration.""" """Evaluate state based on configuration."""
if config_validation:
config = CONDITION_SCHEMA(config)
numeric_state_config = { numeric_state_config = {
condition.CONF_CONDITION: "numeric_state", condition.CONF_CONDITION: "numeric_state",
condition.CONF_ENTITY_ID: config[CONF_ENTITY_ID], condition.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
@ -201,6 +197,7 @@ def async_condition_from_config(
if CONF_BELOW in config: if CONF_BELOW in config:
numeric_state_config[condition.CONF_BELOW] = config[CONF_BELOW] numeric_state_config[condition.CONF_BELOW] = config[CONF_BELOW]
numeric_state_config = cv.NUMERIC_STATE_CONDITION_SCHEMA(numeric_state_config)
return condition.async_numeric_state_from_config(numeric_state_config) return condition.async_numeric_state_from_config(numeric_state_config)

View file

@ -19,12 +19,8 @@ CONDITION_SCHEMA = toggle_entity.CONDITION_SCHEMA.extend(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> ConditionCheckerType:
"""Evaluate state based on configuration.""" """Evaluate state based on configuration."""
if config_validation:
config = CONDITION_SCHEMA(config)
return toggle_entity.async_condition_from_config(config) return toggle_entity.async_condition_from_config(config)

View file

@ -53,12 +53,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_docked": if config[CONF_TYPE] == "is_docked":
test_states = [STATE_DOCKED] test_states = [STATE_DOCKED]
else: else:

View file

@ -495,7 +495,11 @@ async def handle_test_condition(
# pylint: disable=import-outside-toplevel # pylint: disable=import-outside-toplevel
from homeassistant.helpers import condition from homeassistant.helpers import condition
check_condition = await condition.async_from_config(hass, msg["condition"]) # Do static + dynamic validation of the condition
config = cv.CONDITION_SCHEMA(msg["condition"])
config = await condition.async_validate_condition_config(hass, config)
# Test the condition
check_condition = await condition.async_from_config(hass, config)
connection.send_result( connection.send_result(
msg["id"], {"result": check_condition(hass, msg.get("variables"))} msg["id"], {"result": check_condition(hass, msg.get("variables"))}
) )

View file

@ -147,13 +147,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
condition_type = config[CONF_TYPE] condition_type = config[CONF_TYPE]
device_id = config[CONF_DEVICE_ID] device_id = config[CONF_DEVICE_ID]

View file

@ -152,7 +152,6 @@ def trace_condition_function(condition: ConditionCheckerType) -> ConditionChecke
async def async_from_config( async def async_from_config(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType | Template, config: ConfigType | Template,
config_validation: bool = True,
) -> ConditionCheckerType: ) -> ConditionCheckerType:
"""Turn a condition configuration into a method. """Turn a condition configuration into a method.
@ -181,21 +180,15 @@ async def async_from_config(
check_factory = check_factory.func check_factory = check_factory.func
if asyncio.iscoroutinefunction(check_factory): if asyncio.iscoroutinefunction(check_factory):
return cast( return cast(ConditionCheckerType, await factory(hass, config))
ConditionCheckerType, await factory(hass, config, config_validation) return cast(ConditionCheckerType, factory(config))
)
return cast(ConditionCheckerType, factory(config, config_validation))
async def async_and_from_config( async def async_and_from_config(
hass: HomeAssistant, config: ConfigType, config_validation: bool = True hass: HomeAssistant, config: ConfigType
) -> ConditionCheckerType: ) -> ConditionCheckerType:
"""Create multi condition matcher using 'AND'.""" """Create multi condition matcher using 'AND'."""
if config_validation: checks = [await async_from_config(hass, entry) for entry in config["conditions"]]
config = cv.AND_CONDITION_SCHEMA(config)
checks = [
await async_from_config(hass, entry, False) for entry in config["conditions"]
]
@trace_condition_function @trace_condition_function
def if_and_condition( def if_and_condition(
@ -223,14 +216,10 @@ async def async_and_from_config(
async def async_or_from_config( async def async_or_from_config(
hass: HomeAssistant, config: ConfigType, config_validation: bool = True hass: HomeAssistant, config: ConfigType
) -> ConditionCheckerType: ) -> ConditionCheckerType:
"""Create multi condition matcher using 'OR'.""" """Create multi condition matcher using 'OR'."""
if config_validation: checks = [await async_from_config(hass, entry) for entry in config["conditions"]]
config = cv.OR_CONDITION_SCHEMA(config)
checks = [
await async_from_config(hass, entry, False) for entry in config["conditions"]
]
@trace_condition_function @trace_condition_function
def if_or_condition( def if_or_condition(
@ -258,14 +247,10 @@ async def async_or_from_config(
async def async_not_from_config( async def async_not_from_config(
hass: HomeAssistant, config: ConfigType, config_validation: bool = True hass: HomeAssistant, config: ConfigType
) -> ConditionCheckerType: ) -> ConditionCheckerType:
"""Create multi condition matcher using 'NOT'.""" """Create multi condition matcher using 'NOT'."""
if config_validation: checks = [await async_from_config(hass, entry) for entry in config["conditions"]]
config = cv.NOT_CONDITION_SCHEMA(config)
checks = [
await async_from_config(hass, entry, False) for entry in config["conditions"]
]
@trace_condition_function @trace_condition_function
def if_not_condition( def if_not_condition(
@ -433,12 +418,8 @@ def async_numeric_state( # noqa: C901
return True return True
def async_numeric_state_from_config( def async_numeric_state_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with state based condition.""" """Wrap action method with state based condition."""
if config_validation:
config = cv.NUMERIC_STATE_CONDITION_SCHEMA(config)
entity_ids = config.get(CONF_ENTITY_ID, []) entity_ids = config.get(CONF_ENTITY_ID, [])
attribute = config.get(CONF_ATTRIBUTE) attribute = config.get(CONF_ATTRIBUTE)
below = config.get(CONF_BELOW) below = config.get(CONF_BELOW)
@ -548,12 +529,8 @@ def state(
return duration_ok return duration_ok
def state_from_config( def state_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with state based condition.""" """Wrap action method with state based condition."""
if config_validation:
config = cv.STATE_CONDITION_SCHEMA(config)
entity_ids = config.get(CONF_ENTITY_ID, []) entity_ids = config.get(CONF_ENTITY_ID, [])
req_states: str | list[str] = config.get(CONF_STATE, []) req_states: str | list[str] = config.get(CONF_STATE, [])
for_period = config.get("for") for_period = config.get("for")
@ -656,12 +633,8 @@ def sun(
return True return True
def sun_from_config( def sun_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with sun based condition.""" """Wrap action method with sun based condition."""
if config_validation:
config = cv.SUN_CONDITION_SCHEMA(config)
before = config.get("before") before = config.get("before")
after = config.get("after") after = config.get("after")
before_offset = config.get("before_offset") before_offset = config.get("before_offset")
@ -703,12 +676,8 @@ def async_template(
return result return result
def async_template_from_config( def async_template_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with state based condition.""" """Wrap action method with state based condition."""
if config_validation:
config = cv.TEMPLATE_CONDITION_SCHEMA(config)
value_template = cast(Template, config.get(CONF_VALUE_TEMPLATE)) value_template = cast(Template, config.get(CONF_VALUE_TEMPLATE))
@trace_condition_function @trace_condition_function
@ -808,12 +777,8 @@ def time(
return True return True
def time_from_config( def time_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with time based condition.""" """Wrap action method with time based condition."""
if config_validation:
config = cv.TIME_CONDITION_SCHEMA(config)
before = config.get(CONF_BEFORE) before = config.get(CONF_BEFORE)
after = config.get(CONF_AFTER) after = config.get(CONF_AFTER)
weekday = config.get(CONF_WEEKDAY) weekday = config.get(CONF_WEEKDAY)
@ -873,12 +838,8 @@ def zone(
) )
def zone_from_config( def zone_from_config(config: ConfigType) -> ConditionCheckerType:
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with zone based condition.""" """Wrap action method with zone based condition."""
if config_validation:
config = cv.ZONE_CONDITION_SCHEMA(config)
entity_ids = config.get(CONF_ENTITY_ID, []) entity_ids = config.get(CONF_ENTITY_ID, [])
zone_entity_ids = config.get(CONF_ZONE, []) zone_entity_ids = config.get(CONF_ZONE, [])
@ -915,28 +876,24 @@ def zone_from_config(
async def async_device_from_config( async def async_device_from_config(
hass: HomeAssistant, config: ConfigType, config_validation: bool = True hass: HomeAssistant, config: ConfigType
) -> ConditionCheckerType: ) -> ConditionCheckerType:
"""Test a device condition.""" """Test a device condition."""
if config_validation:
config = cv.DEVICE_CONDITION_SCHEMA(config)
platform = await async_get_device_automation_platform( platform = await async_get_device_automation_platform(
hass, config[CONF_DOMAIN], "condition" hass, config[CONF_DOMAIN], "condition"
) )
return trace_condition_function( return trace_condition_function(
cast( cast(
ConditionCheckerType, ConditionCheckerType,
platform.async_condition_from_config(config, config_validation), # type: ignore platform.async_condition_from_config(config), # type: ignore
) )
) )
async def async_trigger_from_config( async def async_trigger_from_config(
hass: HomeAssistant, config: ConfigType, config_validation: bool = True hass: HomeAssistant, config: ConfigType
) -> ConditionCheckerType: ) -> ConditionCheckerType:
"""Test a trigger condition.""" """Test a trigger condition."""
if config_validation:
config = cv.TRIGGER_CONDITION_SCHEMA(config)
trigger_id = config[CONF_ID] trigger_id = config[CONF_ID]
@trace_condition_function @trace_condition_function

View file

@ -1275,7 +1275,7 @@ class Script:
else: else:
config_cache_key = frozenset((k, str(v)) for k, v in config.items()) config_cache_key = frozenset((k, str(v)) for k, v in config.items())
if not (cond := self._config_cache.get(config_cache_key)): if not (cond := self._config_cache.get(config_cache_key)):
cond = await condition.async_from_config(self._hass, config, False) cond = await condition.async_from_config(self._hass, config)
self._config_cache[config_cache_key] = cond self._config_cache[config_cache_key] = cond
return cond return cond

View file

@ -58,12 +58,8 @@ async def async_get_conditions(
@callback @callback
def async_condition_from_config( def async_condition_from_config(config: ConfigType) -> condition.ConditionCheckerType:
config: ConfigType, config_validation: bool
) -> condition.ConditionCheckerType:
"""Create a function to test a device condition.""" """Create a function to test a device condition."""
if config_validation:
config = CONDITION_SCHEMA(config)
if config[CONF_TYPE] == "is_on": if config[CONF_TYPE] == "is_on":
state = STATE_ON state = STATE_ON
else: else:

View file

@ -552,7 +552,7 @@ async def test_failure_scenarios(hass, client, hank_binary_switch, integration):
with pytest.raises(HomeAssistantError): with pytest.raises(HomeAssistantError):
await device_condition.async_condition_from_config( await device_condition.async_condition_from_config(
{"type": "failed.test", "device_id": device.id}, False {"type": "failed.test", "device_id": device.id}
) )
with patch( with patch(

File diff suppressed because it is too large Load diff