Adjust registry access in conversation (#88879)

pull/88882/merge
epenet 2023-03-01 03:56:18 +01:00 committed by GitHub
parent 6ab0b2751d
commit 0e4c32efe2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 68 deletions

View File

@ -18,9 +18,9 @@ import yaml
from homeassistant import core, setup
from homeassistant.helpers import (
area_registry,
device_registry,
entity_registry,
area_registry as ar,
device_registry as dr,
entity_registry as er,
intent,
template,
translation,
@ -95,12 +95,12 @@ class DefaultAgent(AbstractConversationAgent):
self._config_intents = config_intents
self.hass.bus.async_listen(
area_registry.EVENT_AREA_REGISTRY_UPDATED,
ar.EVENT_AREA_REGISTRY_UPDATED,
self._async_handle_area_registry_changed,
run_immediately=True,
)
self.hass.bus.async_listen(
entity_registry.EVENT_ENTITY_REGISTRY_UPDATED,
er.EVENT_ENTITY_REGISTRY_UPDATED,
self._async_handle_entity_registry_changed,
run_immediately=True,
)
@ -471,8 +471,8 @@ class DefaultAgent(AbstractConversationAgent):
states = [
state for state in self.hass.states.async_all() if is_entity_exposed(state)
]
entities = entity_registry.async_get(self.hass)
devices = device_registry.async_get(self.hass)
entities = er.async_get(self.hass)
devices = dr.async_get(self.hass)
# Gather exposed entity names
entity_names = []
@ -512,7 +512,7 @@ class DefaultAgent(AbstractConversationAgent):
entity_names.append((state.name, state.name, context))
# Gather areas from exposed entities
areas = area_registry.async_get(self.hass)
areas = ar.async_get(self.hass)
area_names = []
for area_id in area_ids_with_entities:
area = areas.async_get_area(area_id)

View File

@ -7,10 +7,10 @@ from homeassistant.components import conversation
from homeassistant.const import ATTR_FRIENDLY_NAME
from homeassistant.core import DOMAIN as HASS_DOMAIN, Context, HomeAssistant
from homeassistant.helpers import (
area_registry,
device_registry,
area_registry as ar,
device_registry as dr,
entity,
entity_registry,
entity_registry as er,
intent,
)
from homeassistant.setup import async_setup_component
@ -29,19 +29,18 @@ async def init_components(hass):
@pytest.mark.parametrize(
"er_kwargs",
[
{"hidden_by": entity_registry.RegistryEntryHider.USER},
{"hidden_by": entity_registry.RegistryEntryHider.INTEGRATION},
{"hidden_by": er.RegistryEntryHider.USER},
{"hidden_by": er.RegistryEntryHider.INTEGRATION},
{"entity_category": entity.EntityCategory.CONFIG},
{"entity_category": entity.EntityCategory.DIAGNOSTIC},
],
)
async def test_hidden_entities_skipped(
hass: HomeAssistant, init_components, er_kwargs
hass: HomeAssistant, init_components, er_kwargs, entity_registry: er.EntityRegistry
) -> None:
"""Test we skip hidden entities."""
er = entity_registry.async_get(hass)
er.async_get_or_create(
entity_registry.async_get_or_create(
"light", "demo", "1234", suggested_object_id="Test light", **er_kwargs
)
hass.states.async_set("light.test_light", "off")
@ -71,27 +70,34 @@ async def test_exposed_domains(hass: HomeAssistant, init_components) -> None:
assert result.response.error_code == intent.IntentResponseErrorCode.NO_INTENT_MATCH
async def test_exposed_areas(hass: HomeAssistant, init_components) -> None:
async def test_exposed_areas(
hass: HomeAssistant,
init_components,
area_registry: ar.AreaRegistry,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test that only expose areas with an exposed entity/device."""
areas = area_registry.async_get(hass)
area_kitchen = areas.async_get_or_create("kitchen")
area_bedroom = areas.async_get_or_create("bedroom")
area_kitchen = area_registry.async_get_or_create("kitchen")
area_bedroom = area_registry.async_get_or_create("bedroom")
devices = device_registry.async_get(hass)
kitchen_device = devices.async_get_or_create(
kitchen_device = device_registry.async_get_or_create(
config_entry_id="1234", connections=set(), identifiers={("demo", "id-1234")}
)
devices.async_update_device(kitchen_device.id, area_id=area_kitchen.id)
device_registry.async_update_device(kitchen_device.id, area_id=area_kitchen.id)
entities = entity_registry.async_get(hass)
kitchen_light = entities.async_get_or_create("light", "demo", "1234")
entities.async_update_entity(kitchen_light.entity_id, device_id=kitchen_device.id)
kitchen_light = entity_registry.async_get_or_create("light", "demo", "1234")
entity_registry.async_update_entity(
kitchen_light.entity_id, device_id=kitchen_device.id
)
hass.states.async_set(
kitchen_light.entity_id, "on", attributes={ATTR_FRIENDLY_NAME: "kitchen light"}
)
bedroom_light = entities.async_get_or_create("light", "demo", "5678")
entities.async_update_entity(bedroom_light.entity_id, area_id=area_bedroom.id)
bedroom_light = entity_registry.async_get_or_create("light", "demo", "5678")
entity_registry.async_update_entity(
bedroom_light.entity_id, area_id=area_bedroom.id
)
hass.states.async_set(
bedroom_light.entity_id, "on", attributes={ATTR_FRIENDLY_NAME: "bedroom light"}
)

View File

@ -12,9 +12,9 @@ from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
from homeassistant.const import ATTR_FRIENDLY_NAME
from homeassistant.core import Context, HomeAssistant
from homeassistant.helpers import (
area_registry,
device_registry,
entity_registry,
area_registry as ar,
device_registry as dr,
entity_registry as er,
intent,
)
from homeassistant.setup import async_setup_component
@ -53,12 +53,14 @@ async def test_http_processing_intent(
hass_client: ClientSessionGenerator,
hass_admin_user: MockUser,
agent_id,
entity_registry: er.EntityRegistry,
) -> None:
"""Test processing intent via HTTP API."""
# Add an alias
entities = entity_registry.async_get(hass)
entities.async_get_or_create("light", "demo", "1234", suggested_object_id="kitchen")
entities.async_update_entity("light.kitchen", aliases={"my cool light"})
entity_registry.async_get_or_create(
"light", "demo", "1234", suggested_object_id="kitchen"
)
entity_registry.async_update_entity("light.kitchen", aliases={"my cool light"})
hass.states.async_set("light.kitchen", "off")
calls = async_mock_service(hass, LIGHT_DOMAIN, "turn_on")
@ -101,12 +103,14 @@ async def test_http_processing_intent_target_ha_agent(
hass_client: ClientSessionGenerator,
hass_admin_user: MockUser,
mock_agent,
entity_registry: er.EntityRegistry,
) -> None:
"""Test processing intent can be processed via HTTP API with picking agent."""
# Add an alias
entities = entity_registry.async_get(hass)
entities.async_get_or_create("light", "demo", "1234", suggested_object_id="kitchen")
entities.async_update_entity("light.kitchen", aliases={"my cool light"})
entity_registry.async_get_or_create(
"light", "demo", "1234", suggested_object_id="kitchen"
)
entity_registry.async_update_entity("light.kitchen", aliases={"my cool light"})
hass.states.async_set("light.kitchen", "off")
calls = async_mock_service(hass, LIGHT_DOMAIN, "turn_on")
@ -148,15 +152,17 @@ async def test_http_processing_intent_entity_added(
init_components,
hass_client: ClientSessionGenerator,
hass_admin_user: MockUser,
entity_registry: er.EntityRegistry,
) -> None:
"""Test processing intent via HTTP API with entities added later.
We want to ensure that adding an entity later busts the cache
so that the new entity is available as well as any aliases.
"""
er = entity_registry.async_get(hass)
er.async_get_or_create("light", "demo", "1234", suggested_object_id="kitchen")
er.async_update_entity("light.kitchen", aliases={"my cool light"})
entity_registry.async_get_or_create(
"light", "demo", "1234", suggested_object_id="kitchen"
)
entity_registry.async_update_entity("light.kitchen", aliases={"my cool light"})
hass.states.async_set("light.kitchen", "off")
calls = async_mock_service(hass, LIGHT_DOMAIN, "turn_on")
@ -192,7 +198,9 @@ async def test_http_processing_intent_entity_added(
}
# Add an alias
er.async_get_or_create("light", "demo", "5678", suggested_object_id="late")
entity_registry.async_get_or_create(
"light", "demo", "5678", suggested_object_id="late"
)
hass.states.async_set("light.late", "off", {"friendly_name": "friendly light"})
client = await hass_client()
@ -226,7 +234,7 @@ async def test_http_processing_intent_entity_added(
}
# Now add an alias
er.async_update_entity("light.late", aliases={"late added light"})
entity_registry.async_update_entity("light.late", aliases={"late added light"})
client = await hass_client()
resp = await client.post(
@ -259,7 +267,7 @@ async def test_http_processing_intent_entity_added(
}
# Now delete the entity
er.async_remove("light.late")
entity_registry.async_remove("light.late")
client = await hass_client()
resp = await client.post(
@ -786,23 +794,28 @@ async def test_non_default_response(hass: HomeAssistant, init_components) -> Non
assert result.response.speech["plain"]["speech"] == "Opened"
async def test_turn_on_area(hass: HomeAssistant, init_components) -> None:
async def test_turn_on_area(
hass: HomeAssistant,
init_components,
area_registry: ar.AreaRegistry,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test turning on an area."""
er = entity_registry.async_get(hass)
dr = device_registry.async_get(hass)
ar = area_registry.async_get(hass)
entry = MockConfigEntry(domain="test")
device = dr.async_get_or_create(
device = device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
kitchen_area = ar.async_create("kitchen")
dr.async_update_device(device.id, area_id=kitchen_area.id)
kitchen_area = area_registry.async_create("kitchen")
device_registry.async_update_device(device.id, area_id=kitchen_area.id)
er.async_get_or_create("light", "demo", "1234", suggested_object_id="stove")
er.async_update_entity(
entity_registry.async_get_or_create(
"light", "demo", "1234", suggested_object_id="stove"
)
entity_registry.async_update_entity(
"light.stove", aliases={"my stove light"}, area_id=kitchen_area.id
)
hass.states.async_set("light.stove", "off")
@ -822,9 +835,9 @@ async def test_turn_on_area(hass: HomeAssistant, init_components) -> None:
assert call.service == "turn_on"
assert call.data == {"entity_id": ["light.stove"]}
basement_area = ar.async_create("basement")
dr.async_update_device(device.id, area_id=basement_area.id)
er.async_update_entity("light.stove", area_id=basement_area.id)
basement_area = area_registry.async_create("basement")
device_registry.async_update_device(device.id, area_id=basement_area.id)
entity_registry.async_update_entity("light.stove", area_id=basement_area.id)
calls.clear()
# Test that the area is updated
@ -852,33 +865,40 @@ async def test_turn_on_area(hass: HomeAssistant, init_components) -> None:
assert call.data == {"entity_id": ["light.stove"]}
async def test_light_area_same_name(hass: HomeAssistant, init_components) -> None:
async def test_light_area_same_name(
hass: HomeAssistant,
init_components,
area_registry: ar.AreaRegistry,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test turning on a light with the same name as an area."""
entities = entity_registry.async_get(hass)
devices = device_registry.async_get(hass)
areas = area_registry.async_get(hass)
entry = MockConfigEntry(domain="test")
device = devices.async_get_or_create(
device = device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
kitchen_area = areas.async_create("kitchen")
devices.async_update_device(device.id, area_id=kitchen_area.id)
kitchen_area = area_registry.async_create("kitchen")
device_registry.async_update_device(device.id, area_id=kitchen_area.id)
kitchen_light = entities.async_get_or_create(
kitchen_light = entity_registry.async_get_or_create(
"light", "demo", "1234", original_name="kitchen light"
)
entities.async_update_entity(kitchen_light.entity_id, area_id=kitchen_area.id)
entity_registry.async_update_entity(
kitchen_light.entity_id, area_id=kitchen_area.id
)
hass.states.async_set(
kitchen_light.entity_id, "off", attributes={ATTR_FRIENDLY_NAME: "kitchen light"}
)
ceiling_light = entities.async_get_or_create(
ceiling_light = entity_registry.async_get_or_create(
"light", "demo", "5678", original_name="ceiling light"
)
entities.async_update_entity(ceiling_light.entity_id, area_id=kitchen_area.id)
entity_registry.async_update_entity(
ceiling_light.entity_id, area_id=kitchen_area.id
)
hass.states.async_set(
ceiling_light.entity_id, "off", attributes={ATTR_FRIENDLY_NAME: "ceiling light"}
)