From 8015bb98a909c95d044579a77e6a22abf108e6f8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 23 Jun 2022 07:32:26 -0500 Subject: [PATCH] Switch recorder and templates to use json helper (#73876) - These were using orjson directly, its a bit cleaner to use the helper so everything is easier to adjust in the future if we need to change anything about the loading --- .../components/recorder/db_schema.py | 32 +++++++++++-------- homeassistant/components/recorder/models.py | 4 +-- homeassistant/helpers/template.py | 8 ++--- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/recorder/db_schema.py b/homeassistant/components/recorder/db_schema.py index f300cc0bae7..36487353e25 100644 --- a/homeassistant/components/recorder/db_schema.py +++ b/homeassistant/components/recorder/db_schema.py @@ -8,7 +8,6 @@ from typing import Any, cast import ciso8601 from fnvhash import fnv1a_32 -import orjson from sqlalchemy import ( JSON, BigInteger, @@ -39,7 +38,12 @@ from homeassistant.const import ( MAX_LENGTH_STATE_STATE, ) from homeassistant.core import Context, Event, EventOrigin, State, split_entity_id -from homeassistant.helpers.json import JSON_DUMP, json_bytes +from homeassistant.helpers.json import ( + JSON_DECODE_EXCEPTIONS, + JSON_DUMP, + json_bytes, + json_loads, +) import homeassistant.util.dt as dt_util from .const import ALL_DOMAIN_EXCLUDE_ATTRS @@ -188,15 +192,15 @@ class Events(Base): # type: ignore[misc,valid-type] try: return Event( self.event_type, - orjson.loads(self.event_data) if self.event_data else {}, + json_loads(self.event_data) if self.event_data else {}, EventOrigin(self.origin) if self.origin else EVENT_ORIGIN_ORDER[self.origin_idx], process_timestamp(self.time_fired), context=context, ) - except ValueError: - # When orjson.loads fails + except JSON_DECODE_EXCEPTIONS: + # When json_loads fails _LOGGER.exception("Error converting to event: %s", self) return None @@ -243,8 +247,8 @@ class EventData(Base): # type: ignore[misc,valid-type] def to_native(self) -> dict[str, Any]: """Convert to an HA state object.""" try: - return cast(dict[str, Any], orjson.loads(self.shared_data)) - except ValueError: + return cast(dict[str, Any], json_loads(self.shared_data)) + except JSON_DECODE_EXCEPTIONS: _LOGGER.exception("Error converting row to event data: %s", self) return {} @@ -330,9 +334,9 @@ class States(Base): # type: ignore[misc,valid-type] parent_id=self.context_parent_id, ) try: - attrs = orjson.loads(self.attributes) if self.attributes else {} - except ValueError: - # When orjson.loads fails + attrs = json_loads(self.attributes) if self.attributes else {} + except JSON_DECODE_EXCEPTIONS: + # When json_loads fails _LOGGER.exception("Error converting row to state: %s", self) return None if self.last_changed is None or self.last_changed == self.last_updated: @@ -402,15 +406,15 @@ class StateAttributes(Base): # type: ignore[misc,valid-type] @staticmethod def hash_shared_attrs_bytes(shared_attrs_bytes: bytes) -> int: - """Return the hash of orjson encoded shared attributes.""" + """Return the hash of json encoded shared attributes.""" return cast(int, fnv1a_32(shared_attrs_bytes)) def to_native(self) -> dict[str, Any]: """Convert to an HA state object.""" try: - return cast(dict[str, Any], orjson.loads(self.shared_attrs)) - except ValueError: - # When orjson.loads fails + return cast(dict[str, Any], json_loads(self.shared_attrs)) + except JSON_DECODE_EXCEPTIONS: + # When json_loads fails _LOGGER.exception("Error converting row to state attributes: %s", self) return {} diff --git a/homeassistant/components/recorder/models.py b/homeassistant/components/recorder/models.py index 64fb44289b0..ff53d9be3d1 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -5,7 +5,6 @@ from datetime import datetime import logging from typing import Any, TypedDict, overload -import orjson from sqlalchemy.engine.row import Row from homeassistant.components.websocket_api.const import ( @@ -15,6 +14,7 @@ from homeassistant.components.websocket_api.const import ( COMPRESSED_STATE_STATE, ) from homeassistant.core import Context, State +from homeassistant.helpers.json import json_loads import homeassistant.util.dt as dt_util # pylint: disable=invalid-name @@ -253,7 +253,7 @@ def decode_attributes_from_row( if not source or source == EMPTY_JSON_OBJECT: return {} try: - attr_cache[source] = attributes = orjson.loads(source) + attr_cache[source] = attributes = json_loads(source) except ValueError: _LOGGER.exception("Error converting row to state attributes: %s", source) attr_cache[source] = attributes = {} diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 02f95254c86..ac5b4c8119f 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -27,7 +27,6 @@ import jinja2 from jinja2 import pass_context, pass_environment from jinja2.sandbox import ImmutableSandboxedEnvironment from jinja2.utils import Namespace -import orjson import voluptuous as vol from homeassistant.const import ( @@ -58,6 +57,7 @@ from homeassistant.util.async_ import run_callback_threadsafe from homeassistant.util.thread import ThreadWithException from . import area_registry, device_registry, entity_registry, location as loc_helper +from .json import JSON_DECODE_EXCEPTIONS, json_loads from .typing import TemplateVarsType # mypy: allow-untyped-defs, no-check-untyped-defs @@ -566,8 +566,8 @@ class Template: variables = dict(variables or {}) variables["value"] = value - with suppress(ValueError, TypeError): - variables["value_json"] = orjson.loads(value) + with suppress(*JSON_DECODE_EXCEPTIONS): + variables["value_json"] = json_loads(value) try: return _render_with_context( @@ -1744,7 +1744,7 @@ def ordinal(value): def from_json(value): """Convert a JSON string to an object.""" - return orjson.loads(value) + return json_loads(value) def to_json(value, ensure_ascii=True):