Avoid recreating ReadOnly dicts when attributes do not change (#106687)

pull/106705/head
J. Nick Koston 2023-12-29 17:10:40 -10:00 committed by GitHub
parent 2177113c6e
commit 9e3869ae1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 1 deletions

View File

@ -1409,7 +1409,13 @@ class State:
self.entity_id = entity_id
self.state = state
self.attributes = ReadOnlyDict(attributes or {})
# State only creates and expects a ReadOnlyDict so
# there is no need to check for subclassing with
# isinstance here so we can use the faster type check.
if type(attributes) is not ReadOnlyDict: # noqa: E721
self.attributes = ReadOnlyDict(attributes or {})
else:
self.attributes = attributes
self.last_updated = last_updated or dt_util.utcnow()
self.last_changed = last_changed or self.last_updated
self.context = context or Context()
@ -1828,6 +1834,11 @@ class StateMachine:
else:
now = dt_util.utcnow()
if same_attr:
if TYPE_CHECKING:
assert old_state is not None
attributes = old_state.attributes
state = State(
entity_id,
new_state,

View File

@ -1157,6 +1157,26 @@ async def test_statemachine_force_update(hass: HomeAssistant) -> None:
assert len(events) == 1
async def test_statemachine_avoids_updating_attributes(hass: HomeAssistant) -> None:
"""Test async_set avoids recreating ReadOnly dicts when possible."""
attrs = {"some_attr": "attr_value"}
hass.states.async_set("light.bowl", "off", attrs)
await hass.async_block_till_done()
state = hass.states.get("light.bowl")
assert state.attributes == attrs
hass.states.async_set("light.bowl", "on", attrs)
await hass.async_block_till_done()
new_state = hass.states.get("light.bowl")
assert new_state.attributes == attrs
assert new_state.attributes is state.attributes
assert isinstance(new_state.attributes, ReadOnlyDict)
def test_service_call_repr() -> None:
"""Test ServiceCall repr."""
call = ha.ServiceCall("homeassistant", "start")