Ensure discovery can setup legacy device tracker platforms (#114101)

This commit is contained in:
J. Nick Koston 2024-03-24 07:38:05 -10:00 committed by GitHub
parent c5893f22bf
commit 6371b344b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 24 deletions

View file

@ -69,15 +69,7 @@ def is_on(hass: HomeAssistant, entity_id: str) -> bool:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the device tracker."""
#
# Legacy and platforms load in a non-awaited tracked task
# to ensure device tracker setup can continue and config
# entry integrations are not waiting for legacy device
# tracker platforms to be set up.
#
hass.async_create_task(
async_setup_legacy_integration(hass, config), eager_start=True
)
async_setup_legacy_integration(hass, config)
return True

View file

@ -201,9 +201,47 @@ def see(
hass.services.call(DOMAIN, SERVICE_SEE, data)
async def async_setup_integration(hass: HomeAssistant, config: ConfigType) -> None:
@callback
def async_setup_integration(hass: HomeAssistant, config: ConfigType) -> None:
"""Set up the legacy integration."""
# The tracker is loaded in the _async_setup_integration task so
# we create a future to avoid waiting on it here so that only
# async_platform_discovered will have to wait in the rare event
# a custom component still uses the legacy device tracker discovery.
tracker_future: asyncio.Future[DeviceTracker] = hass.loop.create_future()
async def async_platform_discovered(
p_type: str, info: dict[str, Any] | None
) -> None:
"""Load a platform."""
platform = await async_create_platform_type(hass, config, p_type, {})
if platform is None or platform.type != PLATFORM_TYPE_LEGACY:
return
tracker = await tracker_future
await platform.async_setup_legacy(hass, tracker, info)
discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)
#
# Legacy and platforms load in a non-awaited tracked task
# to ensure device tracker setup can continue and config
# entry integrations are not waiting for legacy device
# tracker platforms to be set up.
#
hass.async_create_task(
_async_setup_integration(hass, config, tracker_future), eager_start=True
)
async def _async_setup_integration(
hass: HomeAssistant,
config: ConfigType,
tracker_future: asyncio.Future[DeviceTracker],
) -> None:
"""Set up the legacy integration."""
tracker = await get_tracker(hass, config)
tracker_future.set_result(tracker)
async def async_see_service(call: ServiceCall) -> None:
"""Service to see a device."""
@ -227,19 +265,6 @@ async def async_setup_integration(hass: HomeAssistant, config: ConfigType) -> No
if setup_tasks:
await asyncio.wait(setup_tasks)
async def async_platform_discovered(
p_type: str, info: dict[str, Any] | None
) -> None:
"""Load a platform."""
platform = await async_create_platform_type(hass, config, p_type, {})
if platform is None or platform.type != PLATFORM_TYPE_LEGACY:
return
await platform.async_setup_legacy(hass, tracker, info)
discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)
# Clean up stale devices
cancel_update_stale = async_track_utc_time_change(
hass, tracker.async_update_stale, second=range(0, 60, 5)

View file

@ -235,7 +235,8 @@ async def test_discover_platform(
"""Test discovery of device_tracker demo platform."""
await async_setup_component(hass, "homeassistant", {})
await async_setup_component(hass, device_tracker.DOMAIN, {})
await hass.async_block_till_done()
# async_block_till_done is intentionally missing here so we
# can verify async_load_platform still works without it
with patch("homeassistant.components.device_tracker.legacy.update_config"):
await discovery.async_load_platform(
hass, device_tracker.DOMAIN, "demo", {"test_key": "test_val"}, {"bla": {}}
@ -251,6 +252,31 @@ async def test_discover_platform(
)
async def test_discover_platform_missing_platform(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test discovery of device_tracker missing platform."""
await async_setup_component(hass, "homeassistant", {})
await async_setup_component(hass, device_tracker.DOMAIN, {})
# async_block_till_done is intentionally missing here so we
# can verify async_load_platform still works without it
with patch("homeassistant.components.device_tracker.legacy.update_config"):
await discovery.async_load_platform(
hass,
device_tracker.DOMAIN,
"its_not_there",
{"test_key": "test_val"},
{"bla": {}},
)
await hass.async_block_till_done()
assert device_tracker.DOMAIN in hass.config.components
assert (
"Unable to prepare setup for platform 'its_not_there.device_tracker'"
in caplog.text
)
# This test should not generate an unhandled exception
async def test_update_stale(
hass: HomeAssistant,
mock_device_tracker_conf: list[legacy.Device],