mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Properly handle the case when a group includes itself. (#8398)
* Properly handle the case when a group includes itself. * Fix lint
This commit is contained in:
parent
57c5ed33ee
commit
c5bf4fe339
@ -184,7 +184,6 @@ def expand_entity_ids(hass, entity_ids):
|
||||
Async friendly.
|
||||
"""
|
||||
found_ids = []
|
||||
|
||||
for entity_id in entity_ids:
|
||||
if not isinstance(entity_id, str):
|
||||
continue
|
||||
@ -196,9 +195,13 @@ def expand_entity_ids(hass, entity_ids):
|
||||
domain, _ = ha.split_entity_id(entity_id)
|
||||
|
||||
if domain == DOMAIN:
|
||||
child_entities = get_entity_ids(hass, entity_id)
|
||||
if entity_id in child_entities:
|
||||
child_entities = list(child_entities)
|
||||
child_entities.remove(entity_id)
|
||||
found_ids.extend(
|
||||
ent_id for ent_id
|
||||
in expand_entity_ids(hass, get_entity_ids(hass, entity_id))
|
||||
in expand_entity_ids(hass, child_entities)
|
||||
if ent_id not in found_ids)
|
||||
|
||||
else:
|
||||
@ -223,7 +226,6 @@ def get_entity_ids(hass, entity_id, domain_filter=None):
|
||||
return []
|
||||
|
||||
entity_ids = group.attributes[ATTR_ENTITY_ID]
|
||||
|
||||
if not domain_filter:
|
||||
return entity_ids
|
||||
|
||||
|
@ -150,6 +150,20 @@ class TestComponentsGroup(unittest.TestCase):
|
||||
sorted(group.expand_entity_ids(
|
||||
self.hass, ['light.bowl', test_group.entity_id])))
|
||||
|
||||
def test_expand_entity_ids_recursive(self):
|
||||
"""Test expand_entity_ids method with a group that contains itself."""
|
||||
self.hass.states.set('light.Bowl', STATE_ON)
|
||||
self.hass.states.set('light.Ceiling', STATE_OFF)
|
||||
test_group = group.Group.create_group(
|
||||
self.hass,
|
||||
'init_group',
|
||||
['light.Bowl', 'light.Ceiling', 'group.init_group'],
|
||||
False)
|
||||
|
||||
self.assertEqual(sorted(['light.ceiling', 'light.bowl']),
|
||||
sorted(group.expand_entity_ids(
|
||||
self.hass, [test_group.entity_id])))
|
||||
|
||||
def test_expand_entity_ids_ignores_non_strings(self):
|
||||
"""Test that non string elements in lists are ignored."""
|
||||
self.assertEqual([], group.expand_entity_ids(self.hass, [5, True]))
|
||||
@ -226,11 +240,11 @@ class TestComponentsGroup(unittest.TestCase):
|
||||
|
||||
group_conf = OrderedDict()
|
||||
group_conf['second_group'] = {
|
||||
'entities': 'light.Bowl, ' + test_group.entity_id,
|
||||
'icon': 'mdi:work',
|
||||
'view': True,
|
||||
'control': 'hidden',
|
||||
}
|
||||
'entities': 'light.Bowl, ' + test_group.entity_id,
|
||||
'icon': 'mdi:work',
|
||||
'view': True,
|
||||
'control': 'hidden',
|
||||
}
|
||||
group_conf['test_group'] = 'hello.world,sensor.happy'
|
||||
group_conf['empty_group'] = {'name': 'Empty Group', 'entities': None}
|
||||
|
||||
@ -275,8 +289,8 @@ class TestComponentsGroup(unittest.TestCase):
|
||||
self.hass, 'light', ['light.test_1', 'light.test_2'])
|
||||
group.Group.create_group(
|
||||
self.hass, 'switch', ['switch.test_1', 'switch.test_2'])
|
||||
group.Group.create_group(self.hass, 'group_of_groups', ['group.light',
|
||||
'group.switch'])
|
||||
group.Group.create_group(
|
||||
self.hass, 'group_of_groups', ['group.light', 'group.switch'])
|
||||
|
||||
self.assertEqual(
|
||||
['light.test_1', 'light.test_2', 'switch.test_1', 'switch.test_2'],
|
||||
@ -325,27 +339,26 @@ class TestComponentsGroup(unittest.TestCase):
|
||||
def test_reloading_groups(self):
|
||||
"""Test reloading the group config."""
|
||||
assert setup_component(self.hass, 'group', {'group': {
|
||||
'second_group': {
|
||||
'entities': 'light.Bowl',
|
||||
'icon': 'mdi:work',
|
||||
'view': True,
|
||||
},
|
||||
'test_group': 'hello.world,sensor.happy',
|
||||
'empty_group': {'name': 'Empty Group', 'entities': None},
|
||||
}
|
||||
})
|
||||
'second_group': {
|
||||
'entities': 'light.Bowl',
|
||||
'icon': 'mdi:work',
|
||||
'view': True,
|
||||
},
|
||||
'test_group': 'hello.world,sensor.happy',
|
||||
'empty_group': {'name': 'Empty Group', 'entities': None},
|
||||
}})
|
||||
|
||||
assert sorted(self.hass.states.entity_ids()) == \
|
||||
['group.empty_group', 'group.second_group', 'group.test_group']
|
||||
assert self.hass.bus.listeners['state_changed'] == 3
|
||||
|
||||
with patch('homeassistant.config.load_yaml_config_file', return_value={
|
||||
'group': {
|
||||
'hello': {
|
||||
'entities': 'light.Bowl',
|
||||
'icon': 'mdi:work',
|
||||
'view': True,
|
||||
}}}):
|
||||
'group': {
|
||||
'hello': {
|
||||
'entities': 'light.Bowl',
|
||||
'icon': 'mdi:work',
|
||||
'view': True,
|
||||
}}}):
|
||||
group.reload(self.hass)
|
||||
self.hass.block_till_done()
|
||||
|
||||
@ -395,6 +408,7 @@ def test_service_group_services(hass):
|
||||
assert hass.services.has_service('group', group.SERVICE_REMOVE)
|
||||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
@asyncio.coroutine
|
||||
def test_service_group_set_group_remove_group(hass):
|
||||
"""Check if service are available."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user