Convert AreaEntry to dataclass (#108648)

* Convert AreaEntry to dataclass

* Correct typing of AreaEntry.id

* Move responsibility for generating area id to AreaRegistry
This commit is contained in:
Erik Montnemery 2024-01-22 14:45:27 +01:00 committed by GitHub
parent 8c31e67dbc
commit ef5d46c79c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,11 +2,10 @@
from __future__ import annotations from __future__ import annotations
from collections import OrderedDict from collections import OrderedDict
from collections.abc import Container, Iterable, MutableMapping from collections.abc import Iterable, MutableMapping
import dataclasses
from typing import Any, Literal, TypedDict, cast from typing import Any, Literal, TypedDict, cast
import attr
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.util import slugify from homeassistant.util import slugify
@ -29,26 +28,15 @@ class EventAreaRegistryUpdatedData(TypedDict):
area_id: str area_id: str
@attr.s(slots=True, frozen=True) @dataclasses.dataclass(frozen=True, kw_only=True, slots=True)
class AreaEntry: class AreaEntry:
"""Area Registry Entry.""" """Area Registry Entry."""
name: str = attr.ib() aliases: set[str]
normalized_name: str = attr.ib() id: str
aliases: set[str] = attr.ib( name: str
converter=attr.converters.default_if_none(factory=set) # type: ignore[misc] normalized_name: str
) picture: str | None
id: str | None = attr.ib(default=None)
picture: str | None = attr.ib(default=None)
def generate_id(self, existing_ids: Container[str]) -> 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 AreaRegistryStore(Store[dict[str, list[dict[str, Any]]]]): class AreaRegistryStore(Store[dict[str, list[dict[str, Any]]]]):
@ -133,10 +121,14 @@ class AreaRegistry:
if self.async_get_area_by_name(name): if self.async_get_area_by_name(name):
raise ValueError(f"The name {name} ({normalized_name}) is already in use") raise ValueError(f"The name {name} ({normalized_name}) is already in use")
area_id = self._generate_area_id(name)
area = AreaEntry( area = AreaEntry(
aliases=aliases, name=name, normalized_name=normalized_name, picture=picture aliases=aliases or set(),
id=area_id,
name=name,
normalized_name=normalized_name,
picture=picture,
) )
area.generate_id(self.areas)
assert area.id is not None assert area.id is not None
self.areas[area.id] = area self.areas[area.id] = area
self._normalized_name_area_idx[normalized_name] = area.id self._normalized_name_area_idx[normalized_name] = area.id
@ -221,7 +213,7 @@ class AreaRegistry:
if not new_values: if not new_values:
return old return old
new = self.areas[area_id] = attr.evolve(old, **new_values) # type: ignore[arg-type] new = self.areas[area_id] = dataclasses.replace(old, **new_values) # type: ignore[arg-type]
if normalized_name is not None: if normalized_name is not None:
self._normalized_name_area_idx[ self._normalized_name_area_idx[
normalized_name normalized_name
@ -273,6 +265,15 @@ class AreaRegistry:
return data return data
def _generate_area_id(self, name: str) -> str:
"""Generate area ID."""
suggestion = suggestion_base = slugify(name)
tries = 1
while suggestion in self.areas:
tries += 1
suggestion = f"{suggestion_base}_{tries}"
return suggestion
@callback @callback
def async_get(hass: HomeAssistant) -> AreaRegistry: def async_get(hass: HomeAssistant) -> AreaRegistry: