diff --git a/homeassistant/components/websocket_api/commands.py b/homeassistant/components/websocket_api/commands.py index fb540183df4..13b51fda9d6 100644 --- a/homeassistant/components/websocket_api/commands.py +++ b/homeassistant/components/websocket_api/commands.py @@ -46,10 +46,10 @@ from homeassistant.helpers.json import ( ExtendedJSONEncoder, find_paths_unserializable_data, json_bytes, + json_fragment, ) from homeassistant.helpers.service import async_get_all_descriptions from homeassistant.loader import ( - Integration, IntegrationNotFound, async_get_integration, async_get_integration_descriptions, @@ -505,19 +505,15 @@ async def handle_manifest_list( hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any] ) -> None: """Handle integrations command.""" - wanted_integrations = msg.get("integrations") - if wanted_integrations is None: - wanted_integrations = async_get_loaded_integrations(hass) - - ints_or_excs = await async_get_integrations(hass, wanted_integrations) - integrations: list[Integration] = [] + ints_or_excs = await async_get_integrations( + hass, msg.get("integrations") or async_get_loaded_integrations(hass) + ) + manifest_json_fragments: list[json_fragment] = [] for int_or_exc in ints_or_excs.values(): if isinstance(int_or_exc, Exception): raise int_or_exc - integrations.append(int_or_exc) - connection.send_result( - msg["id"], [integration.manifest for integration in integrations] - ) + manifest_json_fragments.append(int_or_exc.manifest_json_fragment) + connection.send_result(msg["id"], manifest_json_fragments) @decorators.websocket_command( @@ -530,9 +526,10 @@ async def handle_manifest_get( """Handle integrations command.""" try: integration = await async_get_integration(hass, msg["integration"]) - connection.send_result(msg["id"], integration.manifest) except IntegrationNotFound: connection.send_error(msg["id"], const.ERR_NOT_FOUND, "Integration not found") + else: + connection.send_result(msg["id"], integration.manifest_json_fragment) @callback diff --git a/homeassistant/loader.py b/homeassistant/loader.py index f2970ce3cf9..1ad04b085b3 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -39,6 +39,7 @@ from .generated.mqtt import MQTT from .generated.ssdp import SSDP from .generated.usb import USB from .generated.zeroconf import HOMEKIT, ZEROCONF +from .helpers.json import json_bytes, json_fragment from .util.hass_dict import HassKey from .util.json import JSON_DECODE_EXCEPTIONS, json_loads @@ -762,6 +763,11 @@ class Integration: self._top_level_files = top_level_files or set() _LOGGER.info("Loaded %s from %s", self.domain, pkg_path) + @cached_property + def manifest_json_fragment(self) -> json_fragment: + """Return manifest as a JSON fragment.""" + return json_fragment(json_bytes(self.manifest)) + @cached_property def name(self) -> str: """Return name.""" diff --git a/tests/test_loader.py b/tests/test_loader.py index 404858200bc..07fe949f882 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -15,6 +15,8 @@ from homeassistant.components import http, hue from homeassistant.components.hue import light as hue_light from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import frame +from homeassistant.helpers.json import json_dumps +from homeassistant.util.json import json_loads from .common import MockModule, async_get_persistent_notifications, mock_integration @@ -1959,3 +1961,12 @@ async def test_hass_helpers_use_reported( "Detected that custom integration 'test_integration_frame' " "accesses hass.helpers.aiohttp_client. This is deprecated" ) in caplog.text + + +async def test_manifest_json_fragment_round_trip(hass: HomeAssistant) -> None: + """Test json_fragment roundtrip.""" + integration = await loader.async_get_integration(hass, "hue") + assert ( + json_loads(json_dumps(integration.manifest_json_fragment)) + == integration.manifest + )