Small cleanup of legacy groups (#102918)

* Small cleanup of legacy groups

* Update tests which create groups
This commit is contained in:
Erik Montnemery 2023-10-28 17:16:41 +02:00 committed by GitHub
parent 7e4e124f50
commit 03d3a87f23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 370 additions and 95 deletions

View File

@ -294,7 +294,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def reload_service_handler(service: ServiceCall) -> None:
"""Remove all user-defined groups and load new ones from config."""
auto = [e for e in component.entities if not e.user_defined]
auto = [e for e in component.entities if e.created_by_service]
if (conf := await component.async_prepare_reload()) is None:
return
@ -329,20 +329,15 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
or None
)
extra_arg = {
attr: service.data[attr]
for attr in (ATTR_ICON,)
if service.data.get(attr) is not None
}
await Group.async_create_group(
hass,
service.data.get(ATTR_NAME, object_id),
object_id=object_id,
created_by_service=True,
entity_ids=entity_ids,
user_defined=False,
icon=service.data.get(ATTR_ICON),
mode=service.data.get(ATTR_ALL),
**extra_arg,
object_id=object_id,
order=None,
)
return
@ -449,7 +444,8 @@ async def _async_process_config(hass: HomeAssistant, config: ConfigType) -> None
Group.async_create_group_entity(
hass,
name,
entity_ids,
created_by_service=False,
entity_ids=entity_ids,
icon=icon,
object_id=object_id,
mode=mode,
@ -570,11 +566,12 @@ class Group(Entity):
self,
hass: HomeAssistant,
name: str,
order: int | None = None,
icon: str | None = None,
user_defined: bool = True,
entity_ids: Collection[str] | None = None,
mode: bool | None = None,
*,
created_by_service: bool,
entity_ids: Collection[str] | None,
icon: str | None,
mode: bool | None,
order: int | None,
) -> None:
"""Initialize a group.
@ -588,7 +585,7 @@ class Group(Entity):
self._on_off: dict[str, bool] = {}
self._assumed: dict[str, bool] = {}
self._on_states: set[str] = set()
self.user_defined = user_defined
self.created_by_service = created_by_service
self.mode = any
if mode:
self.mode = all
@ -596,36 +593,18 @@ class Group(Entity):
self._assumed_state = False
self._async_unsub_state_changed: CALLBACK_TYPE | None = None
@staticmethod
def create_group(
hass: HomeAssistant,
name: str,
entity_ids: Collection[str] | None = None,
user_defined: bool = True,
icon: str | None = None,
object_id: str | None = None,
mode: bool | None = None,
order: int | None = None,
) -> Group:
"""Initialize a group."""
return asyncio.run_coroutine_threadsafe(
Group.async_create_group(
hass, name, entity_ids, user_defined, icon, object_id, mode, order
),
hass.loop,
).result()
@staticmethod
@callback
def async_create_group_entity(
hass: HomeAssistant,
name: str,
entity_ids: Collection[str] | None = None,
user_defined: bool = True,
icon: str | None = None,
object_id: str | None = None,
mode: bool | None = None,
order: int | None = None,
*,
created_by_service: bool,
entity_ids: Collection[str] | None,
icon: str | None,
mode: bool | None,
object_id: str | None,
order: int | None,
) -> Group:
"""Create a group entity."""
if order is None:
@ -639,11 +618,11 @@ class Group(Entity):
group = Group(
hass,
name,
order=order,
icon=icon,
user_defined=user_defined,
created_by_service=created_by_service,
entity_ids=entity_ids,
icon=icon,
mode=mode,
order=order,
)
group.entity_id = async_generate_entity_id(
@ -656,19 +635,27 @@ class Group(Entity):
async def async_create_group(
hass: HomeAssistant,
name: str,
entity_ids: Collection[str] | None = None,
user_defined: bool = True,
icon: str | None = None,
object_id: str | None = None,
mode: bool | None = None,
order: int | None = None,
*,
created_by_service: bool,
entity_ids: Collection[str] | None,
icon: str | None,
mode: bool | None,
object_id: str | None,
order: int | None,
) -> Group:
"""Initialize a group.
This method must be run in the event loop.
"""
group = Group.async_create_group_entity(
hass, name, entity_ids, user_defined, icon, object_id, mode, order
hass,
name,
created_by_service=created_by_service,
entity_ids=entity_ids,
icon=icon,
mode=mode,
object_id=object_id,
order=order,
)
# If called before the platform async_setup is called (test cases)
@ -704,7 +691,7 @@ class Group(Entity):
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes for the group."""
data = {ATTR_ENTITY_ID: self.tracking, ATTR_ORDER: self._order}
if not self.user_defined:
if self.created_by_service:
data[ATTR_AUTO] = True
return data

View File

@ -182,7 +182,16 @@ async def test_lights_turn_on_when_coming_home_after_sun_set_person(
assert await async_setup_component(hass, "group", {})
await hass.async_block_till_done()
await group.Group.async_create_group(hass, "person_me", ["person.me"])
await group.Group.async_create_group(
hass,
"person_me",
created_by_service=False,
entity_ids=["person.me"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert await async_setup_component(
hass,

View File

@ -39,7 +39,14 @@ async def test_setup_group_with_mixed_groupable_states(hass: HomeAssistant) -> N
assert await async_setup_component(hass, "group", {})
await group.Group.async_create_group(
hass, "person_and_light", ["light.Bowl", "device_tracker.Paulus"]
hass,
"person_and_light",
created_by_service=False,
entity_ids=["light.Bowl", "device_tracker.Paulus"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.async_block_till_done()
@ -54,7 +61,14 @@ async def test_setup_group_with_a_non_existing_state(hass: HomeAssistant) -> Non
assert await async_setup_component(hass, "group", {})
grp = await group.Group.async_create_group(
hass, "light_and_nothing", ["light.Bowl", "non.existing"]
hass,
"light_and_nothing",
created_by_service=False,
entity_ids=["light.Bowl", "non.existing"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert grp.state == STATE_ON
@ -68,7 +82,14 @@ async def test_setup_group_with_non_groupable_states(hass: HomeAssistant) -> Non
assert await async_setup_component(hass, "group", {})
grp = await group.Group.async_create_group(
hass, "chromecasts", ["cast.living_room", "cast.bedroom"]
hass,
"chromecasts",
created_by_service=False,
entity_ids=["cast.living_room", "cast.bedroom"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert grp.state is None
@ -76,7 +97,16 @@ async def test_setup_group_with_non_groupable_states(hass: HomeAssistant) -> Non
async def test_setup_empty_group(hass: HomeAssistant) -> None:
"""Try to set up an empty group."""
grp = await group.Group.async_create_group(hass, "nothing", [])
grp = await group.Group.async_create_group(
hass,
"nothing",
created_by_service=False,
entity_ids=[],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert grp.state is None
@ -89,7 +119,14 @@ async def test_monitor_group(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
# Test if group setup in our init mode is ok
@ -108,7 +145,14 @@ async def test_group_turns_off_if_all_off(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.async_block_till_done()
@ -127,7 +171,14 @@ async def test_group_turns_on_if_all_are_off_and_one_turns_on(
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
# Turn one on
@ -148,7 +199,14 @@ async def test_allgroup_stays_off_if_all_are_off_and_one_turns_on(
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False, mode=True
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=True,
object_id=None,
order=None,
)
# Turn one on
@ -167,7 +225,14 @@ async def test_allgroup_turn_on_if_last_turns_on(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False, mode=True
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=True,
object_id=None,
order=None,
)
# Turn one on
@ -186,7 +251,14 @@ async def test_expand_entity_ids(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert sorted(["light.ceiling", "light.bowl"]) == sorted(
@ -204,7 +276,14 @@ async def test_expand_entity_ids_does_not_return_duplicates(
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert ["light.bowl", "light.ceiling"] == sorted(
@ -226,8 +305,12 @@ async def test_expand_entity_ids_recursive(hass: HomeAssistant) -> None:
test_group = await group.Group.async_create_group(
hass,
"init_group",
["light.Bowl", "light.Ceiling", "group.init_group"],
False,
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling", "group.init_group"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert sorted(["light.ceiling", "light.bowl"]) == sorted(
@ -248,7 +331,14 @@ async def test_get_entity_ids(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert ["light.bowl", "light.ceiling"] == sorted(
@ -263,7 +353,14 @@ async def test_get_entity_ids_with_domain_filter(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
mixed_group = await group.Group.async_create_group(
hass, "mixed_group", ["light.Bowl", "switch.AC"], False
hass,
"mixed_group",
created_by_service=True,
entity_ids=["light.Bowl", "switch.AC"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert ["switch.ac"] == group.get_entity_ids(
@ -293,7 +390,14 @@ async def test_group_being_init_before_first_tracked_state_is_set_to_on(
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "test group", ["light.not_there_1"]
hass,
"test group",
created_by_service=False,
entity_ids=["light.not_there_1"],
icon=None,
mode=None,
object_id=None,
order=None,
)
hass.states.async_set("light.not_there_1", STATE_ON)
@ -314,7 +418,14 @@ async def test_group_being_init_before_first_tracked_state_is_set_to_off(
"""
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "test group", ["light.not_there_1"]
hass,
"test group",
created_by_service=False,
entity_ids=["light.not_there_1"],
icon=None,
mode=None,
object_id=None,
order=None,
)
hass.states.async_set("light.not_there_1", STATE_OFF)
@ -330,8 +441,26 @@ async def test_groups_get_unique_names(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
grp1 = await group.Group.async_create_group(hass, "Je suis Charlie")
grp2 = await group.Group.async_create_group(hass, "Je suis Charlie")
grp1 = await group.Group.async_create_group(
hass,
"Je suis Charlie",
created_by_service=False,
entity_ids=None,
icon=None,
mode=None,
object_id=None,
order=None,
)
grp2 = await group.Group.async_create_group(
hass,
"Je suis Charlie",
created_by_service=False,
entity_ids=None,
icon=None,
mode=None,
object_id=None,
order=None,
)
assert grp1.entity_id != grp2.entity_id
@ -342,13 +471,34 @@ async def test_expand_entity_ids_expands_nested_groups(hass: HomeAssistant) -> N
assert await async_setup_component(hass, "group", {})
await group.Group.async_create_group(
hass, "light", ["light.test_1", "light.test_2"]
hass,
"light",
created_by_service=False,
entity_ids=["light.test_1", "light.test_2"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await group.Group.async_create_group(
hass, "switch", ["switch.test_1", "switch.test_2"]
hass,
"switch",
created_by_service=False,
entity_ids=["switch.test_1", "switch.test_2"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await group.Group.async_create_group(
hass, "group_of_groups", ["group.light", "group.switch"]
hass,
"group_of_groups",
created_by_service=False,
entity_ids=["group.light", "group.switch"],
icon=None,
mode=None,
object_id=None,
order=None,
)
assert [
@ -367,7 +517,14 @@ async def test_set_assumed_state_based_on_tracked(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling", "sensor.no_exist"]
hass,
"init_group",
created_by_service=False,
entity_ids=["light.Bowl", "light.Ceiling", "sensor.no_exist"],
icon=None,
mode=None,
object_id=None,
order=None,
)
state = hass.states.get(test_group.entity_id)
@ -398,7 +555,14 @@ async def test_group_updated_after_device_tracker_zone_change(
assert await async_setup_component(hass, "device_tracker", {})
await group.Group.async_create_group(
hass, "peeps", ["device_tracker.Adam", "device_tracker.Eve"]
hass,
"peeps",
created_by_service=False,
entity_ids=["device_tracker.Adam", "device_tracker.Eve"],
icon=None,
mode=None,
object_id=None,
order=None,
)
hass.states.async_set("device_tracker.Adam", "cool_state_not_home")
@ -417,7 +581,14 @@ async def test_is_on(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.async_block_till_done()
@ -446,7 +617,14 @@ async def test_reloading_groups(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
await group.Group.async_create_group(
hass, "all tests", ["test.one", "test.two"], user_defined=False
hass,
"all tests",
created_by_service=True,
entity_ids=["test.one", "test.two"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.async_block_till_done()
@ -523,14 +701,24 @@ async def test_setup(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
test_group = await group.Group.async_create_group(
hass, "init_group", ["light.Bowl", "light.Ceiling"], False
hass,
"init_group",
created_by_service=True,
entity_ids=["light.Bowl", "light.Ceiling"],
icon=None,
mode=None,
object_id=None,
order=None,
)
await group.Group.async_create_group(
hass,
"created_group",
["light.Bowl", f"{test_group.entity_id}"],
True,
"mdi:work",
created_by_service=False,
entity_ids=["light.Bowl", f"{test_group.entity_id}"],
icon="mdi:work",
mode=None,
object_id=None,
order=None,
)
await hass.async_block_till_done()

View File

@ -224,7 +224,16 @@ async def test_set_config_parameter(
# Test groups get expanded
assert await async_setup_component(hass, "group", {})
await Group.async_create_group(hass, "test", [AIR_TEMPERATURE_SENSOR])
await Group.async_create_group(
hass,
"test",
created_by_service=False,
entity_ids=[AIR_TEMPERATURE_SENSOR],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.services.async_call(
DOMAIN,
SERVICE_SET_CONFIG_PARAMETER,
@ -594,7 +603,16 @@ async def test_bulk_set_config_parameters(
# Test groups get expanded
assert await async_setup_component(hass, "group", {})
await Group.async_create_group(hass, "test", [AIR_TEMPERATURE_SENSOR])
await Group.async_create_group(
hass,
"test",
created_by_service=False,
entity_ids=[AIR_TEMPERATURE_SENSOR],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.services.async_call(
DOMAIN,
SERVICE_BULK_SET_PARTIAL_CONFIG_PARAMETERS,
@ -728,7 +746,16 @@ async def test_refresh_value(
# Test groups get expanded
assert await async_setup_component(hass, "group", {})
await Group.async_create_group(hass, "test", [CLIMATE_RADIO_THERMOSTAT_ENTITY])
await Group.async_create_group(
hass,
"test",
created_by_service=False,
entity_ids=[CLIMATE_RADIO_THERMOSTAT_ENTITY],
icon=None,
mode=None,
object_id=None,
order=None,
)
client.async_send_command.return_value = {"result": 2}
await hass.services.async_call(
DOMAIN,
@ -848,7 +875,16 @@ async def test_set_value(
# Test groups get expanded
assert await async_setup_component(hass, "group", {})
await Group.async_create_group(hass, "test", [CLIMATE_DANFOSS_LC13_ENTITY])
await Group.async_create_group(
hass,
"test",
created_by_service=False,
entity_ids=[CLIMATE_DANFOSS_LC13_ENTITY],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,
@ -1150,7 +1186,14 @@ async def test_multicast_set_value(
# Test groups get expanded for multicast call
assert await async_setup_component(hass, "group", {})
await Group.async_create_group(
hass, "test", [CLIMATE_DANFOSS_LC13_ENTITY, CLIMATE_EUROTRONICS_SPIRIT_Z_ENTITY]
hass,
"test",
created_by_service=False,
entity_ids=[CLIMATE_DANFOSS_LC13_ENTITY, CLIMATE_EUROTRONICS_SPIRIT_Z_ENTITY],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.services.async_call(
DOMAIN,
@ -1516,7 +1559,14 @@ async def test_ping(
# Test groups get expanded for multicast call
assert await async_setup_component(hass, "group", {})
await Group.async_create_group(
hass, "test", [CLIMATE_DANFOSS_LC13_ENTITY, CLIMATE_RADIO_THERMOSTAT_ENTITY]
hass,
"test",
created_by_service=False,
entity_ids=[CLIMATE_DANFOSS_LC13_ENTITY, CLIMATE_RADIO_THERMOSTAT_ENTITY],
icon=None,
mode=None,
object_id=None,
order=None,
)
await hass.services.async_call(
DOMAIN,

View File

@ -465,7 +465,14 @@ async def test_extract_entity_ids(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
await hass.async_block_till_done()
await hass.components.group.Group.async_create_group(
hass, "test", ["light.Ceiling", "light.Kitchen"]
hass,
"test",
created_by_service=False,
entity_ids=["light.Ceiling", "light.Kitchen"],
icon=None,
mode=None,
object_id=None,
order=None,
)
call = ServiceCall("light", "turn_on", {ATTR_ENTITY_ID: "light.Bowl"})

View File

@ -2649,7 +2649,16 @@ async def test_closest_function_home_vs_group_entity_id(hass: HomeAssistant) ->
assert await async_setup_component(hass, "group", {})
await hass.async_block_till_done()
await group.Group.async_create_group(hass, "location group", ["test_domain.object"])
await group.Group.async_create_group(
hass,
"location group",
created_by_service=False,
entity_ids=["test_domain.object"],
icon=None,
mode=None,
object_id=None,
order=None,
)
info = render_to_info(hass, '{{ closest("group.location_group").entity_id }}')
assert_result_info(
@ -2677,7 +2686,16 @@ async def test_closest_function_home_vs_group_state(hass: HomeAssistant) -> None
assert await async_setup_component(hass, "group", {})
await hass.async_block_till_done()
await group.Group.async_create_group(hass, "location group", ["test_domain.object"])
await group.Group.async_create_group(
hass,
"location group",
created_by_service=False,
entity_ids=["test_domain.object"],
icon=None,
mode=None,
object_id=None,
order=None,
)
info = render_to_info(hass, '{{ closest("group.location_group").entity_id }}')
assert_result_info(
@ -2727,7 +2745,16 @@ async def test_expand(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
await hass.async_block_till_done()
await group.Group.async_create_group(hass, "new group", ["test.object"])
await group.Group.async_create_group(
hass,
"new group",
created_by_service=False,
entity_ids=["test.object"],
icon=None,
mode=None,
object_id=None,
order=None,
)
info = render_to_info(
hass,
@ -2769,7 +2796,14 @@ async def test_expand(hass: HomeAssistant) -> None:
assert await async_setup_component(hass, "group", {})
await hass.async_block_till_done()
await group.Group.async_create_group(
hass, "power sensors", ["sensor.power_1", "sensor.power_2", "sensor.power_3"]
hass,
"power sensors",
created_by_service=False,
entity_ids=["sensor.power_1", "sensor.power_2", "sensor.power_3"],
icon=None,
mode=None,
object_id=None,
order=None,
)
info = render_to_info(