mirror of
https://github.com/home-assistant/core.git
synced 2025-04-19 14:57:52 +00:00
Avoid waiting for integration platforms in the parent integration (#112467)
This commit is contained in:
parent
87739bc072
commit
f3a9756f81
@ -125,7 +125,7 @@ class BackupManager:
|
||||
async def load_platforms(self) -> None:
|
||||
"""Load backup platforms."""
|
||||
await integration_platform.async_process_integration_platforms(
|
||||
self.hass, DOMAIN, self._add_platform
|
||||
self.hass, DOMAIN, self._add_platform, wait_for_platforms=True
|
||||
)
|
||||
LOGGER.debug("Loaded %s platforms", len(self.platforms))
|
||||
self.loaded_platforms = True
|
||||
|
@ -71,7 +71,9 @@ async def async_get_energy_platforms(
|
||||
|
||||
platforms[domain] = cast(EnergyPlatform, platform).async_get_solar_forecast
|
||||
|
||||
await async_process_integration_platforms(hass, DOMAIN, _process_energy_platform)
|
||||
await async_process_integration_platforms(
|
||||
hass, DOMAIN, _process_energy_platform, wait_for_platforms=True
|
||||
)
|
||||
|
||||
return platforms
|
||||
|
||||
|
@ -15,7 +15,9 @@ async def async_process_hardware_platforms(hass: HomeAssistant) -> None:
|
||||
"""Start processing hardware platforms."""
|
||||
hass.data[DOMAIN]["hardware_platform"] = {}
|
||||
|
||||
await async_process_integration_platforms(hass, DOMAIN, _register_hardware_platform)
|
||||
await async_process_integration_platforms(
|
||||
hass, DOMAIN, _register_hardware_platform, wait_for_platforms=True
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -143,7 +143,10 @@ class MultiprotocolAddonManager(WaitingAddonManager):
|
||||
async def async_setup(self) -> None:
|
||||
"""Set up the manager."""
|
||||
await async_process_integration_platforms(
|
||||
self._hass, "silabs_multiprotocol", self._register_multipan_platform
|
||||
self._hass,
|
||||
"silabs_multiprotocol",
|
||||
self._register_multipan_platform,
|
||||
wait_for_platforms=True,
|
||||
)
|
||||
await self.async_load()
|
||||
|
||||
|
@ -102,7 +102,9 @@ async def async_process_repairs_platforms(hass: HomeAssistant) -> None:
|
||||
"""Start processing repairs platforms."""
|
||||
hass.data[DOMAIN]["platforms"] = {}
|
||||
|
||||
await async_process_integration_platforms(hass, DOMAIN, _register_repairs_platform)
|
||||
await async_process_integration_platforms(
|
||||
hass, DOMAIN, _register_repairs_platform, wait_for_platforms=True
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -157,6 +157,7 @@ async def async_process_integration_platforms(
|
||||
platform_name: str,
|
||||
# Any = platform.
|
||||
process_platform: Callable[[HomeAssistant, str, Any], Awaitable[None] | None],
|
||||
wait_for_platforms: bool = False,
|
||||
) -> None:
|
||||
"""Process a specific platform for all current and future loaded integrations."""
|
||||
if DATA_INTEGRATION_PLATFORMS not in hass.data:
|
||||
@ -194,6 +195,36 @@ async def async_process_integration_platforms(
|
||||
if not top_level_components:
|
||||
return
|
||||
|
||||
# We create a task here for two reasons:
|
||||
#
|
||||
# 1. We want the integration that provides the integration platform to
|
||||
# not be delayed by waiting on each individual platform to be processed
|
||||
# since the import or the integration platforms themselves may have to
|
||||
# schedule I/O or executor jobs.
|
||||
#
|
||||
# 2. We want the behavior to be the same as if the integration that has
|
||||
# the integration platform is loaded after the platform is processed.
|
||||
#
|
||||
# We use hass.async_create_task instead of asyncio.create_task because
|
||||
# we want to make sure that startup waits for the task to complete.
|
||||
#
|
||||
future = hass.async_create_task(
|
||||
_async_process_integration_platforms(
|
||||
hass, platform_name, top_level_components.copy(), process_job
|
||||
),
|
||||
eager_start=True,
|
||||
)
|
||||
if wait_for_platforms:
|
||||
await future
|
||||
|
||||
|
||||
async def _async_process_integration_platforms(
|
||||
hass: HomeAssistant,
|
||||
platform_name: str,
|
||||
top_level_components: set[str],
|
||||
process_job: HassJob,
|
||||
) -> None:
|
||||
"""Process integration platforms for a component."""
|
||||
integrations = await async_get_integrations(hass, top_level_components)
|
||||
loaded_integrations: list[Integration] = [
|
||||
integration
|
||||
|
@ -19,6 +19,7 @@ async def test_accuweather_system_health(
|
||||
aioclient_mock.get("https://dataservice.accuweather.com/", text="")
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN]["0123xyz"] = {}
|
||||
@ -43,6 +44,7 @@ async def test_accuweather_system_health_fail(
|
||||
aioclient_mock.get("https://dataservice.accuweather.com/", exc=ClientError)
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN]["0123xyz"] = {}
|
||||
|
@ -19,6 +19,7 @@ async def test_airly_system_health(
|
||||
aioclient_mock.get("https://airapi.airly.eu/v2/", text="")
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN]["0123xyz"] = Mock(
|
||||
@ -47,6 +48,7 @@ async def test_airly_system_health_fail(
|
||||
aioclient_mock.get("https://airapi.airly.eu/v2/", exc=ClientError)
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN]["0123xyz"] = Mock(
|
||||
|
@ -11,6 +11,7 @@ async def test_humanify_alexa_event(hass: HomeAssistant) -> None:
|
||||
hass.config.components.add("recorder")
|
||||
await async_setup_component(hass, "alexa", {})
|
||||
await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
hass.states.async_set("light.kitchen", "on", {"friendly_name": "Kitchen Light"})
|
||||
|
||||
results = mock_humanify(
|
||||
|
@ -15,6 +15,7 @@ async def test_recording_event(
|
||||
"""Test recording event."""
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entry = MockConfigEntry()
|
||||
entry.add_to_hass(hass)
|
||||
|
@ -1862,6 +1862,7 @@ async def test_logbook_humanify_automation_triggered_event(hass: HomeAssistant)
|
||||
hass.config.components.add("recorder")
|
||||
await async_setup_component(hass, automation.DOMAIN, {})
|
||||
await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
event1, event2 = mock_humanify(
|
||||
hass,
|
||||
|
@ -11,6 +11,7 @@ async def test_humanify_automation_trigger_event(hass: HomeAssistant) -> None:
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "automation", {})
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
context = Context()
|
||||
|
||||
event1, event2 = mock_humanify(
|
||||
|
@ -199,6 +199,7 @@ async def test_loading_platforms(
|
||||
),
|
||||
)
|
||||
await manager.load_platforms()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert manager.loaded_platforms
|
||||
assert len(manager.platforms) == 1
|
||||
@ -218,6 +219,7 @@ async def test_not_loading_bad_platforms(
|
||||
|
||||
await _setup_mock_domain(hass)
|
||||
await manager.load_platforms()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert manager.loaded_platforms
|
||||
assert len(manager.platforms) == 0
|
||||
|
@ -74,6 +74,7 @@ async def test_humanifying_deconz_alarm_event(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
@ -183,6 +184,7 @@ async def test_humanifying_deconz_event(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
|
@ -89,6 +89,7 @@ async def test_save_preferences(
|
||||
mock_energy_platform,
|
||||
) -> None:
|
||||
"""Test we can save preferences."""
|
||||
await hass.async_block_till_done()
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
# Test saving default prefs is also valid.
|
||||
@ -283,6 +284,7 @@ async def test_get_solar_forecast(
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
manager = await data.async_get_manager(hass)
|
||||
|
||||
manager.data = data.EnergyManager.default_preferences()
|
||||
manager.data["energy_sources"].append(
|
||||
{
|
||||
@ -292,6 +294,7 @@ async def test_get_solar_forecast(
|
||||
}
|
||||
)
|
||||
client = await hass_ws_client(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await client.send_json({"id": 5, "type": "energy/solar_forecast"})
|
||||
|
||||
|
@ -21,6 +21,7 @@ async def test_gios_system_health(
|
||||
await integration.async_get_component()
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
info = await get_system_health_info(hass, DOMAIN)
|
||||
|
||||
@ -40,6 +41,7 @@ async def test_gios_system_health_fail(
|
||||
await integration.async_get_component()
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
info = await get_system_health_info(hass, DOMAIN)
|
||||
|
||||
|
@ -18,6 +18,7 @@ async def test_humanify_command_received(hass: HomeAssistant) -> None:
|
||||
hass.config.components.add("frontend")
|
||||
hass.config.components.add("google_assistant")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set(
|
||||
"light.kitchen", "on", {ATTR_FRIENDLY_NAME: "The Kitchen Lights"}
|
||||
|
@ -759,6 +759,7 @@ async def test_service_group_services_add_remove_entities(hass: HomeAssistant) -
|
||||
assert await async_setup_component(hass, "person", {})
|
||||
with assert_setup_component(0, "group"):
|
||||
await async_setup_component(hass, "group", {"group": {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.services.has_service("group", group.SERVICE_SET)
|
||||
|
||||
|
@ -29,6 +29,7 @@ async def test_hassio_system_health(
|
||||
|
||||
hass.config.components.add("hassio")
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.data["hassio_info"] = {
|
||||
"channel": "stable",
|
||||
@ -88,6 +89,7 @@ async def test_hassio_system_health_with_issues(
|
||||
|
||||
hass.config.components.add("hassio")
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.data["hassio_info"] = {"channel": "stable"}
|
||||
hass.data["hassio_host_info"] = {}
|
||||
|
@ -33,6 +33,7 @@ async def test_humanify_homekit_changed_event(
|
||||
with patch("homeassistant.components.homekit.HomeKit"):
|
||||
assert await async_setup_component(hass, "homekit", {"homekit": {}})
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
event1, event2 = mock_humanify(
|
||||
hass,
|
||||
|
@ -17,6 +17,7 @@ async def test_ipma_system_health(
|
||||
|
||||
hass.config.components.add("ipma")
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
info = await get_system_health_info(hass, "ipma")
|
||||
|
||||
|
@ -27,6 +27,7 @@ async def test_system_health(
|
||||
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
@ -66,6 +67,7 @@ async def test_system_health_failed_connect(
|
||||
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
|
@ -19,6 +19,7 @@ async def test_nextdns_system_health(
|
||||
aioclient_mock.get(API_ENDPOINT, text="")
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
info = await get_system_health_info(hass, DOMAIN)
|
||||
|
||||
@ -36,6 +37,7 @@ async def test_nextdns_system_health_fail(
|
||||
aioclient_mock.get(API_ENDPOINT, exc=ClientError)
|
||||
hass.config.components.add(DOMAIN)
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
info = await get_system_health_info(hass, DOMAIN)
|
||||
|
||||
|
@ -18,6 +18,7 @@ async def test_hardware_info(
|
||||
"""Test we can get the board info."""
|
||||
mock_integration(hass, MockModule("hassio"))
|
||||
await async_setup_component(hass, HASSIO_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Setup the config entry
|
||||
config_entry = MockConfigEntry(
|
||||
@ -70,6 +71,7 @@ async def test_hardware_info_fail(
|
||||
"""Test async_info raises if os_info is not as expected."""
|
||||
mock_integration(hass, MockModule("hassio"))
|
||||
await async_setup_component(hass, HASSIO_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Setup the config entry
|
||||
config_entry = MockConfigEntry(
|
||||
|
@ -898,6 +898,7 @@ async def test_logbook_humanify_script_started_event(hass: HomeAssistant) -> Non
|
||||
hass.config.components.add("recorder")
|
||||
await async_setup_component(hass, DOMAIN, {})
|
||||
await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
event1, event2 = mock_humanify(
|
||||
hass,
|
||||
|
@ -31,6 +31,7 @@ async def test_humanify_shelly_click_event_block_device(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
event1, event2 = mock_humanify(
|
||||
hass,
|
||||
@ -81,6 +82,7 @@ async def test_humanify_shelly_click_event_rpc_device(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
event1, event2 = mock_humanify(
|
||||
hass,
|
||||
|
@ -84,6 +84,7 @@ async def test_zha_logbook_event_device_with_triggers(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
@ -162,6 +163,7 @@ async def test_zha_logbook_event_device_no_triggers(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
@ -246,6 +248,7 @@ async def test_zha_logbook_event_device_no_device(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
|
@ -25,6 +25,7 @@ async def test_humanifying_zwave_js_notification_event(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
@ -108,6 +109,7 @@ async def test_humanifying_zwave_js_value_notification_event(
|
||||
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = mock_humanify(
|
||||
hass,
|
||||
|
@ -16,6 +16,44 @@ from homeassistant.setup import ATTR_COMPONENT, EVENT_COMPONENT_LOADED
|
||||
from tests.common import mock_platform
|
||||
|
||||
|
||||
async def test_process_integration_platforms_with_wait(hass: HomeAssistant) -> None:
|
||||
"""Test processing integrations."""
|
||||
loaded_platform = Mock()
|
||||
mock_platform(hass, "loaded.platform_to_check", loaded_platform)
|
||||
hass.config.components.add("loaded")
|
||||
|
||||
event_platform = Mock()
|
||||
mock_platform(hass, "event.platform_to_check", event_platform)
|
||||
|
||||
processed = []
|
||||
|
||||
async def _process_platform(hass, domain, platform):
|
||||
"""Process platform."""
|
||||
processed.append((domain, platform))
|
||||
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", _process_platform, wait_for_platforms=True
|
||||
)
|
||||
# No block till done here, we want to make sure it waits for the platform
|
||||
|
||||
assert len(processed) == 1
|
||||
assert processed[0][0] == "loaded"
|
||||
assert processed[0][1] == loaded_platform
|
||||
|
||||
hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: "event"})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(processed) == 2
|
||||
assert processed[1][0] == "event"
|
||||
assert processed[1][1] == event_platform
|
||||
|
||||
hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: "event"})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Firing again should not check again
|
||||
assert len(processed) == 2
|
||||
|
||||
|
||||
async def test_process_integration_platforms(hass: HomeAssistant) -> None:
|
||||
"""Test processing integrations."""
|
||||
loaded_platform = Mock()
|
||||
@ -34,6 +72,7 @@ async def test_process_integration_platforms(hass: HomeAssistant) -> None:
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", _process_platform
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(processed) == 1
|
||||
assert processed[0][0] == "loaded"
|
||||
@ -77,6 +116,7 @@ async def test_process_integration_platforms_import_fails(
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", _process_platform
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(processed) == 0
|
||||
assert "Unexpected error importing platform_to_check for loaded" in caplog.text
|
||||
@ -115,6 +155,7 @@ async def test_process_integration_platforms_import_fails_after_registered(
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", _process_platform
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(processed) == 1
|
||||
assert processed[0][0] == "loaded"
|
||||
@ -166,6 +207,7 @@ async def test_process_integration_platforms_non_compliant(
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", process_platform
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(processed) == 0
|
||||
assert "Exception in " in caplog.text
|
||||
@ -204,6 +246,7 @@ async def test_broken_integration(
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", _process_platform
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# This should never actually happen as the component cannot be
|
||||
# in hass.config.components without a loaded manifest
|
||||
@ -226,5 +269,6 @@ async def test_process_integration_platforms_no_integrations(
|
||||
await async_process_integration_platforms(
|
||||
hass, "platform_to_check", _process_platform
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(processed) == 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user