mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Remove assumption in ConfigEntryItems about unique unique_id (#127399)
This commit is contained in:
parent
80582a128a
commit
48a07d531c
@ -1600,7 +1600,7 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._domain_index: dict[str, list[ConfigEntry]] = {}
|
self._domain_index: dict[str, list[ConfigEntry]] = {}
|
||||||
self._domain_unique_id_index: dict[str, dict[str, ConfigEntry]] = {}
|
self._domain_unique_id_index: dict[str, dict[str, list[ConfigEntry]]] = {}
|
||||||
|
|
||||||
def values(self) -> ValuesView[ConfigEntry]:
|
def values(self) -> ValuesView[ConfigEntry]:
|
||||||
"""Return the underlying values to avoid __iter__ overhead."""
|
"""Return the underlying values to avoid __iter__ overhead."""
|
||||||
@ -1643,9 +1643,9 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
report_issue,
|
report_issue,
|
||||||
)
|
)
|
||||||
|
|
||||||
self._domain_unique_id_index.setdefault(entry.domain, {})[
|
self._domain_unique_id_index.setdefault(entry.domain, {}).setdefault(
|
||||||
unique_id_hash
|
unique_id_hash, []
|
||||||
] = entry
|
).append(entry)
|
||||||
|
|
||||||
def _unindex_entry(self, entry_id: str) -> None:
|
def _unindex_entry(self, entry_id: str) -> None:
|
||||||
"""Unindex an entry."""
|
"""Unindex an entry."""
|
||||||
@ -1658,7 +1658,9 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
# Check type first to avoid expensive isinstance call
|
# Check type first to avoid expensive isinstance call
|
||||||
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
||||||
unique_id = str(entry.unique_id) # type: ignore[unreachable]
|
unique_id = str(entry.unique_id) # type: ignore[unreachable]
|
||||||
del self._domain_unique_id_index[domain][unique_id]
|
self._domain_unique_id_index[domain][unique_id].remove(entry)
|
||||||
|
if not self._domain_unique_id_index[domain][unique_id]:
|
||||||
|
del self._domain_unique_id_index[domain][unique_id]
|
||||||
if not self._domain_unique_id_index[domain]:
|
if not self._domain_unique_id_index[domain]:
|
||||||
del self._domain_unique_id_index[domain]
|
del self._domain_unique_id_index[domain]
|
||||||
|
|
||||||
@ -1690,7 +1692,10 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
# Check type first to avoid expensive isinstance call
|
# Check type first to avoid expensive isinstance call
|
||||||
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
||||||
unique_id = str(unique_id) # type: ignore[unreachable]
|
unique_id = str(unique_id) # type: ignore[unreachable]
|
||||||
return self._domain_unique_id_index.get(domain, {}).get(unique_id)
|
entries = self._domain_unique_id_index.get(domain, {}).get(unique_id)
|
||||||
|
if not entries:
|
||||||
|
return None
|
||||||
|
return entries[0]
|
||||||
|
|
||||||
|
|
||||||
class ConfigEntryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
|
class ConfigEntryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
|
||||||
|
@ -513,6 +513,41 @@ async def test_remove_entry(
|
|||||||
assert not entity_entry_list
|
assert not entity_entry_list
|
||||||
|
|
||||||
|
|
||||||
|
async def test_remove_entry_non_unique_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
manager: config_entries.ConfigEntries,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test that we can remove entry with colliding unique_id."""
|
||||||
|
entry_1 = MockConfigEntry(
|
||||||
|
domain="test_other", entry_id="test1", unique_id="not_unique"
|
||||||
|
)
|
||||||
|
entry_1.add_to_manager(manager)
|
||||||
|
entry_2 = MockConfigEntry(
|
||||||
|
domain="test_other", entry_id="test2", unique_id="not_unique"
|
||||||
|
)
|
||||||
|
entry_2.add_to_manager(manager)
|
||||||
|
entry_3 = MockConfigEntry(
|
||||||
|
domain="test_other", entry_id="test3", unique_id="not_unique"
|
||||||
|
)
|
||||||
|
entry_3.add_to_manager(manager)
|
||||||
|
|
||||||
|
# Check all config entries exist
|
||||||
|
assert manager.async_entry_ids() == [
|
||||||
|
"test1",
|
||||||
|
"test2",
|
||||||
|
"test3",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Remove entries
|
||||||
|
assert await manager.async_remove("test1") == {"require_restart": False}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert await manager.async_remove("test2") == {"require_restart": False}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert await manager.async_remove("test3") == {"require_restart": False}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
async def test_remove_entry_cancels_reauth(
|
async def test_remove_entry_cancels_reauth(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
manager: config_entries.ConfigEntries,
|
manager: config_entries.ConfigEntries,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user