Convert States to dicts via as_dict only once (#41208)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
2f54bf29ba
commit
4798f37c6e
4 changed files with 63 additions and 20 deletions
|
@ -65,7 +65,7 @@ class Events(Base): # type: ignore
|
|||
return Events(
|
||||
event_type=event.event_type,
|
||||
event_data=event_data or json.dumps(event.data, cls=JSONEncoder),
|
||||
origin=str(event.origin),
|
||||
origin=str(event.origin.value),
|
||||
time_fired=event.time_fired,
|
||||
context_id=event.context.id,
|
||||
context_user_id=event.context.user_id,
|
||||
|
|
|
@ -21,6 +21,7 @@ from typing import (
|
|||
Any,
|
||||
Awaitable,
|
||||
Callable,
|
||||
Collection,
|
||||
Coroutine,
|
||||
Dict,
|
||||
Iterable,
|
||||
|
@ -561,8 +562,8 @@ class Event:
|
|||
return {
|
||||
"event_type": self.event_type,
|
||||
"data": dict(self.data),
|
||||
"origin": str(self.origin),
|
||||
"time_fired": self.time_fired,
|
||||
"origin": str(self.origin.value),
|
||||
"time_fired": self.time_fired.isoformat(),
|
||||
"context": self.context.as_dict(),
|
||||
}
|
||||
|
||||
|
@ -626,6 +627,7 @@ class EventBus:
|
|||
event_data: Optional[Dict] = None,
|
||||
origin: EventOrigin = EventOrigin.local,
|
||||
context: Optional[Context] = None,
|
||||
time_fired: Optional[datetime.datetime] = None,
|
||||
) -> None:
|
||||
"""Fire an event.
|
||||
|
||||
|
@ -638,7 +640,7 @@ class EventBus:
|
|||
if match_all_listeners is not None and event_type != EVENT_HOMEASSISTANT_CLOSE:
|
||||
listeners = match_all_listeners + listeners
|
||||
|
||||
event = Event(event_type, event_data, origin, None, context)
|
||||
event = Event(event_type, event_data, origin, time_fired, context)
|
||||
|
||||
if event_type != EVENT_TIME_CHANGED:
|
||||
_LOGGER.debug("Bus:Handling %s", event)
|
||||
|
@ -771,6 +773,7 @@ class State:
|
|||
"context",
|
||||
"domain",
|
||||
"object_id",
|
||||
"_as_dict",
|
||||
]
|
||||
|
||||
def __init__(
|
||||
|
@ -805,6 +808,7 @@ class State:
|
|||
self.last_changed = last_changed or self.last_updated
|
||||
self.context = context or Context()
|
||||
self.domain, self.object_id = split_entity_id(self.entity_id)
|
||||
self._as_dict: Optional[Dict[str, Collection[Any]]] = None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
@ -821,14 +825,21 @@ class State:
|
|||
To be used for JSON serialization.
|
||||
Ensures: state == State.from_dict(state.as_dict())
|
||||
"""
|
||||
return {
|
||||
"entity_id": self.entity_id,
|
||||
"state": self.state,
|
||||
"attributes": dict(self.attributes),
|
||||
"last_changed": self.last_changed,
|
||||
"last_updated": self.last_updated,
|
||||
"context": self.context.as_dict(),
|
||||
}
|
||||
if not self._as_dict:
|
||||
last_changed_isoformat = self.last_changed.isoformat()
|
||||
if self.last_changed == self.last_updated:
|
||||
last_updated_isoformat = last_changed_isoformat
|
||||
else:
|
||||
last_updated_isoformat = self.last_updated.isoformat()
|
||||
self._as_dict = {
|
||||
"entity_id": self.entity_id,
|
||||
"state": self.state,
|
||||
"attributes": dict(self.attributes),
|
||||
"last_changed": last_changed_isoformat,
|
||||
"last_updated": last_updated_isoformat,
|
||||
"context": self.context.as_dict(),
|
||||
}
|
||||
return self._as_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, json_dict: Dict) -> Any:
|
||||
|
@ -1643,13 +1654,18 @@ def _async_create_timer(hass: HomeAssistant) -> None:
|
|||
"""Fire next time event."""
|
||||
now = dt_util.utcnow()
|
||||
|
||||
hass.bus.async_fire(EVENT_TIME_CHANGED, {ATTR_NOW: now}, context=timer_context)
|
||||
hass.bus.async_fire(
|
||||
EVENT_TIME_CHANGED, {ATTR_NOW: now}, time_fired=now, context=timer_context
|
||||
)
|
||||
|
||||
# If we are more than a second late, a tick was missed
|
||||
late = monotonic() - target
|
||||
if late > 1:
|
||||
hass.bus.async_fire(
|
||||
EVENT_TIMER_OUT_OF_SYNC, {ATTR_SECONDS: late}, context=timer_context
|
||||
EVENT_TIMER_OUT_OF_SYNC,
|
||||
{ATTR_SECONDS: late},
|
||||
time_fired=now,
|
||||
context=timer_context,
|
||||
)
|
||||
|
||||
schedule_tick(now)
|
||||
|
|
|
@ -201,10 +201,7 @@ async def test_get_states(hass, websocket_client):
|
|||
|
||||
states = []
|
||||
for state in hass.states.async_all():
|
||||
state = state.as_dict()
|
||||
state["last_changed"] = state["last_changed"].isoformat()
|
||||
state["last_updated"] = state["last_updated"].isoformat()
|
||||
states.append(state)
|
||||
states.append(state.as_dict())
|
||||
|
||||
assert msg["result"] == states
|
||||
|
||||
|
|
|
@ -291,7 +291,7 @@ def test_event_repr():
|
|||
|
||||
|
||||
def test_event_as_dict():
|
||||
"""Test as Event as dictionary."""
|
||||
"""Test an Event as dictionary."""
|
||||
event_type = "some_type"
|
||||
now = dt_util.utcnow()
|
||||
data = {"some": "attr"}
|
||||
|
@ -301,7 +301,7 @@ def test_event_as_dict():
|
|||
"event_type": event_type,
|
||||
"data": data,
|
||||
"origin": "LOCAL",
|
||||
"time_fired": now,
|
||||
"time_fired": now.isoformat(),
|
||||
"context": {
|
||||
"id": event.context.id,
|
||||
"parent_id": None,
|
||||
|
@ -309,6 +309,36 @@ def test_event_as_dict():
|
|||
},
|
||||
}
|
||||
assert event.as_dict() == expected
|
||||
# 2nd time to verify cache
|
||||
assert event.as_dict() == expected
|
||||
|
||||
|
||||
def test_state_as_dict():
|
||||
"""Test a State as dictionary."""
|
||||
last_time = datetime(1984, 12, 8, 12, 0, 0)
|
||||
state = ha.State(
|
||||
"happy.happy",
|
||||
"on",
|
||||
{"pig": "dog"},
|
||||
last_updated=last_time,
|
||||
last_changed=last_time,
|
||||
)
|
||||
expected = {
|
||||
"context": {
|
||||
"id": state.context.id,
|
||||
"parent_id": None,
|
||||
"user_id": state.context.user_id,
|
||||
},
|
||||
"entity_id": "happy.happy",
|
||||
"attributes": {"pig": "dog"},
|
||||
"last_changed": last_time.isoformat(),
|
||||
"last_updated": last_time.isoformat(),
|
||||
"state": "on",
|
||||
}
|
||||
assert state.as_dict() == expected
|
||||
# 2nd time to verify cache
|
||||
assert state.as_dict() == expected
|
||||
assert state.as_dict() is state.as_dict()
|
||||
|
||||
|
||||
class TestEventBus(unittest.TestCase):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue