Make core States use cached_property (#100312)
Need to validate this is worth removing __slots__
This commit is contained in:
parent
3cc9410a62
commit
547f32818c
6 changed files with 24 additions and 44 deletions
|
@ -202,11 +202,11 @@ class APIStatesView(HomeAssistantView):
|
|||
user: User = request["hass_user"]
|
||||
hass: HomeAssistant = request.app["hass"]
|
||||
if user.is_admin:
|
||||
states = (state.as_dict_json() for state in hass.states.async_all())
|
||||
states = (state.as_dict_json for state in hass.states.async_all())
|
||||
else:
|
||||
entity_perm = user.permissions.check_entity
|
||||
states = (
|
||||
state.as_dict_json()
|
||||
state.as_dict_json
|
||||
for state in hass.states.async_all()
|
||||
if entity_perm(state.entity_id, "read")
|
||||
)
|
||||
|
@ -233,7 +233,7 @@ class APIEntityStateView(HomeAssistantView):
|
|||
|
||||
if state := hass.states.get(entity_id):
|
||||
return web.Response(
|
||||
body=state.as_dict_json(),
|
||||
body=state.as_dict_json,
|
||||
content_type=CONTENT_TYPE_JSON,
|
||||
)
|
||||
return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND)
|
||||
|
|
|
@ -270,7 +270,7 @@ def handle_get_states(
|
|||
states = _async_get_allowed_states(hass, connection)
|
||||
|
||||
try:
|
||||
serialized_states = [state.as_dict_json() for state in states]
|
||||
serialized_states = [state.as_dict_json for state in states]
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
else:
|
||||
|
@ -281,7 +281,7 @@ def handle_get_states(
|
|||
serialized_states = []
|
||||
for state in states:
|
||||
try:
|
||||
serialized_states.append(state.as_dict_json())
|
||||
serialized_states.append(state.as_dict_json)
|
||||
except (ValueError, TypeError):
|
||||
connection.logger.error(
|
||||
"Unable to serialize to JSON. Bad data found at %s",
|
||||
|
@ -358,7 +358,7 @@ def handle_subscribe_entities(
|
|||
# to succeed for the UI to show.
|
||||
try:
|
||||
serialized_states = [
|
||||
state.as_compressed_state_json()
|
||||
state.as_compressed_state_json
|
||||
for state in states
|
||||
if not entity_ids or state.entity_id in entity_ids
|
||||
]
|
||||
|
@ -371,7 +371,7 @@ def handle_subscribe_entities(
|
|||
serialized_states = []
|
||||
for state in states:
|
||||
try:
|
||||
serialized_states.append(state.as_compressed_state_json())
|
||||
serialized_states.append(state.as_compressed_state_json)
|
||||
except (ValueError, TypeError):
|
||||
connection.logger.error(
|
||||
"Unable to serialize to JSON. Bad data found at %s",
|
||||
|
|
|
@ -141,7 +141,7 @@ def _state_diff_event(event: Event) -> dict:
|
|||
if (event_old_state := event.data["old_state"]) is None:
|
||||
return {
|
||||
ENTITY_EVENT_ADD: {
|
||||
event_new_state.entity_id: event_new_state.as_compressed_state()
|
||||
event_new_state.entity_id: event_new_state.as_compressed_state
|
||||
}
|
||||
}
|
||||
if TYPE_CHECKING:
|
||||
|
|
|
@ -35,6 +35,7 @@ import voluptuous as vol
|
|||
import yarl
|
||||
|
||||
from . import block_async_io, util
|
||||
from .backports.functools import cached_property
|
||||
from .const import (
|
||||
ATTR_DOMAIN,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
|
@ -1239,20 +1240,6 @@ class State:
|
|||
object_id: Object id of this state.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"entity_id",
|
||||
"state",
|
||||
"attributes",
|
||||
"last_changed",
|
||||
"last_updated",
|
||||
"context",
|
||||
"domain",
|
||||
"object_id",
|
||||
"_as_dict",
|
||||
"_as_dict_json",
|
||||
"_as_compressed_state_json",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
entity_id: str,
|
||||
|
@ -1282,8 +1269,6 @@ class State:
|
|||
self.context = context or Context()
|
||||
self.domain, self.object_id = split_entity_id(self.entity_id)
|
||||
self._as_dict: ReadOnlyDict[str, Collection[Any]] | None = None
|
||||
self._as_dict_json: str | None = None
|
||||
self._as_compressed_state_json: str | None = None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
@ -1318,12 +1303,12 @@ class State:
|
|||
)
|
||||
return self._as_dict
|
||||
|
||||
@cached_property
|
||||
def as_dict_json(self) -> str:
|
||||
"""Return a JSON string of the State."""
|
||||
if not self._as_dict_json:
|
||||
self._as_dict_json = json_dumps(self.as_dict())
|
||||
return self._as_dict_json
|
||||
return json_dumps(self.as_dict())
|
||||
|
||||
@cached_property
|
||||
def as_compressed_state(self) -> dict[str, Any]:
|
||||
"""Build a compressed dict of a state for adds.
|
||||
|
||||
|
@ -1348,6 +1333,7 @@ class State:
|
|||
)
|
||||
return compressed_state
|
||||
|
||||
@cached_property
|
||||
def as_compressed_state_json(self) -> str:
|
||||
"""Build a compressed JSON key value pair of a state for adds.
|
||||
|
||||
|
@ -1355,11 +1341,7 @@ class State:
|
|||
|
||||
It is used for sending multiple states in a single message.
|
||||
"""
|
||||
if not self._as_compressed_state_json:
|
||||
self._as_compressed_state_json = json_dumps(
|
||||
{self.entity_id: self.as_compressed_state()}
|
||||
)[1:-1]
|
||||
return self._as_compressed_state_json
|
||||
return json_dumps({self.entity_id: self.as_compressed_state})[1:-1]
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, json_dict: dict[str, Any]) -> Self | None:
|
||||
|
|
|
@ -929,8 +929,6 @@ class DomainStates:
|
|||
class TemplateStateBase(State):
|
||||
"""Class to represent a state object in a template."""
|
||||
|
||||
__slots__ = ("_hass", "_collect", "_entity_id", "__dict__")
|
||||
|
||||
_state: State
|
||||
|
||||
__setitem__ = _readonly
|
||||
|
|
|
@ -671,11 +671,11 @@ def test_state_as_dict_json() -> None:
|
|||
'"last_changed":"1984-12-08T12:00:00","last_updated":"1984-12-08T12:00:00",'
|
||||
'"context":{"id":"01H0D6K3RFJAYAV2093ZW30PCW","parent_id":null,"user_id":null}}'
|
||||
)
|
||||
as_dict_json_1 = state.as_dict_json()
|
||||
as_dict_json_1 = state.as_dict_json
|
||||
assert as_dict_json_1 == expected
|
||||
# 2nd time to verify cache
|
||||
assert state.as_dict_json() == expected
|
||||
assert state.as_dict_json() is as_dict_json_1
|
||||
assert state.as_dict_json == expected
|
||||
assert state.as_dict_json is as_dict_json_1
|
||||
|
||||
|
||||
def test_state_as_compressed_state() -> None:
|
||||
|
@ -694,12 +694,12 @@ def test_state_as_compressed_state() -> None:
|
|||
"lc": last_time.timestamp(),
|
||||
"s": "on",
|
||||
}
|
||||
as_compressed_state = state.as_compressed_state()
|
||||
as_compressed_state = state.as_compressed_state
|
||||
# We are not too concerned about these being ReadOnlyDict
|
||||
# since we don't expect them to be called by external callers
|
||||
assert as_compressed_state == expected
|
||||
# 2nd time to verify cache
|
||||
assert state.as_compressed_state() == expected
|
||||
assert state.as_compressed_state == expected
|
||||
|
||||
|
||||
def test_state_as_compressed_state_unique_last_updated() -> None:
|
||||
|
@ -720,12 +720,12 @@ def test_state_as_compressed_state_unique_last_updated() -> None:
|
|||
"lu": last_updated.timestamp(),
|
||||
"s": "on",
|
||||
}
|
||||
as_compressed_state = state.as_compressed_state()
|
||||
as_compressed_state = state.as_compressed_state
|
||||
# We are not too concerned about these being ReadOnlyDict
|
||||
# since we don't expect them to be called by external callers
|
||||
assert as_compressed_state == expected
|
||||
# 2nd time to verify cache
|
||||
assert state.as_compressed_state() == expected
|
||||
assert state.as_compressed_state == expected
|
||||
|
||||
|
||||
def test_state_as_compressed_state_json() -> None:
|
||||
|
@ -740,13 +740,13 @@ def test_state_as_compressed_state_json() -> None:
|
|||
context=ha.Context(id="01H0D6H5K3SZJ3XGDHED1TJ79N"),
|
||||
)
|
||||
expected = '"happy.happy":{"s":"on","a":{"pig":"dog"},"c":"01H0D6H5K3SZJ3XGDHED1TJ79N","lc":471355200.0}'
|
||||
as_compressed_state = state.as_compressed_state_json()
|
||||
as_compressed_state = state.as_compressed_state_json
|
||||
# We are not too concerned about these being ReadOnlyDict
|
||||
# since we don't expect them to be called by external callers
|
||||
assert as_compressed_state == expected
|
||||
# 2nd time to verify cache
|
||||
assert state.as_compressed_state_json() == expected
|
||||
assert state.as_compressed_state_json() is as_compressed_state
|
||||
assert state.as_compressed_state_json == expected
|
||||
assert state.as_compressed_state_json is as_compressed_state
|
||||
|
||||
|
||||
async def test_eventbus_add_remove_listener(hass: HomeAssistant) -> None:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue