Update home-assistant-parameter-type for async_remove_config_entry_device (#179371)

This commit is contained in:
Erik Montnemery
2026-08-18 09:35:39 +02:00
committed by GitHub
parent 8f956e93dd
commit d82f2e2066
67 changed files with 414 additions and 83 deletions
+3 -1
View File
@@ -92,7 +92,9 @@ async def async_setup_august(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: AugustConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: AugustConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove august config entry from a device if its no longer present."""
return not any(
+1 -1
View File
@@ -128,7 +128,7 @@ def _async_remove_old_device_identifiers(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: BondConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: BondConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove bond config entry from a device."""
data = config_entry.runtime_data
+1 -1
View File
@@ -102,7 +102,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: CastConfigEntry) -> Non
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: CastConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: CastConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove cast config entry from a device.
@@ -57,7 +57,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: CoolmasterConfigEntry)
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: CoolmasterConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return not device_entry.identifiers.intersection(
@@ -15,7 +15,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from .const import DOMAIN, PLATFORMS
@@ -91,7 +91,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: DevoloHomeControlConfigEntry,
device_entry: DeviceEntry,
device_entry: AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return True
@@ -7,7 +7,7 @@ from eheimdigital.device import EheimDigitalDevice
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from .const import DOMAIN
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
@@ -61,7 +61,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: EheimDigitalConfigEntry,
device_entry: DeviceEntry,
device_entry: AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return not any(
@@ -106,7 +106,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: EnphaseConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: EnphaseConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: EnphaseConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove an enphase_envoy config entry from a device."""
dev_ids = {dev_id[1] for dev_id in device_entry.identifiers if dev_id[0] == DOMAIN}
+2 -2
View File
@@ -22,7 +22,7 @@ from homeassistant.const import CONF_PASSWORD, CONF_URL, CONF_USERNAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceEntry, DeviceInfo
from homeassistant.helpers.device_registry import AnyDeviceEntry, DeviceInfo
from homeassistant.util import slugify
from .const import CONF_IMPORT_PLUGINS, DOMAIN
@@ -353,7 +353,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: FibaroConfigEntry) -> b
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: FibaroConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: FibaroConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a device entry from fibaro integration.
@@ -154,7 +154,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: FjaraskupanConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
for service_info in async_discovered_service_info(hass, False):
@@ -5,7 +5,7 @@ from requests.exceptions import ConnectionError as RequestConnectionError, HTTPE
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, UnitOfTemperature
from homeassistant.core import Event, HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.entity_registry import RegistryEntry, async_migrate_entries
from .const import DOMAIN, LOGGER, PLATFORMS
@@ -66,7 +66,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: FritzboxConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: FritzboxConfigEntry, device: DeviceEntry
hass: HomeAssistant, entry: FritzboxConfigEntry, device: AnyDeviceEntry
) -> bool:
"""Remove Fritzbox config entry from a device."""
coordinator = entry.runtime_data
+3 -1
View File
@@ -66,7 +66,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: FroniusConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: FroniusConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: FroniusConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return True
+4 -1
View File
@@ -72,9 +72,12 @@ async def async_unload_entry(hass: HomeAssistant, entry: HeosConfigEntry) -> boo
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: HeosConfigEntry, device: dr.DeviceEntry
hass: HomeAssistant, entry: HeosConfigEntry, device: dr.AnyDeviceEntry
) -> bool:
"""Remove config entry from device if no longer present."""
if not isinstance(device, dr.DeviceEntry):
# This integration does not create child devices.
return False
return not any(
(domain, key)
for domain, key in device.identifiers
+1 -1
View File
@@ -92,7 +92,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: HiveConfigEntry) -> Non
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: HiveConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: HiveConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
return True
@@ -123,7 +123,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove homekit_controller config entry from a device."""
hkid = config_entry.data["AccessoryPairingID"]
+2 -2
View File
@@ -3,7 +3,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from .const import DOMAIN, PLATFORMS
from .coordinator import IBeaconCoordinator
@@ -27,7 +27,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: IBeaconConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: IBeaconConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove iBeacon config entry from a device."""
coordinator = config_entry.runtime_data
+1 -1
View File
@@ -248,7 +248,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: IsyConfigEntry) -> bool
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: IsyConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove ISY config entry from a device."""
return not device_entry.identifiers.intersection(
@@ -81,7 +81,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: JellyfinConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: JellyfinConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: JellyfinConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove device from a config entry."""
coordinator = config_entry.runtime_data
@@ -34,7 +34,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
@@ -142,7 +142,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
+2 -2
View File
@@ -13,7 +13,7 @@ from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.reload import async_integration_yaml_config
from homeassistant.helpers.storage import STORAGE_DIR
from homeassistant.helpers.typing import ConfigType
@@ -278,7 +278,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
knx_module = hass.data[KNX_MODULE_KEY]
@@ -10,7 +10,7 @@ from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN
@@ -97,7 +97,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: LitterRobotConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, entry: LitterRobotConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
return not any(
+1 -1
View File
@@ -206,7 +206,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: LookinConfigEntry) -> b
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: LookinConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, entry: LookinConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove lookin config entry from a device."""
data = entry.runtime_data
@@ -522,7 +522,7 @@ def _id_to_identifier(lutron_id: str) -> tuple[str, str]:
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: LutronCasetaConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, entry: LutronCasetaConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove lutron_caseta config entry from a device."""
data = entry.runtime_data
+6 -1
View File
@@ -398,9 +398,14 @@ def _remove_via_devices(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: MatterConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: MatterConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
if not isinstance(device_entry, dr.DeviceEntry):
# This integration does not create child devices.
return False
node = get_node_from_device_entry(hass, device_entry)
if node is None:
+1 -1
View File
@@ -105,7 +105,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: MieleConfigEntry) -> bo
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: MieleConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: MieleConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
return not any(
+2 -2
View File
@@ -30,7 +30,7 @@ from homeassistant.helpers import (
event as ev,
issue_registry as ir,
)
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import async_get_platforms
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
@@ -689,7 +689,7 @@ def is_connected(hass: HomeAssistant) -> bool:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove MQTT config entry from a device."""
from . import device_automation # noqa: PLC0415
@@ -294,7 +294,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: MusicAssistantConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
player_id = next(
@@ -9,7 +9,7 @@ from mysensors import BaseAsyncGateway
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry, DeviceEntry
from .const import (
ATTR_DEVICES,
@@ -68,9 +68,12 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a MySensors config entry from a device."""
if not isinstance(device_entry, DeviceEntry):
# This integration does not create child devices.
return False
gateway: BaseAsyncGateway = hass.data[DOMAIN][MYSENSORS_GATEWAYS][
config_entry.entry_id
]
@@ -17,7 +17,7 @@ from homeassistant.helpers.config_entry_oauth2_flow import (
OAuth2Session,
async_get_config_entry_implementation,
)
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from .api import AsyncConfigEntryAuth
from .const import DOMAIN, OAUTH2_SCOPES
@@ -119,7 +119,7 @@ def create_devices(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: MyUplinkConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: MyUplinkConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove myuplink config entry from a device."""
+2 -2
View File
@@ -22,7 +22,7 @@ from homeassistant.helpers.config_entry_oauth2_flow import (
OAuth2Session,
async_get_config_entry_implementation,
)
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.start import async_at_started
@@ -147,7 +147,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: NetatmoConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: NetatmoConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: NetatmoConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
homes = config_entry.runtime_data.account.homes.values()
+6 -1
View File
@@ -112,9 +112,14 @@ async def async_unload_entry(hass: HomeAssistant, entry: NetgearConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: NetgearConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: NetgearConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a device from a config entry."""
if not isinstance(device_entry, dr.DeviceEntry):
# This integration does not create child devices.
return False
router = config_entry.runtime_data.router
device_mac = None
+1 -1
View File
@@ -82,7 +82,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: NexiaConfigEntry) -> bo
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: NexiaConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, entry: NexiaConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove a nexia config entry from a device."""
coordinator = entry.runtime_data
+1 -1
View File
@@ -168,7 +168,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: NutConfigEntry) -> bool
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: NutConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove NUT config entry from a device."""
return not any(
+3 -1
View File
@@ -43,7 +43,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: OneWireConfigEntry) -> b
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: OneWireConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: OneWireConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
onewire_hub = config_entry.runtime_data
+2 -2
View File
@@ -3,7 +3,7 @@
from homeassistant.const import CONF_NAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from .const import DOMAIN
from .coordinator import OpenRGBConfigEntry, OpenRGBCoordinator
@@ -51,7 +51,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: OpenRGBConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: OpenRGBConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, entry: OpenRGBConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Allows removal of device if it is no longer connected."""
coordinator = entry.runtime_data
@@ -21,7 +21,7 @@ from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.helpers.aiohttp_client import async_create_clientsession
import homeassistant.helpers.config_validation as cv
import homeassistant.helpers.device_registry as dr
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
import homeassistant.helpers.entity_registry as er
from homeassistant.helpers.start import async_at_started
from homeassistant.helpers.typing import ConfigType
@@ -229,7 +229,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: PortainerConfigEntry)
async def async_remove_config_entry_device(
hass: HomeAssistant,
entry: PortainerConfigEntry,
device: DeviceEntry,
device: AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
coordinator = entry.runtime_data
+3 -1
View File
@@ -51,7 +51,9 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: RenaultConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: RenaultConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return not device_entry.identifiers.intersection(
+4 -1
View File
@@ -348,9 +348,12 @@ async def async_remove_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ReolinkConfigEntry, device: dr.DeviceEntry
hass: HomeAssistant, config_entry: ReolinkConfigEntry, device: dr.AnyDeviceEntry
) -> bool:
"""Remove a device from a config entry."""
if not isinstance(device, dr.DeviceEntry):
# This integration does not create child devices.
return False
host: ReolinkHost = config_entry.runtime_data.host
(_device_uid, ch, is_chime) = get_device_uid_and_ch(device, host)
+1 -1
View File
@@ -447,7 +447,7 @@ def get_device_tuple_from_identifiers(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove config entry from a device.
+1 -1
View File
@@ -85,7 +85,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: RingConfigEntry) -> boo
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: RingConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, entry: RingConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
return True
+1 -1
View File
@@ -299,7 +299,7 @@ async def update_listener(hass: HomeAssistant, entry: ScrapeConfigEntry) -> None
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: ConfigEntry, device: dr.DeviceEntry
hass: HomeAssistant, entry: ConfigEntry, device: dr.AnyDeviceEntry
) -> bool:
"""Remove Scrape config entry from a device."""
entity_registry = er.async_get(hass)
+2 -2
View File
@@ -11,7 +11,7 @@ from homeassistant.helpers import (
device_registry as dr,
entity_registry as er,
)
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN, LOGGER, PLATFORMS
@@ -88,7 +88,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: SensiboConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: SensiboConfigEntry, device: DeviceEntry
hass: HomeAssistant, entry: SensiboConfigEntry, device: AnyDeviceEntry
) -> bool:
"""Remove Sensibo config entry from a device."""
entity_registry = er.async_get(hass)
@@ -37,7 +37,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: SlimProtoConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: SlimProtoConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return True
+1 -1
View File
@@ -724,7 +724,7 @@ class SonosDiscoveryManager:
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: SonosConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: SonosConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove Sonos config entry from a device."""
known_devices = config_entry.runtime_data.discovered.keys()
@@ -28,7 +28,7 @@ from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
DeviceEntry,
AnyDeviceEntry,
DeviceEntryType,
)
from homeassistant.helpers.dispatcher import async_dispatcher_send
@@ -272,9 +272,12 @@ async def async_unload_entry(hass: HomeAssistant, entry: SqueezeboxConfigEntry)
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: SqueezeboxConfigEntry,
device_entry: DeviceEntry,
device_entry: AnyDeviceEntry,
) -> bool:
"""Allow removal of a Squeezebox player only if its coordinator is unavailable."""
if not isinstance(device_entry, dr.DeviceEntry):
# This integration does not create child devices.
return False
if device_entry.entry_type is DeviceEntryType.SERVICE:
raise HomeAssistantError(
f"Cannot remove Lyrion Music Server '{device_entry.name}' directly. "
@@ -96,7 +96,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: SwitcherConfigEntry) ->
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: SwitcherConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: SwitcherConfigEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return not device_entry.identifiers.intersection(
@@ -204,7 +204,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant, entry: SynologyDSMConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, entry: SynologyDSMConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove synology_dsm config entry from a device."""
data = entry.runtime_data
+4 -1
View File
@@ -160,9 +160,12 @@ async def async_setup_device(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove Tasmota config entry from a device."""
if not isinstance(device_entry, dr.DeviceEntry):
# This integration does not create child devices.
return False
connections = device_entry.connections
macs = [c[1] for c in connections if c[0] == CONNECTION_NETWORK_MAC]
+5 -2
View File
@@ -7,7 +7,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.storage import Store
from homeassistant.helpers.typing import ConfigType
@@ -84,9 +84,12 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: UnifiConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: UnifiConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove config entry from a device."""
if not isinstance(device_entry, dr.DeviceEntry):
# This integration does not create child devices.
return False
hub = config_entry.runtime_data
return not any(
identifier in hub.api.devices for _, identifier in device_entry.connections
@@ -237,9 +237,12 @@ async def async_remove_entry(hass: HomeAssistant, entry: UFPConfigEntry) -> None
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: UFPConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: UFPConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove ufp config entry from a device."""
if not isinstance(device_entry, dr.DeviceEntry):
# This integration does not create child devices.
return False
unifi_macs = {
_async_unifi_mac_from_hass(connection[1])
for connection in device_entry.connections
@@ -43,7 +43,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: UptimeKumaConfigEntry) -
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: UptimeKumaConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a stale device from a config entry."""
+1 -1
View File
@@ -136,7 +136,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: VelbusConfigEntry) -> N
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: VelbusConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Allow removing a Velbus device and its sub-devices.
+2 -2
View File
@@ -14,7 +14,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN
@@ -136,7 +136,7 @@ async def async_migrate_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: VesyncConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: VesyncConfigEntry, device_entry: AnyDeviceEntry
) -> bool:
"""Remove a config entry from a device."""
manager = config_entry.runtime_data.manager
@@ -70,7 +70,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: VictronGxConfigEntry) -
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: VictronGxConfigEntry,
device_entry: dr.DeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
"""Remove a device from the config entry if the device is no longer known."""
hub: Hub = config_entry.runtime_data
+1 -1
View File
@@ -123,7 +123,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: VoipConfigEntry) -> boo
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove device from a config entry."""
return True
@@ -8,7 +8,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.start import async_at_started
@@ -83,7 +83,7 @@ async def async_unload_entry(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: WeatherFlowConfigEntry,
device_entry: DeviceEntry,
device_entry: AnyDeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
client = config_entry.runtime_data
+1 -1
View File
@@ -84,7 +84,7 @@ async def async_setup_yale(
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: YaleConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: YaleConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
"""Remove yale config entry from a device if its no longer present."""
return not any(
@@ -142,7 +142,7 @@ _FUNCTION_MATCH: dict[str, list[TypeHintMatch]] = {
arg_types={
0: "HomeAssistant",
1: "ConfigEntry",
2: "DeviceEntry",
2: "AnyDeviceEntry",
},
return_type="bool",
mandatory=True,
@@ -435,7 +435,7 @@ async def test_remove_device(
can_remove = False
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
return can_remove
@@ -521,7 +521,7 @@ async def test_remove_device_fails(
ws_client = await hass_ws_client(hass)
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
return True
@@ -626,7 +626,7 @@ async def test_remove_device_if_integration_removes(
can_remove = False
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
if can_remove:
device_registry.async_remove_device(device_entry.id)
@@ -759,7 +759,7 @@ async def test_remove_config_entry_from_device_deprecated_config_entry_mismatch(
ws_client = await hass_ws_client(hass)
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
return True
@@ -1070,7 +1070,7 @@ async def test_remove_config_entry_from_child_device(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: ConfigEntry,
device_entry: dr.DeviceEntry | dr.ChildDeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
removed_devices.append(device_entry.id)
return can_remove
@@ -1117,7 +1117,7 @@ async def test_remove_config_entry_from_parent_with_children(
async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: ConfigEntry,
device_entry: dr.DeviceEntry | dr.ChildDeviceEntry,
device_entry: dr.AnyDeviceEntry,
) -> bool:
consulted_devices.append(device_entry.id)
return True
+32
View File
@@ -200,6 +200,38 @@ async def test_device_info(
assert device.model == "Speaker"
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry,
config_entry: MockConfigEntry,
controller: MockHeos,
) -> None:
"""Test removing an unexpected child device is rejected."""
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
assert await async_setup_component(hass, "config", {})
parent_device = device_registry.async_get_device_by_identifier(
(DOMAIN, "1"), config_entry.entry_id
)
assert parent_device is not None
child_device = device_registry.async_get_or_create_child(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
async def test_device_id_migration(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
+28
View File
@@ -960,6 +960,34 @@ async def test_remove_config_entry_device_no_node(
assert not device_registry.async_get(device_entry.id)
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry,
integration: MockConfigEntry,
) -> None:
"""Test that removing an unexpected child device is rejected."""
assert await async_setup_component(hass, "config", {})
parent_device = device_registry.async_get_or_create(
config_entry_id=integration.entry_id,
identifiers={(DOMAIN, "test_parent_device")},
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=integration.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
@pytest.mark.parametrize(
("matter_ws_url", "expected"),
[
+30
View File
@@ -99,3 +99,33 @@ async def test_remove_config_entry_device(
)
assert not entity_registry.async_get(entity_id)
assert not hass.states.get(entity_id)
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
integration: MockConfigEntry,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test that removing an unexpected child device is rejected."""
config_entry = integration
assert await async_setup_component(hass, "config", {})
parent_device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_parent_device")},
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
+57
View File
@@ -14,8 +14,10 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
from tests.typing import WebSocketGenerator
SERIAL = "5ER1AL0000001"
HOST = "10.0.0.1"
@@ -87,3 +89,58 @@ async def test_tracked_device_links_to_router(
)
assert tracked_device is not None
assert tracked_device.via_device_id == router_device.id
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test removing an unexpected child device is rejected."""
entry = MockConfigEntry(
domain=DOMAIN,
data={
CONF_HOST: HOST,
CONF_PORT: 80,
CONF_SSL: False,
CONF_USERNAME: "admin",
CONF_PASSWORD: "password",
},
unique_id=SERIAL,
)
entry.add_to_hass(hass)
with patch("homeassistant.components.netgear.router.Netgear") as netgear_mock:
api = netgear_mock.return_value
api.login_try_port = Mock(return_value=True)
api.get_info = Mock(return_value=ROUTER_INFOS)
api.port = 80
api.ssl = False
api.get_attached_devices_2 = Mock(return_value=[TRACKED_DEVICE])
api.get_traffic_meter = Mock(return_value=None)
api.get_new_speed_test_result = Mock(return_value=None)
api.check_new_firmware = Mock(return_value=None)
api.get_system_info = Mock(return_value=None)
api.check_ethernet_link = Mock(return_value=None)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert await async_setup_component(hass, "config", {})
router_device = device_registry.async_get_device_by_identifier(
(DOMAIN, SERIAL), entry.entry_id
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=router_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
+34
View File
@@ -339,6 +339,40 @@ async def test_removing_chime(
assert sorted(device_models) == sorted(expected_models)
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
config_entry: MockConfigEntry,
reolink_host: MagicMock,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test removing an unexpected child device is rejected."""
reolink_host.channels = [0]
assert await async_setup_component(hass, "config", {})
with patch("homeassistant.components.reolink.PLATFORMS", [Platform.SWITCH]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
parent_device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_parent_device")},
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
async def test_via_device_id_chain(
hass: HomeAssistant,
config_entry: MockConfigEntry,
+14
View File
@@ -236,3 +236,17 @@ async def test_remove_device_allowed_stale_player(
)
result = await async_remove_config_entry_device(hass, entry, device)
assert result is True
async def test_remove_device_rejects_child_device(
hass: HomeAssistant,
setup_squeezebox: MockConfigEntry,
) -> None:
"""Test that removal is rejected for an unexpected child device."""
entry = setup_squeezebox
child_device = dr.ChildDeviceEntry(
config_entry_id=entry.entry_id,
parent_device_id="mock-parent-device",
)
result = await async_remove_config_entry_device(hass, entry, child_device)
assert result is False
+32 -1
View File
@@ -4,6 +4,8 @@ import copy
import json
from unittest.mock import call
import pytest
from homeassistant.components.tasmota.const import DEFAULT_PREFIX, DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
@@ -92,7 +94,7 @@ async def test_device_remove_non_tasmota_device(
assert await async_setup_component(hass, "config", {})
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.AnyDeviceEntry
) -> bool:
return True
@@ -193,3 +195,32 @@ async def test_tasmota_ws_remove_discovered_device(
)
is None
)
@pytest.mark.usefixtures("mqtt_mock", "setup_tasmota")
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test removing an unexpected child device is rejected."""
assert await async_setup_component(hass, "config", {})
config_entry = hass.config_entries.async_entries(DOMAIN)[0]
parent_device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_parent_device")},
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
+30
View File
@@ -12,6 +12,7 @@ from homeassistant.components.unifi.const import (
CONF_ALLOW_UPTIME_SENSORS,
CONF_TRACK_CLIENTS,
CONF_TRACK_DEVICES,
DOMAIN,
)
from homeassistant.components.unifi.errors import AuthenticationRequired, CannotConnect
from homeassistant.config_entries import ConfigEntryState
@@ -211,3 +212,32 @@ async def test_remove_config_entry_device(
assert not device_registry.async_get_device_by_connection(
(dr.CONNECTION_NETWORK_MAC, client_payload[1]["mac"]), config_entry.entry_id
)
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry,
config_entry_factory: ConfigEntryFactoryType,
) -> None:
"""Test removing an unexpected child device is rejected."""
config_entry = await config_entry_factory()
assert await async_setup_component(hass, "config", {})
parent_device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_parent_device")},
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
@@ -423,6 +423,36 @@ async def test_device_remove_devices_nvr(
assert not response["success"]
async def test_remove_config_entry_device_rejects_child_device(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry,
ufp: MockUFPFixture,
light: Light,
) -> None:
"""Test removing an unexpected child device is rejected."""
await init_entry(hass, ufp, [light])
assert await async_setup_component(hass, "config", {})
parent_device = device_registry.async_get_or_create(
config_entry_id=ufp.entry.entry_id,
identifiers={(DOMAIN, "test_parent_device")},
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=ufp.entry.entry_id,
identifiers={(DOMAIN, "test_child_device")},
parent_device_id=parent_device.id,
)
client = await hass_ws_client(hass)
response = await client.remove_device(child_device.id)
assert not response["success"]
assert (
response["error"]["message"]
== "Failed to remove device entry, rejected by integration"
)
assert device_registry.async_get(child_device.id)
@pytest.mark.parametrize(
("mock_entries", "expected_result"),
[