mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Restore __slots__ to registry entries (#127481)
This commit is contained in:
parent
c104e66964
commit
24fbc366a6
@ -104,8 +104,12 @@ async def async_get_config_entry_diagnostics(
|
|||||||
if state := hass.states.get(entity.entity_id):
|
if state := hass.states.get(entity.entity_id):
|
||||||
state_dict = dict(state.as_dict())
|
state_dict = dict(state.as_dict())
|
||||||
state_dict.pop("context", None)
|
state_dict.pop("context", None)
|
||||||
entities.append({"entity": asdict(entity), "state": state_dict})
|
entity_dict = asdict(entity)
|
||||||
device_entities.append({"device": asdict(device), "entities": entities})
|
entity_dict.pop("_cache", None)
|
||||||
|
entities.append({"entity": entity_dict, "state": state_dict})
|
||||||
|
device_dict = asdict(device)
|
||||||
|
device_dict.pop("_cache", None)
|
||||||
|
device_entities.append({"device": device_dict, "entities": entities})
|
||||||
|
|
||||||
# remove envoy serial
|
# remove envoy serial
|
||||||
old_serial = coordinator.envoy_serial_number
|
old_serial = coordinator.envoy_serial_number
|
||||||
|
@ -7,9 +7,7 @@ from collections.abc import Iterable
|
|||||||
import dataclasses
|
import dataclasses
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Literal, TypedDict
|
from typing import TYPE_CHECKING, Any, Literal, TypedDict
|
||||||
|
|
||||||
from propcache import cached_property
|
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.util.dt import utc_from_timestamp, utcnow
|
from homeassistant.util.dt import utc_from_timestamp, utcnow
|
||||||
@ -27,6 +25,13 @@ from .singleton import singleton
|
|||||||
from .storage import Store
|
from .storage import Store
|
||||||
from .typing import UNDEFINED, UndefinedType
|
from .typing import UNDEFINED, UndefinedType
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
# mypy cannot workout _cache Protocol with dataclasses
|
||||||
|
from propcache import cached_property as under_cached_property
|
||||||
|
else:
|
||||||
|
from propcache import under_cached_property
|
||||||
|
|
||||||
|
|
||||||
DATA_REGISTRY: HassKey[AreaRegistry] = HassKey("area_registry")
|
DATA_REGISTRY: HassKey[AreaRegistry] = HassKey("area_registry")
|
||||||
EVENT_AREA_REGISTRY_UPDATED: EventType[EventAreaRegistryUpdatedData] = EventType(
|
EVENT_AREA_REGISTRY_UPDATED: EventType[EventAreaRegistryUpdatedData] = EventType(
|
||||||
"area_registry_updated"
|
"area_registry_updated"
|
||||||
@ -63,7 +68,7 @@ class EventAreaRegistryUpdatedData(TypedDict):
|
|||||||
area_id: str
|
area_id: str
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True, slots=True)
|
||||||
class AreaEntry(NormalizedNameBaseRegistryEntry):
|
class AreaEntry(NormalizedNameBaseRegistryEntry):
|
||||||
"""Area Registry Entry."""
|
"""Area Registry Entry."""
|
||||||
|
|
||||||
@ -73,8 +78,9 @@ class AreaEntry(NormalizedNameBaseRegistryEntry):
|
|||||||
id: str
|
id: str
|
||||||
labels: set[str] = field(default_factory=set)
|
labels: set[str] = field(default_factory=set)
|
||||||
picture: str | None
|
picture: str | None
|
||||||
|
_cache: dict[str, Any] = field(default_factory=dict, compare=False, init=False)
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def json_fragment(self) -> json_fragment:
|
def json_fragment(self) -> json_fragment:
|
||||||
"""Return a JSON representation of this AreaEntry."""
|
"""Return a JSON representation of this AreaEntry."""
|
||||||
return json_fragment(
|
return json_fragment(
|
||||||
|
@ -12,7 +12,6 @@ import time
|
|||||||
from typing import TYPE_CHECKING, Any, Literal, TypedDict
|
from typing import TYPE_CHECKING, Any, Literal, TypedDict
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from propcache import cached_property
|
|
||||||
from yarl import URL
|
from yarl import URL
|
||||||
|
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
|
||||||
@ -46,9 +45,14 @@ from .singleton import singleton
|
|||||||
from .typing import UNDEFINED, UndefinedType
|
from .typing import UNDEFINED, UndefinedType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
# mypy cannot workout _cache Protocol with attrs
|
||||||
|
from propcache import cached_property as under_cached_property
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
|
||||||
from . import entity_registry
|
from . import entity_registry
|
||||||
|
else:
|
||||||
|
from propcache import under_cached_property
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -278,7 +282,7 @@ def _validate_configuration_url(value: Any) -> str | None:
|
|||||||
return url_as_str
|
return url_as_str
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True, slots=True)
|
||||||
class DeviceEntry:
|
class DeviceEntry:
|
||||||
"""Device Registry Entry."""
|
"""Device Registry Entry."""
|
||||||
|
|
||||||
@ -306,6 +310,7 @@ class DeviceEntry:
|
|||||||
via_device_id: str | None = attr.ib(default=None)
|
via_device_id: str | None = attr.ib(default=None)
|
||||||
# This value is not stored, just used to keep track of events to fire.
|
# This value is not stored, just used to keep track of events to fire.
|
||||||
is_new: bool = attr.ib(default=False)
|
is_new: bool = attr.ib(default=False)
|
||||||
|
_cache: dict[str, Any] = attr.ib(factory=dict, eq=False, init=False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def disabled(self) -> bool:
|
def disabled(self) -> bool:
|
||||||
@ -342,7 +347,7 @@ class DeviceEntry:
|
|||||||
"via_device_id": self.via_device_id,
|
"via_device_id": self.via_device_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def json_repr(self) -> bytes | None:
|
def json_repr(self) -> bytes | None:
|
||||||
"""Return a cached JSON representation of the entry."""
|
"""Return a cached JSON representation of the entry."""
|
||||||
try:
|
try:
|
||||||
@ -358,7 +363,7 @@ class DeviceEntry:
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def as_storage_fragment(self) -> json_fragment:
|
def as_storage_fragment(self) -> json_fragment:
|
||||||
"""Return a json fragment for storage."""
|
"""Return a json fragment for storage."""
|
||||||
return json_fragment(
|
return json_fragment(
|
||||||
@ -390,7 +395,7 @@ class DeviceEntry:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True, slots=True)
|
||||||
class DeletedDeviceEntry:
|
class DeletedDeviceEntry:
|
||||||
"""Deleted Device Registry Entry."""
|
"""Deleted Device Registry Entry."""
|
||||||
|
|
||||||
@ -401,6 +406,7 @@ class DeletedDeviceEntry:
|
|||||||
orphaned_timestamp: float | None = attr.ib()
|
orphaned_timestamp: float | None = attr.ib()
|
||||||
created_at: datetime = attr.ib(factory=utcnow)
|
created_at: datetime = attr.ib(factory=utcnow)
|
||||||
modified_at: datetime = attr.ib(factory=utcnow)
|
modified_at: datetime = attr.ib(factory=utcnow)
|
||||||
|
_cache: dict[str, Any] = attr.ib(factory=dict, eq=False, init=False)
|
||||||
|
|
||||||
def to_device_entry(
|
def to_device_entry(
|
||||||
self,
|
self,
|
||||||
@ -419,7 +425,7 @@ class DeletedDeviceEntry:
|
|||||||
is_new=True,
|
is_new=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def as_storage_fragment(self) -> json_fragment:
|
def as_storage_fragment(self) -> json_fragment:
|
||||||
"""Return a json fragment for storage."""
|
"""Return a json fragment for storage."""
|
||||||
return json_fragment(
|
return json_fragment(
|
||||||
|
@ -19,7 +19,6 @@ import time
|
|||||||
from typing import TYPE_CHECKING, Any, Literal, NotRequired, TypedDict
|
from typing import TYPE_CHECKING, Any, Literal, NotRequired, TypedDict
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from propcache import cached_property
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -65,7 +64,12 @@ from .singleton import singleton
|
|||||||
from .typing import UNDEFINED, UndefinedType
|
from .typing import UNDEFINED, UndefinedType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
# mypy cannot workout _cache Protocol with attrs
|
||||||
|
from propcache import cached_property as under_cached_property
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
else:
|
||||||
|
from propcache import under_cached_property
|
||||||
|
|
||||||
DATA_REGISTRY: HassKey[EntityRegistry] = HassKey("entity_registry")
|
DATA_REGISTRY: HassKey[EntityRegistry] = HassKey("entity_registry")
|
||||||
EVENT_ENTITY_REGISTRY_UPDATED: EventType[EventEntityRegistryUpdatedData] = EventType(
|
EVENT_ENTITY_REGISTRY_UPDATED: EventType[EventEntityRegistryUpdatedData] = EventType(
|
||||||
@ -162,7 +166,7 @@ def _protect_entity_options(
|
|||||||
return ReadOnlyDict({key: ReadOnlyDict(val) for key, val in data.items()})
|
return ReadOnlyDict({key: ReadOnlyDict(val) for key, val in data.items()})
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True, slots=True)
|
||||||
class RegistryEntry:
|
class RegistryEntry:
|
||||||
"""Entity Registry Entry."""
|
"""Entity Registry Entry."""
|
||||||
|
|
||||||
@ -201,6 +205,7 @@ class RegistryEntry:
|
|||||||
supported_features: int = attr.ib(default=0)
|
supported_features: int = attr.ib(default=0)
|
||||||
translation_key: str | None = attr.ib(default=None)
|
translation_key: str | None = attr.ib(default=None)
|
||||||
unit_of_measurement: str | None = attr.ib(default=None)
|
unit_of_measurement: str | None = attr.ib(default=None)
|
||||||
|
_cache: dict[str, Any] = attr.ib(factory=dict, eq=False, init=False)
|
||||||
|
|
||||||
@domain.default
|
@domain.default
|
||||||
def _domain_default(self) -> str:
|
def _domain_default(self) -> str:
|
||||||
@ -247,7 +252,7 @@ class RegistryEntry:
|
|||||||
display_dict["dp"] = precision
|
display_dict["dp"] = precision
|
||||||
return display_dict
|
return display_dict
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def display_json_repr(self) -> bytes | None:
|
def display_json_repr(self) -> bytes | None:
|
||||||
"""Return a cached partial JSON representation of the entry.
|
"""Return a cached partial JSON representation of the entry.
|
||||||
|
|
||||||
@ -267,7 +272,7 @@ class RegistryEntry:
|
|||||||
return None
|
return None
|
||||||
return json_repr
|
return json_repr
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def as_partial_dict(self) -> dict[str, Any]:
|
def as_partial_dict(self) -> dict[str, Any]:
|
||||||
"""Return a partial dict representation of the entry."""
|
"""Return a partial dict representation of the entry."""
|
||||||
# Convert sets and tuples to lists
|
# Convert sets and tuples to lists
|
||||||
@ -296,7 +301,7 @@ class RegistryEntry:
|
|||||||
"unique_id": self.unique_id,
|
"unique_id": self.unique_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def extended_dict(self) -> dict[str, Any]:
|
def extended_dict(self) -> dict[str, Any]:
|
||||||
"""Return a extended dict representation of the entry."""
|
"""Return a extended dict representation of the entry."""
|
||||||
# Convert sets and tuples to lists
|
# Convert sets and tuples to lists
|
||||||
@ -311,7 +316,7 @@ class RegistryEntry:
|
|||||||
"original_icon": self.original_icon,
|
"original_icon": self.original_icon,
|
||||||
}
|
}
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def partial_json_repr(self) -> bytes | None:
|
def partial_json_repr(self) -> bytes | None:
|
||||||
"""Return a cached partial JSON representation of the entry."""
|
"""Return a cached partial JSON representation of the entry."""
|
||||||
try:
|
try:
|
||||||
@ -327,7 +332,7 @@ class RegistryEntry:
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def as_storage_fragment(self) -> json_fragment:
|
def as_storage_fragment(self) -> json_fragment:
|
||||||
"""Return a json fragment for storage."""
|
"""Return a json fragment for storage."""
|
||||||
return json_fragment(
|
return json_fragment(
|
||||||
@ -394,7 +399,7 @@ class RegistryEntry:
|
|||||||
hass.states.async_set(self.entity_id, STATE_UNAVAILABLE, attrs)
|
hass.states.async_set(self.entity_id, STATE_UNAVAILABLE, attrs)
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True, slots=True)
|
||||||
class DeletedRegistryEntry:
|
class DeletedRegistryEntry:
|
||||||
"""Deleted Entity Registry Entry."""
|
"""Deleted Entity Registry Entry."""
|
||||||
|
|
||||||
@ -407,13 +412,14 @@ class DeletedRegistryEntry:
|
|||||||
orphaned_timestamp: float | None = attr.ib()
|
orphaned_timestamp: float | None = attr.ib()
|
||||||
created_at: datetime = attr.ib(factory=utcnow)
|
created_at: datetime = attr.ib(factory=utcnow)
|
||||||
modified_at: datetime = attr.ib(factory=utcnow)
|
modified_at: datetime = attr.ib(factory=utcnow)
|
||||||
|
_cache: dict[str, Any] = attr.ib(factory=dict, eq=False, init=False)
|
||||||
|
|
||||||
@domain.default
|
@domain.default
|
||||||
def _domain_default(self) -> str:
|
def _domain_default(self) -> str:
|
||||||
"""Compute domain value."""
|
"""Compute domain value."""
|
||||||
return split_entity_id(self.entity_id)[0]
|
return split_entity_id(self.entity_id)[0]
|
||||||
|
|
||||||
@cached_property
|
@under_cached_property
|
||||||
def as_storage_fragment(self) -> json_fragment:
|
def as_storage_fragment(self) -> json_fragment:
|
||||||
"""Return a json fragment for storage."""
|
"""Return a json fragment for storage."""
|
||||||
return json_fragment(
|
return json_fragment(
|
||||||
|
@ -27,7 +27,7 @@ from tests.common import MockConfigEntry, MockModule, mock_integration, mock_pla
|
|||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True, slots=True)
|
||||||
class MockDeviceEntry(dr.DeviceEntry):
|
class MockDeviceEntry(dr.DeviceEntry):
|
||||||
"""Device Registry Entry with fixed UUID."""
|
"""Device Registry Entry with fixed UUID."""
|
||||||
|
|
||||||
|
@ -289,6 +289,7 @@ async def test_snapshots(
|
|||||||
entry.pop("device_id", None)
|
entry.pop("device_id", None)
|
||||||
entry.pop("created_at", None)
|
entry.pop("created_at", None)
|
||||||
entry.pop("modified_at", None)
|
entry.pop("modified_at", None)
|
||||||
|
entry.pop("_cache", None)
|
||||||
|
|
||||||
entities.append({"entry": entry, "state": state_dict})
|
entities.append({"entry": entry, "state": state_dict})
|
||||||
|
|
||||||
@ -297,6 +298,8 @@ async def test_snapshots(
|
|||||||
device_dict.pop("via_device_id", None)
|
device_dict.pop("via_device_id", None)
|
||||||
device_dict.pop("created_at", None)
|
device_dict.pop("created_at", None)
|
||||||
device_dict.pop("modified_at", None)
|
device_dict.pop("modified_at", None)
|
||||||
|
device_dict.pop("_cache", None)
|
||||||
|
|
||||||
devices.append({"device": device_dict, "entities": entities})
|
devices.append({"device": device_dict, "entities": entities})
|
||||||
|
|
||||||
assert snapshot == devices
|
assert snapshot == devices
|
||||||
|
@ -132,6 +132,7 @@ class HomeAssistantSnapshotSerializer(AmberDataSerializer):
|
|||||||
"""Prepare a Home Assistant area registry entry for serialization."""
|
"""Prepare a Home Assistant area registry entry for serialization."""
|
||||||
serialized = AreaRegistryEntrySnapshot(dataclasses.asdict(data) | {"id": ANY})
|
serialized = AreaRegistryEntrySnapshot(dataclasses.asdict(data) | {"id": ANY})
|
||||||
serialized.pop("_json_repr")
|
serialized.pop("_json_repr")
|
||||||
|
serialized.pop("_cache")
|
||||||
return serialized
|
return serialized
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -156,6 +157,7 @@ class HomeAssistantSnapshotSerializer(AmberDataSerializer):
|
|||||||
serialized["via_device_id"] = ANY
|
serialized["via_device_id"] = ANY
|
||||||
if serialized["primary_config_entry"] is not None:
|
if serialized["primary_config_entry"] is not None:
|
||||||
serialized["primary_config_entry"] = ANY
|
serialized["primary_config_entry"] = ANY
|
||||||
|
serialized.pop("_cache")
|
||||||
return cls._remove_created_and_modified_at(serialized)
|
return cls._remove_created_and_modified_at(serialized)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -182,6 +184,7 @@ class HomeAssistantSnapshotSerializer(AmberDataSerializer):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
serialized.pop("categories")
|
serialized.pop("categories")
|
||||||
|
serialized.pop("_cache")
|
||||||
return cls._remove_created_and_modified_at(serialized)
|
return cls._remove_created_and_modified_at(serialized)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
Loading…
x
Reference in New Issue
Block a user