From acf58111c69c0c78c67351c0ee9911d81d70c5dd Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 15 Nov 2021 13:00:46 +0100 Subject: [PATCH] Correct initial update of async_track_template_result (#59705) --- homeassistant/components/template/light.py | 18 +++--- homeassistant/helpers/event.py | 4 +- tests/components/template/test_light.py | 1 + tests/helpers/test_event.py | 67 ++++++++++++++++++++++ 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/template/light.py b/homeassistant/components/template/light.py index fce35f312f8..5d172489840 100644 --- a/homeassistant/components/template/light.py +++ b/homeassistant/components/template/light.py @@ -510,7 +510,7 @@ class LightTemplate(TemplateEntity, LightEntity): def _update_brightness(self, brightness): """Update the brightness from the template.""" try: - if brightness in ("None", ""): + if brightness in (None, "None", ""): self._brightness = None return if 0 <= int(brightness) <= 255: @@ -531,7 +531,7 @@ class LightTemplate(TemplateEntity, LightEntity): def _update_white_value(self, white_value): """Update the white value from the template.""" try: - if white_value in ("None", ""): + if white_value in (None, "None", ""): self._white_value = None return if 0 <= int(white_value) <= 255: @@ -551,7 +551,7 @@ class LightTemplate(TemplateEntity, LightEntity): @callback def _update_effect_list(self, effect_list): """Update the effect list from the template.""" - if effect_list in ("None", ""): + if effect_list in (None, "None", ""): self._effect_list = None return @@ -572,7 +572,7 @@ class LightTemplate(TemplateEntity, LightEntity): @callback def _update_effect(self, effect): """Update the effect from the template.""" - if effect in ("None", ""): + if effect in (None, "None", ""): self._effect = None return @@ -617,7 +617,7 @@ class LightTemplate(TemplateEntity, LightEntity): def _update_temperature(self, render): """Update the temperature from the template.""" try: - if render in ("None", ""): + if render in (None, "None", ""): self._temperature = None return temperature = int(render) @@ -643,7 +643,7 @@ class LightTemplate(TemplateEntity, LightEntity): """Update the hs_color from the template.""" h_str = s_str = None if isinstance(render, str): - if render in ("None", ""): + if render in (None, "None", ""): self._color = None return h_str, s_str = map( @@ -675,7 +675,7 @@ class LightTemplate(TemplateEntity, LightEntity): """Update the max mireds from the template.""" try: - if render in ("None", ""): + if render in (None, "None", ""): self._max_mireds = None return self._max_mireds = int(render) @@ -690,7 +690,7 @@ class LightTemplate(TemplateEntity, LightEntity): def _update_min_mireds(self, render): """Update the min mireds from the template.""" try: - if render in ("None", ""): + if render in (None, "None", ""): self._min_mireds = None return self._min_mireds = int(render) @@ -704,7 +704,7 @@ class LightTemplate(TemplateEntity, LightEntity): @callback def _update_supports_transition(self, render): """Update the supports transition from the template.""" - if render in ("None", ""): + if render in (None, "None", ""): self._supports_transition = False return self._supports_transition = bool(render) diff --git a/homeassistant/helpers/event.py b/homeassistant/helpers/event.py index b157840db0d..d9fdce8b1f3 100644 --- a/homeassistant/helpers/event.py +++ b/homeassistant/helpers/event.py @@ -923,8 +923,8 @@ class _TrackTemplateResultInfo: last_result = self._last_result.get(template) - # Check to see if the result has changed - if result == last_result: + # Check to see if the result has changed or is new + if result == last_result and template in self._last_result: return True if isinstance(result, TemplateError) and isinstance(last_result, TemplateError): diff --git a/tests/components/template/test_light.py b/tests/components/template/test_light.py index e0ee5422439..255cea6348f 100644 --- a/tests/components/template/test_light.py +++ b/tests/components/template/test_light.py @@ -685,6 +685,7 @@ async def test_level_action_no_template(hass, start_ha, calls): (None, {"replace4": '"{{x - 12}}"'}), (None, {"replace4": '"{{ none }}"'}), (None, {"replace4": '""'}), + (None, {"replace4": "\"{{ state_attr('light.nolight', 'brightness') }}\""}), ], ) @pytest.mark.parametrize( diff --git a/tests/helpers/test_event.py b/tests/helpers/test_event.py index 2e8f6264f1a..6d78ae089da 100644 --- a/tests/helpers/test_event.py +++ b/tests/helpers/test_event.py @@ -1022,6 +1022,73 @@ async def test_track_template_result(hass): assert len(wildercard_runs) == 4 +async def test_track_template_result_none(hass): + """Test tracking template.""" + specific_runs = [] + wildcard_runs = [] + wildercard_runs = [] + + template_condition = Template("{{state_attr('sensor.test', 'battery')}}", hass) + template_condition_var = Template( + "{{(state_attr('sensor.test', 'battery')|int) + test }}", hass + ) + + def specific_run_callback(event, updates): + track_result = updates.pop() + result = int(track_result.result) if track_result.result is not None else None + specific_runs.append(result) + + async_track_template_result( + hass, [TrackTemplate(template_condition, None)], specific_run_callback + ) + + @ha.callback + def wildcard_run_callback(event, updates): + track_result = updates.pop() + last_result = ( + int(track_result.last_result) + if track_result.last_result is not None + else None + ) + result = int(track_result.result) if track_result.result is not None else None + wildcard_runs.append((last_result, result)) + + async_track_template_result( + hass, [TrackTemplate(template_condition, None)], wildcard_run_callback + ) + + async def wildercard_run_callback(event, updates): + track_result = updates.pop() + last_result = ( + int(track_result.last_result) + if track_result.last_result is not None + else None + ) + result = int(track_result.result) if track_result.result is not None else None + wildercard_runs.append((last_result, result)) + + async_track_template_result( + hass, + [TrackTemplate(template_condition_var, {"test": 5})], + wildercard_run_callback, + ) + await hass.async_block_till_done() + + hass.states.async_set("sensor.test", "-") + await hass.async_block_till_done() + + assert specific_runs == [None] + assert wildcard_runs == [(None, None)] + assert wildercard_runs == [(None, 5)] + + hass.states.async_set("sensor.test", "-", {"battery": 5}) + await hass.async_block_till_done() + + assert specific_runs == [None, 5] + assert wildcard_runs == [(None, None), (None, 5)] + assert wildercard_runs == [(None, 5), (5, 10)] + + async def test_track_template_result_super_template(hass): """Test tracking template with super template listening to same entity.""" specific_runs = []