From f5f2848d94fb3df88c635ebbc6651f8fd1aa70f6 Mon Sep 17 00:00:00 2001 From: David Wu <133224895+David-Wu1119@users.noreply.github.com> Date: Mon, 7 Sep 2026 01:04:47 -0700 Subject: [PATCH] Type the dlna_dmr domain data with a HassKey (#181101) --- homeassistant/components/dlna_dmr/const.py | 10 +++++++++- homeassistant/components/dlna_dmr/data.py | 20 ++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/dlna_dmr/const.py b/homeassistant/components/dlna_dmr/const.py index cb308faea15f..14fd7b9ce96d 100644 --- a/homeassistant/components/dlna_dmr/const.py +++ b/homeassistant/components/dlna_dmr/const.py @@ -2,16 +2,24 @@ from collections.abc import Mapping import logging -from typing import Final +from typing import TYPE_CHECKING, Final from async_upnp_client.profiles.dlna import PlayMode as _PlayMode from homeassistant.components.media_player import MediaType, RepeatMode +from homeassistant.util.hass_dict import HassKey + +if TYPE_CHECKING: + from .data import DlnaDmrData LOGGER = logging.getLogger(__package__) DOMAIN: Final = "dlna_dmr" +# One DlnaDmrData owns the shared UPnP requester and event notifiers used by +# every config entry, so it is not per-entry state. +DOMAIN_DATA: HassKey[DlnaDmrData] = HassKey(DOMAIN) + CONF_LISTEN_PORT: Final = "listen_port" CONF_CALLBACK_URL_OVERRIDE: Final = "callback_url_override" CONF_POLL_AVAILABILITY: Final = "poll_availability" diff --git a/homeassistant/components/dlna_dmr/data.py b/homeassistant/components/dlna_dmr/data.py index 7b5a36fffe3f..fcc3c17cfe7f 100644 --- a/homeassistant/components/dlna_dmr/data.py +++ b/homeassistant/components/dlna_dmr/data.py @@ -1,9 +1,8 @@ """Data used by this integration.""" -# pylint: disable=home-assistant-use-runtime-data # Uses legacy hass.data[DOMAIN] pattern import asyncio from collections import defaultdict -from typing import NamedTuple, cast +from typing import NamedTuple from async_upnp_client.aiohttp import AiohttpNotifyServer, AiohttpSessionRequester from async_upnp_client.client import UpnpRequester @@ -14,7 +13,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant from homeassistant.helpers import aiohttp_client -from .const import DOMAIN, LOGGER +from .const import DOMAIN_DATA, LOGGER class EventListenAddr(NamedTuple): @@ -117,10 +116,15 @@ class DlnaDmrData: def get_domain_data(hass: HomeAssistant) -> DlnaDmrData: - """Obtain this integration's domain data, creating it if needed.""" - if DOMAIN in hass.data: - return cast(DlnaDmrData, hass.data[DOMAIN]) + """Obtain this integration's domain data, creating it if needed. - data = DlnaDmrData(hass) - hass.data[DOMAIN] = data + Creation is deferred to the first caller rather than done at setup, to + avoid building DlnaDmrData and its dependencies until a device is + actually connected to. This module is imported to run the config flow + for any DMR device discovered on the network, including ignored ones. + """ + if (data := hass.data.get(DOMAIN_DATA)) is not None: + return data + + data = hass.data[DOMAIN_DATA] = DlnaDmrData(hass) return data