Avoid sorting domain/all states in templates (#90608)

pull/90855/head
J. Nick Koston 2023-03-31 11:27:55 -10:00 committed by Paulus Schoutsen
parent 03f085d7be
commit 6242dd2214
3 changed files with 33 additions and 24 deletions

View File

@ -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]:

View File

@ -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 = []

View File

@ -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,