diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 36e0a597b87..8e5951488ba 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -13,7 +13,7 @@ from functools import cache, lru_cache, partial, wraps import json import logging import math -from operator import attrgetter, contains +from operator import contains import pathlib import random import re @@ -983,7 +983,7 @@ def _state_generator( hass: HomeAssistant, domain: str | None ) -> Generator[TemplateState, None, None]: """State generator for a domain or all states.""" - for state in sorted(hass.states.async_all(domain), key=attrgetter("entity_id")): + for state in hass.states.async_all(domain): yield _template_state_no_collect(hass, state) @@ -1097,7 +1097,7 @@ def expand(hass: HomeAssistant, *args: Any) -> Iterable[State]: _collect_state(hass, entity_id) found[entity_id] = entity - return sorted(found.values(), key=lambda a: a.entity_id) + return list(found.values()) def device_entities(hass: HomeAssistant, _device_id: str) -> Iterable[str]: diff --git a/tests/helpers/test_event.py b/tests/helpers/test_event.py index 7e84d634eff..a482e1b63b5 100644 --- a/tests/helpers/test_event.py +++ b/tests/helpers/test_event.py @@ -3043,7 +3043,9 @@ async def test_async_track_template_result_multiple_templates_mixing_domain( template_1 = Template("{{ states.switch.test.state == 'on' }}") template_2 = Template("{{ states.switch.test.state == 'on' }}") template_3 = Template("{{ states.switch.test.state == 'off' }}") - template_4 = Template("{{ states.switch | map(attribute='entity_id') | list }}") + template_4 = Template( + "{{ states.switch | sort(attribute='entity_id') | map(attribute='entity_id') | list }}" + ) refresh_runs = [] diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index f185191d1bf..4b3b9488bd8 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -185,7 +185,7 @@ def test_raise_exception_on_error(hass: HomeAssistant) -> None: def test_iterating_all_states(hass: HomeAssistant) -> None: """Test iterating all states.""" - tmpl_str = "{% for state in states %}{{ state.state }}{% endfor %}" + tmpl_str = "{% for state in states | sort(attribute='entity_id') %}{{ state.state }}{% endfor %}" info = render_to_info(hass, tmpl_str) assert_result_info(info, "", all_states=True) @@ -2511,20 +2511,22 @@ async def test_expand(hass: HomeAssistant) -> None: hass.states.async_set("test.object", "happy") info = render_to_info( - hass, "{{ expand('test.object') | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand('test.object') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info(info, "test.object", ["test.object"]) assert info.rate_limit is None info = render_to_info( hass, - "{{ expand('group.new_group') | map(attribute='entity_id') | join(', ') }}", + "{{ expand('group.new_group') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info(info, "", ["group.new_group"]) assert info.rate_limit is None info = render_to_info( - hass, "{{ expand(states.group) | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand(states.group) | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info(info, "", [], ["group"]) assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT @@ -2535,13 +2537,14 @@ async def test_expand(hass: HomeAssistant) -> None: info = render_to_info( hass, - "{{ expand('group.new_group') | map(attribute='entity_id') | join(', ') }}", + "{{ expand('group.new_group') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info(info, "test.object", {"group.new_group", "test.object"}) assert info.rate_limit is None info = render_to_info( - hass, "{{ expand(states.group) | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand(states.group) | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info(info, "test.object", {"test.object"}, ["group"]) assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT @@ -2550,7 +2553,7 @@ async def test_expand(hass: HomeAssistant) -> None: hass, ( "{{ expand('group.new_group', 'test.object')" - " | map(attribute='entity_id') | join(', ') }}" + " | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}" ), ) assert_result_info(info, "test.object", {"test.object", "group.new_group"}) @@ -2559,7 +2562,7 @@ async def test_expand(hass: HomeAssistant) -> None: hass, ( "{{ ['group.new_group', 'test.object'] | expand" - " | map(attribute='entity_id') | join(', ') }}" + " | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}" ), ) assert_result_info(info, "test.object", {"test.object", "group.new_group"}) @@ -2579,7 +2582,7 @@ async def test_expand(hass: HomeAssistant) -> None: hass, ( "{{ states.group.power_sensors.attributes.entity_id | expand " - "| map(attribute='state')|map('float')|sum }}" + "| sort(attribute='entity_id') | map(attribute='state')|map('float')|sum }}" ), ) assert_result_info( @@ -2607,7 +2610,8 @@ async def test_expand(hass: HomeAssistant) -> None: await hass.async_block_till_done() info = render_to_info( - hass, "{{ expand('light.grouped') | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand('light.grouped') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info( info, @@ -2629,7 +2633,8 @@ async def test_expand(hass: HomeAssistant) -> None: }, ) info = render_to_info( - hass, "{{ expand('zone.test') | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand('zone.test') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info( info, @@ -2644,7 +2649,8 @@ async def test_expand(hass: HomeAssistant) -> None: await hass.async_block_till_done() info = render_to_info( - hass, "{{ expand('zone.test') | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand('zone.test') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info( info, @@ -2659,7 +2665,8 @@ async def test_expand(hass: HomeAssistant) -> None: await hass.async_block_till_done() info = render_to_info( - hass, "{{ expand('zone.test') | map(attribute='entity_id') | join(', ') }}" + hass, + "{{ expand('zone.test') | sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}", ) assert_result_info( info, @@ -2709,7 +2716,7 @@ async def test_device_entities( hass, ( f"{{{{ device_entities('{device_entry.id}') | expand " - "| map(attribute='entity_id') | join(', ') }}" + "| sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}" ), ) assert_result_info(info, "", ["light.hue_5678"]) @@ -2721,7 +2728,7 @@ async def test_device_entities( hass, ( f"{{{{ device_entities('{device_entry.id}') | expand " - "| map(attribute='entity_id') | join(', ') }}" + "| sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}" ), ) assert_result_info(info, "light.hue_5678", ["light.hue_5678"]) @@ -2743,7 +2750,7 @@ async def test_device_entities( hass, ( f"{{{{ device_entities('{device_entry.id}') | expand " - "| map(attribute='entity_id') | join(', ') }}" + "| sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}" ), ) assert_result_info( @@ -3384,7 +3391,7 @@ def test_async_render_to_info_with_complex_branching(hass: HomeAssistant) -> Non {% elif states.light.a == "on" %} {{ states[domain] | list }} {% elif states('light.b') == "on" %} - {{ states[otherdomain] | map(attribute='entity_id') | list }} + {{ states[otherdomain] | sort(attribute='entity_id') | map(attribute='entity_id') | list }} {% elif states.light.a == "on" %} {{ states["nonexist"] | list }} {% else %} @@ -4205,7 +4212,7 @@ async def test_lights(hass: HomeAssistant) -> None: """Test we can sort lights.""" tmpl = """ - {% set lights_on = states.light|selectattr('state','eq','on')|map(attribute='name')|list %} + {% set lights_on = states.light|selectattr('state','eq','on')|sort(attribute='entity_id')|map(attribute='name')|list %} {% if lights_on|length == 0 %} No lights on. Sleep well.. {% elif lights_on|length == 1 %} @@ -4308,7 +4315,7 @@ async def test_unavailable_states(hass: HomeAssistant) -> None: tpl = template.Template( ( "{{ states | selectattr('state', 'in', ['unavailable','unknown','none']) " - "| map(attribute='entity_id') | list | join(', ') }}" + "| sort(attribute='entity_id') | map(attribute='entity_id') | list | join(', ') }}" ), hass, ) @@ -4318,7 +4325,7 @@ async def test_unavailable_states(hass: HomeAssistant) -> None: ( "{{ states.light " "| selectattr('state', 'in', ['unavailable','unknown','none']) " - "| map(attribute='entity_id') | list " + "| sort(attribute='entity_id') | map(attribute='entity_id') | list " "| join(', ') }}" ), hass,