From a641be50d3c74a0bd87e8d246bb910aa5b8243fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 23 Mar 2021 10:09:15 -1000 Subject: [PATCH 1/2] Include integrations that are platform only in the manifest list api Ensure legacy device trackers get add to hass.config.components as they were previously all called device_tracker.legacy --- .../components/device_tracker/legacy.py | 9 +++-- .../components/websocket_api/commands.py | 9 ++--- homeassistant/setup.py | 34 +++++++++++++++++++ script/hassfest/dependencies.py | 19 ++--------- tests/test_setup.py | 18 ++++++++++ 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/device_tracker/legacy.py b/homeassistant/components/device_tracker/legacy.py index 7ab8df1de8717..1649c51b1ae9c 100644 --- a/homeassistant/components/device_tracker/legacy.py +++ b/homeassistant/components/device_tracker/legacy.py @@ -221,7 +221,7 @@ def type(self): async def async_setup_legacy(self, hass, tracker, discovery_info=None): """Set up a legacy platform.""" - LOGGER.info("Setting up %s.%s", DOMAIN, self.type) + LOGGER.info("Setting up %s.%s", DOMAIN, self.name) try: scanner = None setup = None @@ -248,6 +248,9 @@ async def async_setup_legacy(self, hass, tracker, discovery_info=None): else: raise HomeAssistantError("Invalid legacy device_tracker platform.") + if setup: + hass.config.components.add(f"{DOMAIN}.{self.name}") + if scanner: async_setup_scanner_platform( hass, self.config, scanner, tracker.async_see, self.type @@ -255,11 +258,11 @@ async def async_setup_legacy(self, hass, tracker, discovery_info=None): return if not setup: - LOGGER.error("Error setting up platform %s", self.type) + LOGGER.error("Error setting up platform %s %s", self.type, self.name) return except Exception: # pylint: disable=broad-except - LOGGER.exception("Error setting up platform %s", self.type) + LOGGER.exception("Error setting up platform %s %s", self.type, self.name) async def async_extract_config(hass, config): diff --git a/homeassistant/components/websocket_api/commands.py b/homeassistant/components/websocket_api/commands.py index f85281d10c1b2..74251e1bf24b2 100644 --- a/homeassistant/components/websocket_api/commands.py +++ b/homeassistant/components/websocket_api/commands.py @@ -17,6 +17,7 @@ from homeassistant.helpers.event import TrackTemplate, async_track_template_result from homeassistant.helpers.service import async_get_all_descriptions from homeassistant.loader import IntegrationNotFound, async_get_integration +from homeassistant.setup import async_get_loaded_integrations from . import const, decorators, messages @@ -215,13 +216,9 @@ def handle_get_config(hass, connection, msg): @decorators.async_response async def handle_manifest_list(hass, connection, msg): """Handle integrations command.""" + loaded_integrations = async_get_loaded_integrations(hass) integrations = await asyncio.gather( - *[ - async_get_integration(hass, domain) - for domain in hass.config.components - # Filter out platforms. - if "." not in domain - ] + *[async_get_integration(hass, domain) for domain in loaded_integrations] ) connection.send_result( msg["id"], [integration.manifest for integration in integrations] diff --git a/homeassistant/setup.py b/homeassistant/setup.py index c22e660e553b2..119903fdf937e 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -18,6 +18,26 @@ ATTR_COMPONENT = "component" +BASE_PLATFORMS = { + "alarm_control_panel", + "binary_sensor", + "climate", + "cover", + "device_tracker", + "fan", + "humidifier", + "image_processing", + "light", + "lock", + "media_player", + "remote", + "scene", + "sensor", + "switch", + "vacuum", + "water_heater", +} + DATA_SETUP_DONE = "setup_done" DATA_SETUP_STARTED = "setup_started" DATA_SETUP = "setup_tasks" @@ -381,3 +401,17 @@ async def loaded_event(event: core.Event) -> None: await when_setup() unsub = hass.bus.async_listen(EVENT_COMPONENT_LOADED, loaded_event) + + +@core.callback +def async_get_loaded_integrations(hass: core.HomeAssistant) -> set: + """Return the complete list of loaded integrations.""" + integrations = set() + for component in hass.config.components: + if "." not in component: + integrations.add(component) + continue + domain, platform = component.split(".", 1) + if domain in BASE_PLATFORMS: + integrations.add(platform) + return integrations diff --git a/script/hassfest/dependencies.py b/script/hassfest/dependencies.py index 5f885c59a1d2a..cb7458af154d2 100644 --- a/script/hassfest/dependencies.py +++ b/script/hassfest/dependencies.py @@ -5,6 +5,7 @@ from pathlib import Path from homeassistant.requirements import DISCOVERY_INTEGRATIONS +from homeassistant.setup import BASE_PLATFORMS from .model import Integration @@ -107,7 +108,6 @@ def visit_Attribute(self, node): "onboarding", "persistent_notification", "person", - "remote", "script", "shopping_list", "sun", @@ -118,22 +118,7 @@ def visit_Attribute(self, node): "websocket_api", "zone", # Entity integrations with platforms - "alarm_control_panel", - "binary_sensor", - "climate", - "cover", - "device_tracker", - "fan", - "humidifier", - "image_processing", - "light", - "lock", - "media_player", - "scene", - "sensor", - "switch", - "vacuum", - "water_heater", + *BASE_PLATFORMS, # Other "mjpeg", # base class, has no reqs or component to load. "stream", # Stream cannot install on all systems, can be imported without reqs. diff --git a/tests/test_setup.py b/tests/test_setup.py index abb8f7569897f..c2cbc3d6ea8c5 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -600,3 +600,21 @@ async def test_integration_disabled(hass, caplog): result = await setup.async_setup_component(hass, "test_component1", {}) assert not result assert disabled_reason in caplog.text + + +async def test_async_get_loaded_integrations(hass): + """Test we can enumerate loaded integations.""" + hass.config.components.add("notbase") + hass.config.components.add("switch") + hass.config.components.add("notbase.switch") + hass.config.components.add("myintegration") + hass.config.components.add("device_tracker") + hass.config.components.add("device_tracker.other") + hass.config.components.add("myintegration.light") + assert setup.async_get_loaded_integrations(hass) == { + "other", + "switch", + "notbase", + "myintegration", + "device_tracker", + } From 4a7e81d550d6732507ad79dbdcd837acb6d4d972 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 27 Mar 2021 05:46:26 -1000 Subject: [PATCH 2/2] add missing base platforms --- homeassistant/setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 119903fdf937e..288f9d0847b78 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -19,6 +19,7 @@ ATTR_COMPONENT = "component" BASE_PLATFORMS = { + "air_quality", "alarm_control_panel", "binary_sensor", "climate", @@ -30,6 +31,7 @@ "light", "lock", "media_player", + "notify", "remote", "scene", "sensor",