mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Avoid sorting domain/all states in templates (#90608)
This commit is contained in:
parent
03f085d7be
commit
6242dd2214
@ -13,7 +13,7 @@ from functools import cache, lru_cache, partial, wraps
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
from operator import attrgetter, contains
|
from operator import contains
|
||||||
import pathlib
|
import pathlib
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
@ -983,7 +983,7 @@ def _state_generator(
|
|||||||
hass: HomeAssistant, domain: str | None
|
hass: HomeAssistant, domain: str | None
|
||||||
) -> Generator[TemplateState, None, None]:
|
) -> Generator[TemplateState, None, None]:
|
||||||
"""State generator for a domain or all states."""
|
"""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)
|
yield _template_state_no_collect(hass, state)
|
||||||
|
|
||||||
|
|
||||||
@ -1097,7 +1097,7 @@ def expand(hass: HomeAssistant, *args: Any) -> Iterable[State]:
|
|||||||
_collect_state(hass, entity_id)
|
_collect_state(hass, entity_id)
|
||||||
found[entity_id] = entity
|
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]:
|
def device_entities(hass: HomeAssistant, _device_id: str) -> Iterable[str]:
|
||||||
|
@ -3043,7 +3043,9 @@ async def test_async_track_template_result_multiple_templates_mixing_domain(
|
|||||||
template_1 = Template("{{ states.switch.test.state == 'on' }}")
|
template_1 = Template("{{ states.switch.test.state == 'on' }}")
|
||||||
template_2 = Template("{{ states.switch.test.state == 'on' }}")
|
template_2 = Template("{{ states.switch.test.state == 'on' }}")
|
||||||
template_3 = Template("{{ states.switch.test.state == 'off' }}")
|
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 = []
|
refresh_runs = []
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ def test_raise_exception_on_error(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
def test_iterating_all_states(hass: HomeAssistant) -> None:
|
def test_iterating_all_states(hass: HomeAssistant) -> None:
|
||||||
"""Test iterating all states."""
|
"""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)
|
info = render_to_info(hass, tmpl_str)
|
||||||
assert_result_info(info, "", all_states=True)
|
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")
|
hass.states.async_set("test.object", "happy")
|
||||||
|
|
||||||
info = render_to_info(
|
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_result_info(info, "test.object", ["test.object"])
|
||||||
assert info.rate_limit is None
|
assert info.rate_limit is None
|
||||||
|
|
||||||
info = render_to_info(
|
info = render_to_info(
|
||||||
hass,
|
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_result_info(info, "", ["group.new_group"])
|
||||||
assert info.rate_limit is None
|
assert info.rate_limit is None
|
||||||
|
|
||||||
info = render_to_info(
|
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_result_info(info, "", [], ["group"])
|
||||||
assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT
|
assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT
|
||||||
@ -2535,13 +2537,14 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
info = render_to_info(
|
info = render_to_info(
|
||||||
hass,
|
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_result_info(info, "test.object", {"group.new_group", "test.object"})
|
||||||
assert info.rate_limit is None
|
assert info.rate_limit is None
|
||||||
|
|
||||||
info = render_to_info(
|
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_result_info(info, "test.object", {"test.object"}, ["group"])
|
||||||
assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT
|
assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT
|
||||||
@ -2550,7 +2553,7 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
hass,
|
hass,
|
||||||
(
|
(
|
||||||
"{{ expand('group.new_group', 'test.object')"
|
"{{ 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"})
|
assert_result_info(info, "test.object", {"test.object", "group.new_group"})
|
||||||
@ -2559,7 +2562,7 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
hass,
|
hass,
|
||||||
(
|
(
|
||||||
"{{ ['group.new_group', 'test.object'] | expand"
|
"{{ ['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"})
|
assert_result_info(info, "test.object", {"test.object", "group.new_group"})
|
||||||
@ -2579,7 +2582,7 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
hass,
|
hass,
|
||||||
(
|
(
|
||||||
"{{ states.group.power_sensors.attributes.entity_id | expand "
|
"{{ 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(
|
assert_result_info(
|
||||||
@ -2607,7 +2610,8 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
info = render_to_info(
|
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(
|
assert_result_info(
|
||||||
info,
|
info,
|
||||||
@ -2629,7 +2633,8 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
info = render_to_info(
|
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(
|
assert_result_info(
|
||||||
info,
|
info,
|
||||||
@ -2644,7 +2649,8 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
info = render_to_info(
|
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(
|
assert_result_info(
|
||||||
info,
|
info,
|
||||||
@ -2659,7 +2665,8 @@ async def test_expand(hass: HomeAssistant) -> None:
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
info = render_to_info(
|
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(
|
assert_result_info(
|
||||||
info,
|
info,
|
||||||
@ -2709,7 +2716,7 @@ async def test_device_entities(
|
|||||||
hass,
|
hass,
|
||||||
(
|
(
|
||||||
f"{{{{ device_entities('{device_entry.id}') | expand "
|
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"])
|
assert_result_info(info, "", ["light.hue_5678"])
|
||||||
@ -2721,7 +2728,7 @@ async def test_device_entities(
|
|||||||
hass,
|
hass,
|
||||||
(
|
(
|
||||||
f"{{{{ device_entities('{device_entry.id}') | expand "
|
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"])
|
assert_result_info(info, "light.hue_5678", ["light.hue_5678"])
|
||||||
@ -2743,7 +2750,7 @@ async def test_device_entities(
|
|||||||
hass,
|
hass,
|
||||||
(
|
(
|
||||||
f"{{{{ device_entities('{device_entry.id}') | expand "
|
f"{{{{ device_entities('{device_entry.id}') | expand "
|
||||||
"| map(attribute='entity_id') | join(', ') }}"
|
"| sort(attribute='entity_id') | map(attribute='entity_id') | join(', ') }}"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
assert_result_info(
|
assert_result_info(
|
||||||
@ -3384,7 +3391,7 @@ def test_async_render_to_info_with_complex_branching(hass: HomeAssistant) -> Non
|
|||||||
{% elif states.light.a == "on" %}
|
{% elif states.light.a == "on" %}
|
||||||
{{ states[domain] | list }}
|
{{ states[domain] | list }}
|
||||||
{% elif states('light.b') == "on" %}
|
{% 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" %}
|
{% elif states.light.a == "on" %}
|
||||||
{{ states["nonexist"] | list }}
|
{{ states["nonexist"] | list }}
|
||||||
{% else %}
|
{% else %}
|
||||||
@ -4205,7 +4212,7 @@ async def test_lights(hass: HomeAssistant) -> None:
|
|||||||
"""Test we can sort lights."""
|
"""Test we can sort lights."""
|
||||||
|
|
||||||
tmpl = """
|
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 %}
|
{% if lights_on|length == 0 %}
|
||||||
No lights on. Sleep well..
|
No lights on. Sleep well..
|
||||||
{% elif lights_on|length == 1 %}
|
{% elif lights_on|length == 1 %}
|
||||||
@ -4308,7 +4315,7 @@ async def test_unavailable_states(hass: HomeAssistant) -> None:
|
|||||||
tpl = template.Template(
|
tpl = template.Template(
|
||||||
(
|
(
|
||||||
"{{ states | selectattr('state', 'in', ['unavailable','unknown','none']) "
|
"{{ states | selectattr('state', 'in', ['unavailable','unknown','none']) "
|
||||||
"| map(attribute='entity_id') | list | join(', ') }}"
|
"| sort(attribute='entity_id') | map(attribute='entity_id') | list | join(', ') }}"
|
||||||
),
|
),
|
||||||
hass,
|
hass,
|
||||||
)
|
)
|
||||||
@ -4318,7 +4325,7 @@ async def test_unavailable_states(hass: HomeAssistant) -> None:
|
|||||||
(
|
(
|
||||||
"{{ states.light "
|
"{{ states.light "
|
||||||
"| selectattr('state', 'in', ['unavailable','unknown','none']) "
|
"| selectattr('state', 'in', ['unavailable','unknown','none']) "
|
||||||
"| map(attribute='entity_id') | list "
|
"| sort(attribute='entity_id') | map(attribute='entity_id') | list "
|
||||||
"| join(', ') }}"
|
"| join(', ') }}"
|
||||||
),
|
),
|
||||||
hass,
|
hass,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user