Skip to content

Commit

Permalink
Add as_dict cache to Context and Event (#92162)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco committed Apr 28, 2023
1 parent 67a7de1 commit 07d1a16
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/homeassistant/triggers/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def filter_event(event: Event) -> bool:
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
Expand Down
44 changes: 29 additions & 15 deletions homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ def _async_log_running_tasks(self, stage: int) -> None:
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,
Expand All @@ -863,14 +863,23 @@ def __init__(
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):
Expand All @@ -887,7 +896,7 @@ def __str__(self) -> str:
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,
Expand All @@ -905,19 +914,24 @@ def __init__(
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."""
Expand Down Expand Up @@ -1189,7 +1203,7 @@ class State:
object_id: Object id of this state.
"""

__slots__ = [
__slots__ = (
"entity_id",
"state",
"attributes",
Expand All @@ -1200,7 +1214,7 @@ class State:
"object_id",
"_as_dict",
"_as_compressed_state",
]
)

def __init__(
self,
Expand Down Expand Up @@ -1265,7 +1279,7 @@ def as_dict(self) -> ReadOnlyDict[str, Collection[Any]]:
"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
Expand Down
4 changes: 3 additions & 1 deletion tests/components/recorder/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down

0 comments on commit 07d1a16

Please sign in to comment.