Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure integration platform loader does not try to load same named platforms #133911

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions homeassistant/helpers/integration_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ def _async_integration_platform_component_loaded(
# First filter out platforms that the integration already processed.
integration_platforms_by_name: dict[str, IntegrationPlatform] = {}
for integration_platform in integration_platforms:
if component_name in integration_platform.seen_components:
platform_name = integration_platform.platform_name
if (
component_name in integration_platform.seen_components
or platform_name == integration.domain
):
continue
integration_platform.seen_components.add(component_name)
integration_platforms_by_name[integration_platform.platform_name] = (
integration_platform
)
integration_platforms_by_name[platform_name] = integration_platform

if not integration_platforms_by_name:
return
Expand Down Expand Up @@ -177,6 +179,8 @@ async def async_process_integration_platforms(

async_register_preload_platform(hass, platform_name)
top_level_components = hass.config.top_level_components.copy()
# Remove the platform itself from the list of components to process.
top_level_components.discard(platform_name)
process_job = HassJob(
catch_log_exception(
process_platform,
Expand Down Expand Up @@ -210,7 +214,7 @@ async def async_process_integration_platforms(
#
future = hass.async_create_task_internal(
_async_process_integration_platforms(
hass, platform_name, top_level_components.copy(), process_job
hass, platform_name, top_level_components, process_job
),
eager_start=True,
)
Expand Down
84 changes: 84 additions & 0 deletions tests/helpers/test_integration_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,87 @@ async def _process_platform(
await hass.async_block_till_done()

assert len(processed) == 0


async def test_process_integration_platforms_ignores_self_with_wait(
hass: HomeAssistant,
) -> None:
"""Test we do not try to load platforms with our name."""
platform_to_check_platform = Mock()
mock_platform(
hass, "platform_to_check.platform_to_check", platform_to_check_platform
)
hass.config.components.add("platform_to_check")

event_platform = Mock()
mock_platform(hass, "event.platform_to_check", event_platform)

processed = []

async def _process_platform(
hass: HomeAssistant, domain: str, platform: Any
) -> None:
"""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) == 0 # should not process platform_to_check.platform_to_check

hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: "event"})
await hass.async_block_till_done()

assert len(processed) == 1
assert processed[0][0] == "event"
assert processed[0][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) == 1


async def test_process_integration_platforms_ignores_self_without_wait(
hass: HomeAssistant,
) -> None:
"""Test we do not try to load platforms with our name."""
platform_to_check_platform = Mock()
mock_platform(
hass, "platform_to_check.platform_to_check", platform_to_check_platform
)
hass.config.components.add("platform_to_check")

event_platform = Mock()
mock_platform(hass, "event.platform_to_check", event_platform)

processed = []

async def _process_platform(
hass: HomeAssistant, domain: str, platform: Any
) -> None:
"""Process platform."""
processed.append((domain, platform))

await async_process_integration_platforms(
hass, "platform_to_check", _process_platform
)
await hass.async_block_till_done()

assert len(processed) == 0 # should not process platform_to_check.platform_to_check

hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: "event"})
await hass.async_block_till_done()

assert len(processed) == 1
assert processed[0][0] == "event"
assert processed[0][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) == 1
Loading