Restore "Promote after dependencies in bootstrap" (#142001)

Revert "Revert "Promote after dependencies in bootstrap" (#141584)"

This reverts commit de1e06c39bce99f55ea36175e29cc1d76bc35836.
This commit is contained in:
Erik Montnemery 2025-04-04 23:26:43 +02:00 committed by GitHub
parent f9cd0f37f7
commit 1e55d4b613
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 25 deletions

View File

@ -859,8 +859,14 @@ async def _async_set_up_integrations(
integrations, all_integrations = await _async_resolve_domains_and_preload( integrations, all_integrations = await _async_resolve_domains_and_preload(
hass, config hass, config
) )
all_domains = set(all_integrations) # Detect all cycles
domains = set(integrations) integrations_after_dependencies = (
await loader.resolve_integrations_after_dependencies(
hass, all_integrations.values(), set(all_integrations)
)
)
all_domains = set(integrations_after_dependencies)
domains = set(integrations) & all_domains
_LOGGER.info( _LOGGER.info(
"Domains to be set up: %s | %s", "Domains to be set up: %s | %s",
@ -868,6 +874,8 @@ async def _async_set_up_integrations(
all_domains - domains, all_domains - domains,
) )
async_set_domains_to_be_loaded(hass, all_domains)
# Initialize recorder # Initialize recorder
if "recorder" in all_domains: if "recorder" in all_domains:
recorder.async_initialize_recorder(hass) recorder.async_initialize_recorder(hass)
@ -900,24 +908,12 @@ async def _async_set_up_integrations(
stage_dep_domains_unfiltered = { stage_dep_domains_unfiltered = {
dep dep
for domain in stage_domains for domain in stage_domains
for dep in all_integrations[domain].all_dependencies for dep in integrations_after_dependencies[domain]
if dep not in stage_domains if dep not in stage_domains
} }
stage_dep_domains = stage_dep_domains_unfiltered - hass.config.components stage_dep_domains = stage_dep_domains_unfiltered - hass.config.components
stage_all_domains = stage_domains | stage_dep_domains stage_all_domains = stage_domains | stage_dep_domains
stage_all_integrations = {
domain: all_integrations[domain] for domain in stage_all_domains
}
# Detect all cycles
stage_integrations_after_dependencies = (
await loader.resolve_integrations_after_dependencies(
hass, stage_all_integrations.values(), stage_all_domains
)
)
stage_all_domains = set(stage_integrations_after_dependencies)
stage_domains &= stage_all_domains
stage_dep_domains &= stage_all_domains
_LOGGER.info( _LOGGER.info(
"Setting up stage %s: %s | %s\nDependencies: %s | %s", "Setting up stage %s: %s | %s\nDependencies: %s | %s",
@ -928,8 +924,6 @@ async def _async_set_up_integrations(
stage_dep_domains_unfiltered - stage_dep_domains, stage_dep_domains_unfiltered - stage_dep_domains,
) )
async_set_domains_to_be_loaded(hass, stage_all_domains)
if timeout is None: if timeout is None:
await _async_setup_multi_components(hass, stage_all_domains, config) await _async_setup_multi_components(hass, stage_all_domains, config)
continue continue

View File

@ -252,8 +252,8 @@ async def test_setup_after_deps_all_present(hass: HomeAssistant) -> None:
@pytest.mark.parametrize("load_registries", [False]) @pytest.mark.parametrize("load_registries", [False])
async def test_setup_after_deps_in_stage_1_ignored(hass: HomeAssistant) -> None: async def test_setup_after_deps_in_stage_1(hass: HomeAssistant) -> None:
"""Test after_dependencies are ignored in stage 1.""" """Test after_dependencies are promoted in stage 1."""
# This test relies on this # This test relies on this
assert "cloud" in bootstrap.STAGE_1_INTEGRATIONS assert "cloud" in bootstrap.STAGE_1_INTEGRATIONS
order = [] order = []
@ -295,7 +295,7 @@ async def test_setup_after_deps_in_stage_1_ignored(hass: HomeAssistant) -> None:
assert "normal_integration" in hass.config.components assert "normal_integration" in hass.config.components
assert "cloud" in hass.config.components assert "cloud" in hass.config.components
assert order == ["cloud", "an_after_dep", "normal_integration"] assert order == ["an_after_dep", "normal_integration", "cloud"]
@pytest.mark.parametrize("load_registries", [False]) @pytest.mark.parametrize("load_registries", [False])
@ -304,7 +304,7 @@ async def test_setup_after_deps_manifests_are_loaded_even_if_not_setup(
) -> None: ) -> None:
"""Ensure we preload manifests for after deps even if they are not setup. """Ensure we preload manifests for after deps even if they are not setup.
Its important that we preload the after dep manifests even if they are not setup It's important that we preload the after dep manifests even if they are not setup
since we will always have to check their requirements since any integration since we will always have to check their requirements since any integration
that lists an after dep may import it and we have to ensure requirements are that lists an after dep may import it and we have to ensure requirements are
up to date before the after dep can be imported. up to date before the after dep can be imported.
@ -371,7 +371,7 @@ async def test_setup_after_deps_manifests_are_loaded_even_if_not_setup(
assert "an_after_dep" not in hass.config.components assert "an_after_dep" not in hass.config.components
assert "an_after_dep_of_after_dep" not in hass.config.components assert "an_after_dep_of_after_dep" not in hass.config.components
assert "an_after_dep_of_after_dep_of_after_dep" not in hass.config.components assert "an_after_dep_of_after_dep_of_after_dep" not in hass.config.components
assert order == ["cloud", "normal_integration"] assert order == ["normal_integration", "cloud"]
assert loader.async_get_loaded_integration(hass, "an_after_dep") is not None assert loader.async_get_loaded_integration(hass, "an_after_dep") is not None
assert ( assert (
loader.async_get_loaded_integration(hass, "an_after_dep_of_after_dep") loader.async_get_loaded_integration(hass, "an_after_dep_of_after_dep")
@ -456,9 +456,9 @@ async def test_setup_frontend_before_recorder(hass: HomeAssistant) -> None:
assert order == [ assert order == [
"http", "http",
"an_after_dep",
"frontend", "frontend",
"recorder", "recorder",
"an_after_dep",
"normal_integration", "normal_integration",
] ]
@ -1577,8 +1577,10 @@ async def test_no_base_platforms_loaded_before_recorder(hass: HomeAssistant) ->
assert not isinstance(integrations_or_excs, Exception) assert not isinstance(integrations_or_excs, Exception)
integrations[domain] = integration integrations[domain] = integration
integrations_all_dependencies = await loader.resolve_integrations_dependencies( integrations_all_dependencies = (
hass, integrations.values() await loader.resolve_integrations_after_dependencies(
hass, integrations.values(), ignore_exceptions=True
)
) )
all_integrations = integrations.copy() all_integrations = integrations.copy()
all_integrations.update( all_integrations.update(