From b3dedb3efb36eafe06ce48fe94b59e37ce5f9257 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Mar 2024 02:38:21 -1000 Subject: [PATCH] Convert sets to list before passing to the JSON serializer in the registries (#113133) There were a few places we were missing the set to list conversions in the registries. We do this before its cached to avoid the JSON serializer having to fallback to the default method every time since its expensive to switch back from the native code into python context for every set. --- homeassistant/helpers/device_registry.py | 3 +++ homeassistant/helpers/entity_registry.py | 28 ++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index e823f356f4e..d751efdffe6 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -263,6 +263,9 @@ class DeviceEntry: @property def dict_repr(self) -> dict[str, Any]: """Return a dict representation of the entry.""" + # Convert sets and tuples to lists + # so the JSON serializer does not have to do + # it every time return { "area_id": self.area_id, "configuration_url": self.configuration_url, diff --git a/homeassistant/helpers/entity_registry.py b/homeassistant/helpers/entity_registry.py index 84d1bd43e2e..413f227c7cc 100644 --- a/homeassistant/helpers/entity_registry.py +++ b/homeassistant/helpers/entity_registry.py @@ -136,11 +136,12 @@ EntityOptionsType = Mapping[str, Mapping[str, Any]] ReadOnlyEntityOptionsType = ReadOnlyDict[str, ReadOnlyDict[str, Any]] DISPLAY_DICT_OPTIONAL = ( - ("ai", "area_id"), - ("lb", "labels"), - ("di", "device_id"), - ("ic", "icon"), - ("tk", "translation_key"), + # key, attr_name, convert_to_list + ("ai", "area_id", False), + ("lb", "labels", True), + ("di", "device_id", False), + ("ic", "icon", False), + ("tk", "translation_key", False), ) @@ -213,9 +214,12 @@ class RegistryEntry: Returns None if there's no data needed for display. """ display_dict: dict[str, Any] = {"ei": self.entity_id, "pl": self.platform} - for key, attr_name in DISPLAY_DICT_OPTIONAL: + for key, attr_name, convert_list in DISPLAY_DICT_OPTIONAL: if (attr_val := getattr(self, attr_name)) is not None: - display_dict[key] = attr_val + # Convert sets and tuples to lists + # so the JSON serializer does not have to do + # it every time + display_dict[key] = list(attr_val) if convert_list else attr_val if (category := self.entity_category) is not None: display_dict["ec"] = ENTITY_CATEGORY_VALUE_TO_INDEX[category] if self.hidden_by is not None: @@ -253,6 +257,9 @@ class RegistryEntry: @cached_property def as_partial_dict(self) -> dict[str, Any]: """Return a partial dict representation of the entry.""" + # Convert sets and tuples to lists + # so the JSON serializer does not have to do + # it every time return { "area_id": self.area_id, "config_entry_id": self.config_entry_id, @@ -264,7 +271,7 @@ class RegistryEntry: "hidden_by": self.hidden_by, "icon": self.icon, "id": self.id, - "labels": self.labels, + "labels": list(self.labels), "name": self.name, "options": self.options, "original_name": self.original_name, @@ -276,9 +283,12 @@ class RegistryEntry: @cached_property def extended_dict(self) -> dict[str, Any]: """Return a extended dict representation of the entry.""" + # Convert sets and tuples to lists + # so the JSON serializer does not have to do + # it every time return { **self.as_partial_dict, - "aliases": self.aliases, + "aliases": list(self.aliases), "capabilities": self.capabilities, "device_class": self.device_class, "original_device_class": self.original_device_class,