In 2022.4 a breaking change to the expand function’s behaviour was introduced whereby groups within groups would be expanded too, where the inner groups aren’t groups using the group domain. While this is a useful change, it did break functionality due to the previous behaviour many relied on. To avoid introducing another breaking change (by reverting the behaviour and adding a recursion parameter instead), I’d like to suggest that the new behaviour is kept, but a parameter which defaults to true gets added (i.e. expand(..., recursion=True)
). Alternatively, an even more flexible option would be to control the recursion depth.
This isn’t the breaking change. expand
always expanded group
entities within group
entities. And to clarify when I say group
entities here I mean specifically entities with domain group
(like group.all_lights
).
However prior to 2022.4 expand
did not expand other types of groups at all. For example if I had a light group called light.my_group
and I did expand('light.my_group')
then I would receive a list of one entity - the state of light.my_group
.
So let’s take this to an example. I have two entities prior to 2022.4, one is an old-style group called group.my_light
and the other is a light group called light.my_light
. Both contain two entities, light.one
and light.two
and both are on.
If I wanted to count the number of lights that were on in each group with a template here would be the result in 2022.3:
{{ expand('group.my_light') | selectattr('state', 'eq', 'on') | list | count }}
# result is 2
{{ expand('light.my_light') | selectattr('state', 'eq', 'on') | list | count }}
# result is 1
Why are these different? Because light groups did not expand like groups so the second one is just counting one item. Here’s the issue about it.
I don’t necessarily disagree with this FR, being able to control recursion sounds like a useful feature. But please get the details right. This is not the breaking change:
The breaking change is this:
In 2022.4 a breaking change to expand function’s behavior was introduced whereby other types of groups (light groups, switch groups, cover groups, etc.) were expanded just like old-style groups.
And I would suggest rather then a recursion
boolean option, add a depth
option that takes a number. Because personally sometimes I actually just want to do this:
expand('group.my_group', depth=0)
And have that just give me a state object for group.my_group
without expanding it into its subentities. A depth parameter could support use cases like these in addition to yours. Yours would be this:
expand('group.my_group', depth=1)
My mistake. I’ve clarified. I’m not affected by this at all. I was simply doing everyone a favour based on the discussions I’ve seen, but you’re right: the details are important.
Thanks for your examples.
I initially mentioned this in the 2022.4 release thread too. But then I thought: What would the default be to keep the new behaviour? expand(..., depth=-1)
to say expand all?
It never expanded Light Groups before and now it does. Old behavior, that existed since expand
was introduced many versions ago, was replaced by new behavior. It altered expand
's behavior to the extent that certain existing templates no longer produced the same result. By its very definition, that’s a Breaking Change.
Trigger-based Template Binary Sensors defaulted to unknown
on startup until 2022.4.0. Then it changed behavior; its last known state was restored on startup. Old behavior replaced by new behavior and was documented as a Breaking Change in 2022.4.0. Based on that inclusion, expand
's new behavior should have also been reported as a Breaking Change.
Sure, I agree.
I just was trying to clarify what exactly the breaking change was. The post originally said that expand didn’t expand groups within groups which wasn’t true. It did expand actual group
entities with that domain, it just didn’t expand the type-specific groups like light groups at all. Regardless of whether they were in something else or not.
Until this FR gets implemented:
While I don’t have a direct replacement/suggestion, it is still possible to emulate the old behavior and even … sort of… control the number of recursions by doing something like this:
{% set ns = namespace(count = 0) %}
{% for light_entity in state_attr("group.lights_all", "entity_id") %}
{% if is_state(light_entity, "on") %}
{{ ns.count = ns.count + 1 }}
{% endif %}
{% endfor %}
{{ ns.count }}
Obviously additional logic (IE nested for loops) for a second or third layer of recursion, but this will only expand the top level of a group as is. The key is the entity_id attribute of group entities contains a list of entities (unexpanded), so you’re basically manually “expanding” the group by iterating this list.