diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index cb4a1fbbe04..a5869915d46 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -51,6 +51,7 @@ class Script(): in self.sequence) self._async_unsub_delay_listener = None self._template_cache = {} + self._config_cache = {} @property def is_running(self) -> bool: @@ -153,9 +154,14 @@ class Script(): def _async_check_condition(self, action, variables): """Test if condition is matching.""" + config_cache_key = frozenset((k, str(v)) for k, v in action.items()) + config = self._config_cache.get(config_cache_key) + if not config: + config = condition.async_from_config(action, False) + self._config_cache[config_cache_key] = config + self.last_action = action.get(CONF_ALIAS, action[CONF_CONDITION]) - check = condition.async_from_config(action, False)( - self.hass, variables) + check = config(self.hass, variables) self._log("Test condition {}: {}".format(self.last_action, check)) return check diff --git a/tests/helpers/test_script.py b/tests/helpers/test_script.py index 9a868bd8d8a..b4febc83048 100644 --- a/tests/helpers/test_script.py +++ b/tests/helpers/test_script.py @@ -1,6 +1,7 @@ """The tests for the Script component.""" # pylint: disable=too-many-public-methods,protected-access from datetime import timedelta +from unittest import mock import unittest # Otherwise can't test just this file (import order issue) @@ -279,3 +280,62 @@ class TestScriptHelper(unittest.TestCase): script_obj.run() self.hass.block_till_done() assert len(events) == 3 + + @mock.patch('homeassistant.helpers.script.condition.async_from_config') + def test_condition_created_once(self, async_from_config): + """Test that the conditions do not get created multiple times.""" + event = 'test_event' + events = [] + + def record_event(event): + """Add recorded event to set.""" + events.append(event) + + self.hass.bus.listen(event, record_event) + + self.hass.states.set('test.entity', 'hello') + + script_obj = script.Script(self.hass, cv.SCRIPT_SCHEMA([ + {'event': event}, + { + 'condition': 'template', + 'value_template': '{{ states.test.entity.state == "hello" }}', + }, + {'event': event}, + ])) + + script_obj.run() + script_obj.run() + self.hass.block_till_done() + assert async_from_config.call_count == 1 + assert len(script_obj._config_cache) == 1 + + def test_all_conditions_cached(self): + """Test that multiple conditions get cached.""" + event = 'test_event' + events = [] + + def record_event(event): + """Add recorded event to set.""" + events.append(event) + + self.hass.bus.listen(event, record_event) + + self.hass.states.set('test.entity', 'hello') + + script_obj = script.Script(self.hass, cv.SCRIPT_SCHEMA([ + {'event': event}, + { + 'condition': 'template', + 'value_template': '{{ states.test.entity.state == "hello" }}', + }, + { + 'condition': 'template', + 'value_template': '{{ states.test.entity.state != "hello" }}', + }, + {'event': event}, + ])) + + script_obj.run() + self.hass.block_till_done() + assert len(script_obj._config_cache) == 2