Add person reload service (#30493)
This commit is contained in:
parent
35e19eec18
commit
30076d1843
6 changed files with 121 additions and 8 deletions
|
@ -19,13 +19,26 @@ from homeassistant.const import (
|
|||
CONF_ID,
|
||||
CONF_NAME,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
SERVICE_RELOAD,
|
||||
STATE_HOME,
|
||||
STATE_NOT_HOME,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant, State, callback, split_entity_id
|
||||
from homeassistant.helpers import collection, config_validation as cv, entity_registry
|
||||
from homeassistant.core import (
|
||||
Event,
|
||||
HomeAssistant,
|
||||
ServiceCall,
|
||||
State,
|
||||
callback,
|
||||
split_entity_id,
|
||||
)
|
||||
from homeassistant.helpers import (
|
||||
collection,
|
||||
config_validation as cv,
|
||||
entity_registry,
|
||||
service,
|
||||
)
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
@ -303,6 +316,17 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType):
|
|||
|
||||
hass.bus.async_listen(EVENT_USER_REMOVED, _handle_user_removed)
|
||||
|
||||
async def async_reload_yaml(call: ServiceCall):
|
||||
"""Reload YAML."""
|
||||
conf = await entity_component.async_prepare_reload(skip_reset=True)
|
||||
if conf is None:
|
||||
return
|
||||
await yaml_collection.async_load(await filter_yaml_data(hass, conf[DOMAIN]))
|
||||
|
||||
service.async_register_admin_service(
|
||||
hass, DOMAIN, SERVICE_RELOAD, async_reload_yaml
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
|
2
homeassistant/components/person/services.yaml
Normal file
2
homeassistant/components/person/services.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
reload:
|
||||
description: Reload the person configuration.
|
|
@ -115,16 +115,27 @@ class YamlCollection(ObservableCollection):
|
|||
"""Offer a fake CRUD interface on top of static YAML."""
|
||||
|
||||
async def async_load(self, data: List[dict]) -> None:
|
||||
"""Load the storage Manager."""
|
||||
"""Load the YAML collection. Overrides existing data."""
|
||||
old_ids = set(self.data)
|
||||
|
||||
for item in data:
|
||||
item_id = item[CONF_ID]
|
||||
|
||||
if self.id_manager.has_id(item_id):
|
||||
if item_id in old_ids:
|
||||
old_ids.remove(item_id)
|
||||
event = CHANGE_UPDATED
|
||||
elif self.id_manager.has_id(item_id):
|
||||
self.logger.warning("Duplicate ID '%s' detected, skipping", item_id)
|
||||
continue
|
||||
else:
|
||||
event = CHANGE_ADDED
|
||||
|
||||
self.data[item_id] = item
|
||||
await self.notify_change(CHANGE_ADDED, item[CONF_ID], item)
|
||||
await self.notify_change(event, item[CONF_ID], item)
|
||||
|
||||
for item_id in old_ids:
|
||||
self.data.pop(item_id)
|
||||
await self.notify_change(CHANGE_REMOVED, item_id, None)
|
||||
|
||||
|
||||
class StorageCollection(ObservableCollection):
|
||||
|
|
|
@ -290,7 +290,7 @@ class EntityComponent:
|
|||
if entity_id in platform.entities:
|
||||
await platform.async_remove_entity(entity_id)
|
||||
|
||||
async def async_prepare_reload(self):
|
||||
async def async_prepare_reload(self, *, skip_reset=False):
|
||||
"""Prepare reloading this entity component.
|
||||
|
||||
This method must be run in the event loop.
|
||||
|
@ -310,7 +310,8 @@ class EntityComponent:
|
|||
if conf is None:
|
||||
return None
|
||||
|
||||
await self._async_reset()
|
||||
if not skip_reset:
|
||||
await self._async_reset()
|
||||
return conf
|
||||
|
||||
def _async_init_entity_platform(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""The tests for the person component."""
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -16,9 +17,10 @@ from homeassistant.const import (
|
|||
ATTR_LATITUDE,
|
||||
ATTR_LONGITUDE,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
SERVICE_RELOAD,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import CoreState, State
|
||||
from homeassistant.core import Context, CoreState, State
|
||||
from homeassistant.helpers import collection, entity_registry
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
|
@ -703,3 +705,59 @@ async def test_add_user_device_tracker(hass, storage_setup, hass_read_only_user)
|
|||
"device_tracker.on_create",
|
||||
"device_tracker.added",
|
||||
]
|
||||
|
||||
|
||||
async def test_reload(hass, hass_admin_user):
|
||||
"""Test reloading the YAML config."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
DOMAIN,
|
||||
{
|
||||
DOMAIN: [
|
||||
{"name": "Person 1", "id": "id-1"},
|
||||
{"name": "Person 2", "id": "id-2"},
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
|
||||
state_1 = hass.states.get("person.person_1")
|
||||
state_2 = hass.states.get("person.person_2")
|
||||
state_3 = hass.states.get("person.person_3")
|
||||
|
||||
assert state_1 is not None
|
||||
assert state_1.name == "Person 1"
|
||||
assert state_2 is not None
|
||||
assert state_2.name == "Person 2"
|
||||
assert state_3 is None
|
||||
|
||||
with patch(
|
||||
"homeassistant.config.load_yaml_config_file",
|
||||
autospec=True,
|
||||
return_value={
|
||||
DOMAIN: [
|
||||
{"name": "Person 1-updated", "id": "id-1"},
|
||||
{"name": "Person 3", "id": "id-3"},
|
||||
]
|
||||
},
|
||||
), patch("homeassistant.config.find_config_file", return_value=""):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_RELOAD,
|
||||
blocking=True,
|
||||
context=Context(user_id=hass_admin_user.id),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
|
||||
state_1 = hass.states.get("person.person_1")
|
||||
state_2 = hass.states.get("person.person_2")
|
||||
state_3 = hass.states.get("person.person_3")
|
||||
|
||||
assert state_1 is not None
|
||||
assert state_1.name == "Person 1-updated"
|
||||
assert state_2 is None
|
||||
assert state_3 is not None
|
||||
assert state_3.name == "Person 3"
|
||||
|
|
|
@ -118,6 +118,23 @@ async def test_yaml_collection():
|
|||
{"id": "mock-2", "name": "Mock 2"},
|
||||
)
|
||||
|
||||
# Test loading new data. Mock 1 is updated, 2 removed, 3 added.
|
||||
await coll.async_load(
|
||||
[{"id": "mock-1", "name": "Mock 1-updated"}, {"id": "mock-3", "name": "Mock 3"}]
|
||||
)
|
||||
assert len(changes) == 5
|
||||
assert changes[2] == (
|
||||
collection.CHANGE_UPDATED,
|
||||
"mock-1",
|
||||
{"id": "mock-1", "name": "Mock 1-updated"},
|
||||
)
|
||||
assert changes[3] == (
|
||||
collection.CHANGE_ADDED,
|
||||
"mock-3",
|
||||
{"id": "mock-3", "name": "Mock 3"},
|
||||
)
|
||||
assert changes[4] == (collection.CHANGE_REMOVED, "mock-2", None,)
|
||||
|
||||
|
||||
async def test_yaml_collection_skipping_duplicate_ids():
|
||||
"""Test YAML collection skipping duplicate IDs."""
|
||||
|
|
Loading…
Add table
Reference in a new issue