From 69710cb6647b65308697453545ac8e07f60558b5 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 1 Dec 2020 12:45:56 +0100 Subject: [PATCH] Base area IDs on initial name (#43804) --- homeassistant/helpers/area_registry.py | 30 ++++++++++++++++---------- tests/helpers/test_area_registry.py | 12 +++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/homeassistant/helpers/area_registry.py b/homeassistant/helpers/area_registry.py index b8f7952cd5a..1a919996f86 100644 --- a/homeassistant/helpers/area_registry.py +++ b/homeassistant/helpers/area_registry.py @@ -1,13 +1,13 @@ """Provide a way to connect devices to one physical location.""" from asyncio import Event, gather from collections import OrderedDict -from typing import Dict, Iterable, List, MutableMapping, Optional, cast +from typing import Container, Dict, Iterable, List, MutableMapping, Optional, cast import attr from homeassistant.core import callback from homeassistant.loader import bind_hass -import homeassistant.util.uuid as uuid_util +from homeassistant.util import slugify from .typing import HomeAssistantType @@ -22,8 +22,17 @@ SAVE_DELAY = 10 class AreaEntry: """Area Registry Entry.""" - name: Optional[str] = attr.ib(default=None) - id: str = attr.ib(factory=uuid_util.random_uuid_hex) + name: str = attr.ib() + id: Optional[str] = attr.ib(default=None) + + def generate_id(self, existing_ids: Container) -> None: + """Initialize ID.""" + suggestion = suggestion_base = slugify(self.name) + tries = 1 + while suggestion in existing_ids: + tries += 1 + suggestion = f"{suggestion_base}_{tries}" + object.__setattr__(self, "id", suggestion) class AreaRegistry: @@ -51,16 +60,15 @@ class AreaRegistry: if self._async_is_registered(name): raise ValueError("Name is already in use") - area = AreaEntry() + area = AreaEntry(name=name) + area.generate_id(self.areas) + assert area.id is not None self.areas[area.id] = area - - created = self._async_update(area.id, name=name) - + self.async_schedule_save() self.hass.bus.async_fire( - EVENT_AREA_REGISTRY_UPDATED, {"action": "create", "area_id": created.id} + EVENT_AREA_REGISTRY_UPDATED, {"action": "create", "area_id": area.id} ) - - return created + return area async def async_delete(self, area_id: str) -> None: """Delete area.""" diff --git a/tests/helpers/test_area_registry.py b/tests/helpers/test_area_registry.py index f6a75fe3c30..4b6ca7da3fe 100644 --- a/tests/helpers/test_area_registry.py +++ b/tests/helpers/test_area_registry.py @@ -43,6 +43,7 @@ async def test_create_area(hass, registry, update_events): """Make sure that we can create an area.""" area = registry.async_create("mock") + assert area.id == "mock" assert area.name == "mock" assert len(registry.areas) == 1 @@ -68,6 +69,17 @@ async def test_create_area_with_name_already_in_use(hass, registry, update_event assert len(update_events) == 1 +async def test_create_area_with_id_already_in_use(registry): + """Make sure that we can't create an area with a name already in use.""" + area1 = registry.async_create("mock") + + updated_area1 = registry.async_update(area1.id, "New Name") + assert updated_area1.id == area1.id + + area2 = registry.async_create("mock") + assert area2.id == "mock_2" + + async def test_delete_area(hass, registry, update_events): """Make sure that we can delete an area.""" area = registry.async_create("mock")