Device and entity registry remove config entry on unload (#16247)

* Test

* Ability to remove device

* Don't remove devices, instead remove config entry from device and entity registries

* Remove print

* Remove is not the same as unload

* Add tests

* Fix hound comment
This commit is contained in:
Robert Svensson 2018-09-04 09:00:14 +02:00 committed by Paulus Schoutsen
parent 7ea482cb1d
commit 7a6facc875
5 changed files with 62 additions and 2 deletions

View File

@ -325,6 +325,14 @@ class ConfigEntries:
unloaded = await entry.async_unload(self.hass)
device_registry = await \
self.hass.helpers.device_registry.async_get_registry()
device_registry.async_clear_config_entry(entry_id)
entity_registry = await \
self.hass.helpers.entity_registry.async_get_registry()
entity_registry.async_clear_config_entry(entry_id)
return {
'require_restart': not unloaded
}

View File

@ -45,7 +45,7 @@ class DeviceRegistry:
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
@callback
def async_get_device(self, identifiers: str, connections: tuple):
def async_get_device(self, identifiers: set, connections: set):
"""Check if device is registered."""
for device in self.devices.values():
if any(iden in device.identifiers for iden in identifiers) or \
@ -127,6 +127,14 @@ class DeviceRegistry:
return data
@callback
def async_clear_config_entry(self, config_entry):
"""Clear config entry from registry entries."""
for device in self.devices.values():
if config_entry in device.config_entries:
device.config_entries.remove(config_entry)
self.async_schedule_save()
@bind_hass
async def async_get_registry(hass) -> DeviceRegistry:

View File

@ -31,7 +31,7 @@ STORAGE_VERSION = 1
STORAGE_KEY = 'core.entity_registry'
@attr.s(slots=True, frozen=True)
@attr.s(slots=True)
class RegistryEntry:
"""Entity Registry Entry."""
@ -250,6 +250,14 @@ class EntityRegistry:
return data
@callback
def async_clear_config_entry(self, config_entry):
"""Clear config entry from registry entries."""
for entry in self.entities.values():
if config_entry == entry.config_entry_id:
entry.config_entry_id = None
self.async_schedule_save()
@bind_hass
async def async_get_registry(hass) -> EntityRegistry:

View File

@ -138,3 +138,30 @@ async def test_loading_from_storage(hass, hass_storage):
manufacturer='manufacturer', model='model')
assert entry.id == 'abcdefghijklm'
assert isinstance(entry.config_entries, set)
async def test_removing_config_entries(registry):
"""Make sure we do not get duplicate entries."""
entry = registry.async_get_or_create(
config_entry='123',
connections={('ethernet', '12:34:56:78:90:AB:CD:EF')},
identifiers={('bridgeid', '0123')},
manufacturer='manufacturer', model='model')
entry2 = registry.async_get_or_create(
config_entry='456',
connections={('ethernet', '12:34:56:78:90:AB:CD:EF')},
identifiers={('bridgeid', '0123')},
manufacturer='manufacturer', model='model')
entry3 = registry.async_get_or_create(
config_entry='123',
connections={('ethernet', '34:56:78:90:AB:CD:EF:12')},
identifiers={('bridgeid', '4567')},
manufacturer='manufacturer', model='model')
assert len(registry.devices) == 2
assert entry is entry2
assert entry is not entry3
assert entry.config_entries == {'123', '456'}
registry.async_clear_config_entry('123')
assert entry.config_entries == {'456'}
assert entry3.config_entries == set()

View File

@ -186,6 +186,15 @@ async def test_updating_config_entry_id(registry):
assert entry2.config_entry_id == 'mock-id-2'
async def test_removing_config_entry_id(registry):
"""Test that we update config entry id in registry."""
entry = registry.async_get_or_create(
'light', 'hue', '5678', config_entry_id='mock-id-1')
assert entry.config_entry_id == 'mock-id-1'
registry.async_clear_config_entry('mock-id-1')
assert entry.config_entry_id is None
async def test_migration(hass):
"""Test migration from old data to new."""
old_conf = {