diff --git a/homeassistant/setup.py b/homeassistant/setup.py index efbaacac43e..7da82156c3f 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -482,8 +482,21 @@ async def async_prepare_setup_platform( log_error(str(err)) return None + # Platforms cannot exist on their own, they are part of their integration. + # If the integration is not set up yet, and can be set up, set it up. + # + # We do this before we import the platform so the platform already knows + # where the top level component is. + # + if load_top_level_component := integration.domain not in hass.config.components: + try: + component = await integration.async_get_component() + except ImportError as exc: + log_error(f"Unable to import the component ({exc}).") + return None + try: - platform = integration.get_platform(domain) + platform = await integration.async_get_platform(domain) except ImportError as exc: log_error(f"Platform not found ({exc}).") return None @@ -494,13 +507,7 @@ async def async_prepare_setup_platform( # Platforms cannot exist on their own, they are part of their integration. # If the integration is not set up yet, and can be set up, set it up. - if integration.domain not in hass.config.components: - try: - component = integration.get_component() - except ImportError as exc: - log_error(f"Unable to import the component ({exc}).") - return None - + if load_top_level_component: if ( hasattr(component, "setup") or hasattr(component, "async_setup") ) and not await async_setup_component(hass, integration.domain, hass_config): diff --git a/tests/test_setup.py b/tests/test_setup.py index 0f6a4302200..29ced934745 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -7,7 +7,7 @@ from unittest.mock import AsyncMock, Mock, patch import pytest import voluptuous as vol -from homeassistant import config_entries, setup +from homeassistant import config_entries, loader, setup from homeassistant.const import EVENT_COMPONENT_LOADED, EVENT_HOMEASSISTANT_START from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError @@ -822,3 +822,30 @@ async def test_importing_integration_in_executor( assert await setup.async_setup_component(hass, "test_package_loaded_executor", {}) assert await setup.async_setup_component(hass, "test_package_loaded_executor", {}) await hass.async_block_till_done() + + +async def test_async_prepare_setup_platform( + hass: HomeAssistant, + enable_custom_integrations: None, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test we can prepare a platform setup.""" + integration = await loader.async_get_integration(hass, "test") + with patch.object( + integration, "async_get_component", side_effect=ImportError("test is broken") + ): + assert ( + await setup.async_prepare_setup_platform(hass, {}, "config", "test") is None + ) + + assert "test is broken" in caplog.text + + caplog.clear() + # There is no actual config platform for this integration + assert await setup.async_prepare_setup_platform(hass, {}, "config", "test") is None + assert "No module named 'custom_components.test.config'" in caplog.text + + button_platform = ( + await setup.async_prepare_setup_platform(hass, {}, "button", "test") is None + ) + assert button_platform is not None