Adjust hue to not access DeviceEntry.config_entries (#181932)

This commit is contained in:
Erik Montnemery
2026-09-11 12:25:36 +02:00
committed by GitHub
parent b385fc9f86
commit e2418c5973
2 changed files with 91 additions and 3 deletions
+17 -3
View File
@@ -47,8 +47,9 @@ async def async_validate_trigger_config(
) is None:
raise InvalidDeviceAutomationConfig(f"Device ID {device_id} is not valid")
entry_ids = _device_config_entry_ids(device_entry)
for entry in entries:
if entry.entry_id not in device_entry.config_entries:
if entry.entry_id not in entry_ids:
continue
bridge = entry.runtime_data
if bridge.api_version == 1:
@@ -72,11 +73,12 @@ async def async_attach_trigger(
) is None:
raise InvalidDeviceAutomationConfig(f"Device ID {device_id} is not valid")
entry_ids = _device_config_entry_ids(device_entry)
entry: HueConfigEntry | None = next(
(
entry
for entry in hass.config_entries.async_entries(DOMAIN)
if entry.entry_id in device_entry.config_entries
if entry.entry_id in entry_ids
),
None,
)
@@ -112,8 +114,9 @@ async def async_get_triggers(
# Iterate all config entries for this device
# and work out the bridge version
entry_ids = _device_config_entry_ids(device_entry)
for entry in entries:
if entry.entry_id not in device_entry.config_entries:
if entry.entry_id not in entry_ids:
continue
bridge = entry.runtime_data
@@ -123,6 +126,17 @@ async def async_get_triggers(
return []
def _device_config_entry_ids(device_entry: dr.DeviceEntry) -> set[str]:
"""Return the ids of the config entries the device belongs to.
A restored composite has no single owning config entry; the union of the
split devices' config entries covers every owning domain.
"""
if device_entry.is_composite_device:
return device_entry.config_entries
return {device_entry.config_entry_id}
async def _async_attach_bridge_trigger(
entry: HueConfigEntry,
device_entry: dr.DeviceEntry,
@@ -4,6 +4,7 @@ from typing import Any
from unittest.mock import Mock, patch
from aiohue.v2.models.button import ButtonEvent
import attr
import pytest
from pytest_unordered import unordered
@@ -159,6 +160,79 @@ async def test_get_triggers(
assert triggers == unordered(expected_triggers)
async def test_get_triggers_for_composite_device_id(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_bridge_v2: Mock,
v2_resources_test_data: JsonArrayType,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test we get the expected triggers for a pre-migration composite device id."""
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
await setup_platform(
hass, mock_bridge_v2, [Platform.BINARY_SENSOR, Platform.SENSOR]
)
hue_wall_switch_device = device_registry.async_get_device_by_identifier(
(hue.DOMAIN, WALL_SWITCH_DEVICE_ID), mock_bridge_v2.config_entry.entry_id
)
other_entry = MockConfigEntry(domain="other")
other_entry.add_to_hass(hass)
other_device = device_registry.async_get_or_create(
config_entry_id=other_entry.entry_id, identifiers={("other", "1")}
)
composite_id = "composite00000000000000000000ab"
# Simulate a migration split: both devices carry the pre-migration composite id
device_registry._devices[hue_wall_switch_device.id] = attr.evolve(
hue_wall_switch_device, composite_device_id=composite_id
)
device_registry._devices[other_device.id] = attr.evolve(
other_device, composite_device_id=composite_id
)
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, composite_id
)
hue_bat_sensor = entity_registry.async_get(
"sensor.wall_switch_with_2_controls_battery"
)
trigger_batt = {
"platform": "device",
"domain": "sensor",
"device_id": composite_id,
"type": "battery_level",
"entity_id": hue_bat_sensor.id,
"metadata": {"secondary": True},
}
expected_triggers = [
trigger_batt,
*(
{
"platform": "device",
"domain": hue.DOMAIN,
"device_id": composite_id,
"unique_id": resource_id,
"type": event_type.value,
"subtype": control_id,
"metadata": {},
}
for event_type in (
ButtonEvent.INITIAL_PRESS,
ButtonEvent.LONG_RELEASE,
ButtonEvent.REPEAT,
ButtonEvent.LONG_PRESS,
ButtonEvent.SHORT_RELEASE,
)
for control_id, resource_id in (
(1, "c658d3d8-a013-4b81-8ac6-78b248537e70"),
(2, "be1eb834-bdf5-4d26-8fba-7b1feaa83a9d"),
)
),
]
assert triggers == unordered(expected_triggers)
async def test_get_triggers_for_removed_device(
hass: HomeAssistant,
mock_bridge_v2: Mock,