Add as_dict cache to Context and Event (#92162)

pull/92209/head
J. Nick Koston 2023-04-28 21:15:39 +02:00 committed by GitHub
parent 67a7de1869
commit 07d1a16efd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 17 deletions

View File

@ -91,7 +91,7 @@ async def async_attach_trigger(
if event_data_schema:
event_data_schema(event.data)
if event_context_schema:
event_context_schema(event.context.as_dict())
event_context_schema(dict(event.context.as_dict()))
except vol.Invalid:
# If event doesn't match, skip event
return False

View File

@ -850,7 +850,7 @@ class HomeAssistant:
class Context:
"""The context that triggered something."""
__slots__ = ("user_id", "parent_id", "id", "origin_event")
__slots__ = ("user_id", "parent_id", "id", "origin_event", "_as_dict")
def __init__(
self,
@ -863,14 +863,23 @@ class Context:
self.user_id = user_id
self.parent_id = parent_id
self.origin_event: Event | None = None
self._as_dict: ReadOnlyDict[str, str | None] | None = None
def __eq__(self, other: Any) -> bool:
"""Compare contexts."""
return bool(self.__class__ == other.__class__ and self.id == other.id)
def as_dict(self) -> dict[str, str | None]:
def as_dict(self) -> ReadOnlyDict[str, str | None]:
"""Return a dictionary representation of the context."""
return {"id": self.id, "parent_id": self.parent_id, "user_id": self.user_id}
if not self._as_dict:
self._as_dict = ReadOnlyDict(
{
"id": self.id,
"parent_id": self.parent_id,
"user_id": self.user_id,
}
)
return self._as_dict
class EventOrigin(enum.Enum):
@ -887,7 +896,7 @@ class EventOrigin(enum.Enum):
class Event:
"""Representation of an event within the bus."""
__slots__ = ["event_type", "data", "origin", "time_fired", "context"]
__slots__ = ("event_type", "data", "origin", "time_fired", "context", "_as_dict")
def __init__(
self,
@ -905,19 +914,24 @@ class Event:
self.context: Context = context or Context(
id=ulid_util.ulid_at_time(dt_util.utc_to_timestamp(self.time_fired))
)
self._as_dict: ReadOnlyDict[str, Any] | None = None
def as_dict(self) -> dict[str, Any]:
def as_dict(self) -> ReadOnlyDict[str, Any]:
"""Create a dict representation of this Event.
Async friendly.
"""
return {
"event_type": self.event_type,
"data": dict(self.data),
"origin": str(self.origin.value),
"time_fired": self.time_fired.isoformat(),
"context": self.context.as_dict(),
}
if not self._as_dict:
self._as_dict = ReadOnlyDict(
{
"event_type": self.event_type,
"data": ReadOnlyDict(self.data),
"origin": str(self.origin.value),
"time_fired": self.time_fired.isoformat(),
"context": self.context.as_dict(),
}
)
return self._as_dict
def __repr__(self) -> str:
"""Return the representation."""
@ -1189,7 +1203,7 @@ class State:
object_id: Object id of this state.
"""
__slots__ = [
__slots__ = (
"entity_id",
"state",
"attributes",
@ -1200,7 +1214,7 @@ class State:
"object_id",
"_as_dict",
"_as_compressed_state",
]
)
def __init__(
self,
@ -1265,7 +1279,7 @@ class State:
"attributes": self.attributes,
"last_changed": last_changed_isoformat,
"last_updated": last_updated_isoformat,
"context": ReadOnlyDict(self.context.as_dict()),
"context": self.context.as_dict(),
}
)
return self._as_dict

View File

@ -256,7 +256,9 @@ async def test_event_to_db_model() -> None:
assert native.as_dict() == event.as_dict()
native = Events.from_event(event).to_native()
event.data = {}
native.data = (
event.data
) # data is not set by from_event as its in the event_data table
native.event_type = event.event_type
assert native.as_dict() == event.as_dict()