Add person reload service (#30493)

This commit is contained in:
Paulus Schoutsen 2020-01-05 11:16:37 +01:00 committed by GitHub
parent 35e19eec18
commit 30076d1843
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 121 additions and 8 deletions

View file

@ -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

View file

@ -0,0 +1,2 @@
reload:
description: Reload the person configuration.

View file

@ -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):

View file

@ -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(

View file

@ -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"

View file

@ -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."""