mirror of
https://github.com/home-assistant/core.git
synced 2025-09-04 20:31:36 +02:00
Adjust device disabled_by flag when changing config entry (#151155)
This commit is contained in:
@@ -129,9 +129,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
||||||
and not all_disabled
|
and not all_disabled
|
||||||
):
|
):
|
||||||
# Device and entity registries don't update the disabled_by flag
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# when moving a device or entity from one config entry to another,
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# so we need to do it manually.
|
# config entry, but we want to set it to DEVICE or USER instead,
|
||||||
entity_disabled_by = (
|
entity_disabled_by = (
|
||||||
er.RegistryEntryDisabler.DEVICE
|
er.RegistryEntryDisabler.DEVICE
|
||||||
if device
|
if device
|
||||||
@@ -146,9 +146,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if device is not None:
|
if device is not None:
|
||||||
# Device and entity registries don't update the disabled_by flag when
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# moving a device or entity from one config entry to another, so we
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# need to do it manually.
|
# config entry, but we want to set it to USER instead,
|
||||||
device_disabled_by = device.disabled_by
|
device_disabled_by = device.disabled_by
|
||||||
if (
|
if (
|
||||||
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
||||||
|
@@ -260,9 +260,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
||||||
and not all_disabled
|
and not all_disabled
|
||||||
):
|
):
|
||||||
# Device and entity registries don't update the disabled_by flag
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# when moving a device or entity from one config entry to another,
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# so we need to do it manually.
|
# config entry, but we want to set it to DEVICE or USER instead,
|
||||||
entity_disabled_by = (
|
entity_disabled_by = (
|
||||||
er.RegistryEntryDisabler.DEVICE
|
er.RegistryEntryDisabler.DEVICE
|
||||||
if device
|
if device
|
||||||
@@ -277,9 +277,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if device is not None:
|
if device is not None:
|
||||||
# Device and entity registries don't update the disabled_by flag when
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# moving a device or entity from one config entry to another, so we
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# need to do it manually.
|
# config entry, but we want to set it to USER instead,
|
||||||
device_disabled_by = device.disabled_by
|
device_disabled_by = device.disabled_by
|
||||||
if (
|
if (
|
||||||
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
||||||
|
@@ -145,9 +145,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
||||||
and not all_disabled
|
and not all_disabled
|
||||||
):
|
):
|
||||||
# Device and entity registries don't update the disabled_by flag
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# when moving a device or entity from one config entry to another,
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# so we need to do it manually.
|
# config entry, but we want to set it to DEVICE or USER instead,
|
||||||
entity_disabled_by = (
|
entity_disabled_by = (
|
||||||
er.RegistryEntryDisabler.DEVICE
|
er.RegistryEntryDisabler.DEVICE
|
||||||
if device
|
if device
|
||||||
@@ -162,9 +162,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if device is not None:
|
if device is not None:
|
||||||
# Device and entity registries don't update the disabled_by flag when
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# moving a device or entity from one config entry to another, so we
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# need to do it manually.
|
# config entry, but we want to set it to USER instead,
|
||||||
device_disabled_by = device.disabled_by
|
device_disabled_by = device.disabled_by
|
||||||
if (
|
if (
|
||||||
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
||||||
|
@@ -320,9 +320,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
entity_disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
||||||
and not all_disabled
|
and not all_disabled
|
||||||
):
|
):
|
||||||
# Device and entity registries don't update the disabled_by flag
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# when moving a device or entity from one config entry to another,
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# so we need to do it manually.
|
# config entry, but we want to set it to DEVICE or USER instead,
|
||||||
entity_disabled_by = (
|
entity_disabled_by = (
|
||||||
er.RegistryEntryDisabler.DEVICE
|
er.RegistryEntryDisabler.DEVICE
|
||||||
if device
|
if device
|
||||||
@@ -337,9 +337,9 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if device is not None:
|
if device is not None:
|
||||||
# Device and entity registries don't update the disabled_by flag when
|
# Device and entity registries will set the disabled_by flag to None
|
||||||
# moving a device or entity from one config entry to another, so we
|
# when moving a device or entity disabled by CONFIG_ENTRY to an enabled
|
||||||
# need to do it manually.
|
# config entry, but we want to set it to USER instead,
|
||||||
device_disabled_by = device.disabled_by
|
device_disabled_by = device.disabled_by
|
||||||
if (
|
if (
|
||||||
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
||||||
|
@@ -1115,6 +1115,16 @@ class DeviceRegistry(BaseRegistry[dict[str, list[dict[str, Any]]]]):
|
|||||||
config_entries_subentries = old.config_entries_subentries | {
|
config_entries_subentries = old.config_entries_subentries | {
|
||||||
add_config_entry_id: {add_config_subentry_id}
|
add_config_entry_id: {add_config_subentry_id}
|
||||||
}
|
}
|
||||||
|
# Enable the device if it was disabled by config entry and we're adding
|
||||||
|
# a non disabled config entry
|
||||||
|
if (
|
||||||
|
# mypy says add_config_entry can be None. That's impossible, because we
|
||||||
|
# raise above if that happens
|
||||||
|
not add_config_entry.disabled_by # type: ignore[union-attr]
|
||||||
|
and old.disabled_by is DeviceEntryDisabler.CONFIG_ENTRY
|
||||||
|
):
|
||||||
|
new_values["disabled_by"] = None
|
||||||
|
old_values["disabled_by"] = old.disabled_by
|
||||||
elif (
|
elif (
|
||||||
add_config_subentry_id
|
add_config_subentry_id
|
||||||
not in old.config_entries_subentries[add_config_entry_id]
|
not in old.config_entries_subentries[add_config_entry_id]
|
||||||
@@ -1157,6 +1167,22 @@ class DeviceRegistry(BaseRegistry[dict[str, list[dict[str, Any]]]]):
|
|||||||
|
|
||||||
config_entries = config_entries - {remove_config_entry_id}
|
config_entries = config_entries - {remove_config_entry_id}
|
||||||
|
|
||||||
|
# Disable the device if it is enabled and all remaining config entries
|
||||||
|
# are disabled
|
||||||
|
has_enabled_config_entries = any(
|
||||||
|
config_entry.disabled_by is None
|
||||||
|
for config_entry_id in config_entries
|
||||||
|
if (
|
||||||
|
config_entry := self.hass.config_entries.async_get_entry(
|
||||||
|
config_entry_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
)
|
||||||
|
if not has_enabled_config_entries and old.disabled_by is None:
|
||||||
|
new_values["disabled_by"] = DeviceEntryDisabler.CONFIG_ENTRY
|
||||||
|
old_values["disabled_by"] = old.disabled_by
|
||||||
|
|
||||||
if config_entries != old.config_entries:
|
if config_entries != old.config_entries:
|
||||||
new_values["config_entries"] = config_entries
|
new_values["config_entries"] = config_entries
|
||||||
old_values["config_entries"] = old.config_entries
|
old_values["config_entries"] = old.config_entries
|
||||||
|
@@ -156,6 +156,8 @@ async def test_migration_from_v1_to_v2(
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"config_entry_disabled_by",
|
"config_entry_disabled_by",
|
||||||
|
"device_disabled_by",
|
||||||
|
"entity_disabled_by",
|
||||||
"merged_config_entry_disabled_by",
|
"merged_config_entry_disabled_by",
|
||||||
"conversation_subentry_data",
|
"conversation_subentry_data",
|
||||||
"main_config_entry",
|
"main_config_entry",
|
||||||
@@ -163,6 +165,8 @@ async def test_migration_from_v1_to_v2(
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, None],
|
[ConfigEntryDisabler.USER, None],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, None],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, None],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -182,18 +186,20 @@ async def test_migration_from_v1_to_v2(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[None, ConfigEntryDisabler.USER],
|
[None, ConfigEntryDisabler.USER],
|
||||||
|
[None, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[None, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.claude",
|
"conversation_entity_id": "conversation.claude",
|
||||||
"device_disabled_by": DeviceEntryDisabler.USER,
|
"device_disabled_by": None,
|
||||||
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
"entity_disabled_by": None,
|
||||||
"device": 0,
|
"device": 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.claude_2",
|
"conversation_entity_id": "conversation.claude_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.USER,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -201,6 +207,8 @@ async def test_migration_from_v1_to_v2(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
ConfigEntryDisabler.USER,
|
ConfigEntryDisabler.USER,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -211,8 +219,8 @@ async def test_migration_from_v1_to_v2(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.claude_2",
|
"conversation_entity_id": "conversation.claude_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.CONFIG_ENTRY,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -225,6 +233,8 @@ async def test_migration_from_v1_disabled(
|
|||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
||||||
|
device_disabled_by: list[DeviceEntryDisabler | None],
|
||||||
|
entity_disabled_by: list[RegistryEntryDisabler | None],
|
||||||
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
||||||
conversation_subentry_data: list[dict[str, Any]],
|
conversation_subentry_data: list[dict[str, Any]],
|
||||||
main_config_entry: int,
|
main_config_entry: int,
|
||||||
@@ -264,7 +274,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="Anthropic",
|
manufacturer="Anthropic",
|
||||||
model="Claude",
|
model="Claude",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
disabled_by=DeviceEntryDisabler.CONFIG_ENTRY,
|
disabled_by=device_disabled_by[0],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -273,7 +283,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry,
|
config_entry=mock_config_entry,
|
||||||
device_id=device_1.id,
|
device_id=device_1.id,
|
||||||
suggested_object_id="claude",
|
suggested_object_id="claude",
|
||||||
disabled_by=RegistryEntryDisabler.CONFIG_ENTRY,
|
disabled_by=entity_disabled_by[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
device_2 = device_registry.async_get_or_create(
|
device_2 = device_registry.async_get_or_create(
|
||||||
@@ -283,6 +293,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="Anthropic",
|
manufacturer="Anthropic",
|
||||||
model="Claude",
|
model="Claude",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
|
disabled_by=device_disabled_by[1],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -291,6 +302,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry_2,
|
config_entry=mock_config_entry_2,
|
||||||
device_id=device_2.id,
|
device_id=device_2.id,
|
||||||
suggested_object_id="claude",
|
suggested_object_id="claude",
|
||||||
|
disabled_by=entity_disabled_by[1],
|
||||||
)
|
)
|
||||||
|
|
||||||
devices = [device_1, device_2]
|
devices = [device_1, device_2]
|
||||||
|
@@ -576,6 +576,8 @@ async def test_migration_from_v1(
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"config_entry_disabled_by",
|
"config_entry_disabled_by",
|
||||||
|
"device_disabled_by",
|
||||||
|
"entity_disabled_by",
|
||||||
"merged_config_entry_disabled_by",
|
"merged_config_entry_disabled_by",
|
||||||
"conversation_subentry_data",
|
"conversation_subentry_data",
|
||||||
"main_config_entry",
|
"main_config_entry",
|
||||||
@@ -583,6 +585,8 @@ async def test_migration_from_v1(
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, None],
|
[ConfigEntryDisabler.USER, None],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, None],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, None],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -602,18 +606,20 @@ async def test_migration_from_v1(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[None, ConfigEntryDisabler.USER],
|
[None, ConfigEntryDisabler.USER],
|
||||||
|
[None, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[None, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.google_generative_ai_conversation",
|
"conversation_entity_id": "conversation.google_generative_ai_conversation",
|
||||||
"device_disabled_by": DeviceEntryDisabler.USER,
|
"device_disabled_by": None,
|
||||||
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
"entity_disabled_by": None,
|
||||||
"device": 0,
|
"device": 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.google_generative_ai_conversation_2",
|
"conversation_entity_id": "conversation.google_generative_ai_conversation_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.USER,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -621,6 +627,8 @@ async def test_migration_from_v1(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
ConfigEntryDisabler.USER,
|
ConfigEntryDisabler.USER,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -631,8 +639,8 @@ async def test_migration_from_v1(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.google_generative_ai_conversation_2",
|
"conversation_entity_id": "conversation.google_generative_ai_conversation_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.CONFIG_ENTRY,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -645,6 +653,8 @@ async def test_migration_from_v1_disabled(
|
|||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
||||||
|
device_disabled_by: list[DeviceEntryDisabler | None],
|
||||||
|
entity_disabled_by: list[RegistryEntryDisabler | None],
|
||||||
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
||||||
conversation_subentry_data: list[dict[str, Any]],
|
conversation_subentry_data: list[dict[str, Any]],
|
||||||
main_config_entry: int,
|
main_config_entry: int,
|
||||||
@@ -684,7 +694,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="Google",
|
manufacturer="Google",
|
||||||
model="Generative AI",
|
model="Generative AI",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
disabled_by=DeviceEntryDisabler.CONFIG_ENTRY,
|
disabled_by=device_disabled_by[0],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -693,7 +703,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry,
|
config_entry=mock_config_entry,
|
||||||
device_id=device_1.id,
|
device_id=device_1.id,
|
||||||
suggested_object_id="google_generative_ai_conversation",
|
suggested_object_id="google_generative_ai_conversation",
|
||||||
disabled_by=RegistryEntryDisabler.CONFIG_ENTRY,
|
disabled_by=entity_disabled_by[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
device_2 = device_registry.async_get_or_create(
|
device_2 = device_registry.async_get_or_create(
|
||||||
@@ -703,6 +713,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="Google",
|
manufacturer="Google",
|
||||||
model="Generative AI",
|
model="Generative AI",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
|
disabled_by=device_disabled_by[1],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -711,6 +722,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry_2,
|
config_entry=mock_config_entry_2,
|
||||||
device_id=device_2.id,
|
device_id=device_2.id,
|
||||||
suggested_object_id="google_generative_ai_conversation_2",
|
suggested_object_id="google_generative_ai_conversation_2",
|
||||||
|
disabled_by=entity_disabled_by[1],
|
||||||
)
|
)
|
||||||
|
|
||||||
devices = [device_1, device_2]
|
devices = [device_1, device_2]
|
||||||
|
@@ -372,6 +372,8 @@ async def test_migration_from_v1_with_same_urls(
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"config_entry_disabled_by",
|
"config_entry_disabled_by",
|
||||||
|
"device_disabled_by",
|
||||||
|
"entity_disabled_by",
|
||||||
"merged_config_entry_disabled_by",
|
"merged_config_entry_disabled_by",
|
||||||
"conversation_subentry_data",
|
"conversation_subentry_data",
|
||||||
"main_config_entry",
|
"main_config_entry",
|
||||||
@@ -379,6 +381,8 @@ async def test_migration_from_v1_with_same_urls(
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, None],
|
[ConfigEntryDisabler.USER, None],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, None],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, None],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -398,18 +402,20 @@ async def test_migration_from_v1_with_same_urls(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[None, ConfigEntryDisabler.USER],
|
[None, ConfigEntryDisabler.USER],
|
||||||
|
[None, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[None, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.ollama",
|
"conversation_entity_id": "conversation.ollama",
|
||||||
"device_disabled_by": DeviceEntryDisabler.USER,
|
"device_disabled_by": None,
|
||||||
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
"entity_disabled_by": None,
|
||||||
"device": 0,
|
"device": 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.ollama_2",
|
"conversation_entity_id": "conversation.ollama_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.USER,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -417,6 +423,8 @@ async def test_migration_from_v1_with_same_urls(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
ConfigEntryDisabler.USER,
|
ConfigEntryDisabler.USER,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -427,8 +435,8 @@ async def test_migration_from_v1_with_same_urls(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.ollama_2",
|
"conversation_entity_id": "conversation.ollama_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.CONFIG_ENTRY,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -441,6 +449,8 @@ async def test_migration_from_v1_disabled(
|
|||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
||||||
|
device_disabled_by: list[DeviceEntryDisabler | None],
|
||||||
|
entity_disabled_by: list[RegistryEntryDisabler | None],
|
||||||
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
||||||
conversation_subentry_data: list[dict[str, Any]],
|
conversation_subentry_data: list[dict[str, Any]],
|
||||||
main_config_entry: int,
|
main_config_entry: int,
|
||||||
@@ -474,7 +484,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="Ollama",
|
manufacturer="Ollama",
|
||||||
model="Ollama",
|
model="Ollama",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
disabled_by=DeviceEntryDisabler.CONFIG_ENTRY,
|
disabled_by=device_disabled_by[0],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -483,7 +493,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry,
|
config_entry=mock_config_entry,
|
||||||
device_id=device_1.id,
|
device_id=device_1.id,
|
||||||
suggested_object_id="ollama",
|
suggested_object_id="ollama",
|
||||||
disabled_by=RegistryEntryDisabler.CONFIG_ENTRY,
|
disabled_by=entity_disabled_by[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
device_2 = device_registry.async_get_or_create(
|
device_2 = device_registry.async_get_or_create(
|
||||||
@@ -493,6 +503,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="Ollama",
|
manufacturer="Ollama",
|
||||||
model="Ollama",
|
model="Ollama",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
|
disabled_by=device_disabled_by[1],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -501,6 +512,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry_2,
|
config_entry=mock_config_entry_2,
|
||||||
device_id=device_2.id,
|
device_id=device_2.id,
|
||||||
suggested_object_id="ollama_2",
|
suggested_object_id="ollama_2",
|
||||||
|
disabled_by=entity_disabled_by[1],
|
||||||
)
|
)
|
||||||
|
|
||||||
devices = [device_1, device_2]
|
devices = [device_1, device_2]
|
||||||
|
@@ -868,6 +868,8 @@ async def test_migration_from_v1_with_same_keys(
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"config_entry_disabled_by",
|
"config_entry_disabled_by",
|
||||||
|
"device_disabled_by",
|
||||||
|
"entity_disabled_by",
|
||||||
"merged_config_entry_disabled_by",
|
"merged_config_entry_disabled_by",
|
||||||
"conversation_subentry_data",
|
"conversation_subentry_data",
|
||||||
"main_config_entry",
|
"main_config_entry",
|
||||||
@@ -875,6 +877,8 @@ async def test_migration_from_v1_with_same_keys(
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, None],
|
[ConfigEntryDisabler.USER, None],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, None],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, None],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -894,18 +898,20 @@ async def test_migration_from_v1_with_same_keys(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[None, ConfigEntryDisabler.USER],
|
[None, ConfigEntryDisabler.USER],
|
||||||
|
[None, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[None, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
None,
|
None,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.chatgpt",
|
"conversation_entity_id": "conversation.chatgpt",
|
||||||
"device_disabled_by": DeviceEntryDisabler.USER,
|
"device_disabled_by": None,
|
||||||
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
"entity_disabled_by": None,
|
||||||
"device": 0,
|
"device": 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.chatgpt_2",
|
"conversation_entity_id": "conversation.chatgpt_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.USER,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.DEVICE,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -913,6 +919,8 @@ async def test_migration_from_v1_with_same_keys(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
[ConfigEntryDisabler.USER, ConfigEntryDisabler.USER],
|
||||||
|
[DeviceEntryDisabler.CONFIG_ENTRY, DeviceEntryDisabler.CONFIG_ENTRY],
|
||||||
|
[RegistryEntryDisabler.CONFIG_ENTRY, RegistryEntryDisabler.CONFIG_ENTRY],
|
||||||
ConfigEntryDisabler.USER,
|
ConfigEntryDisabler.USER,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -923,8 +931,8 @@ async def test_migration_from_v1_with_same_keys(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"conversation_entity_id": "conversation.chatgpt_2",
|
"conversation_entity_id": "conversation.chatgpt_2",
|
||||||
"device_disabled_by": None,
|
"device_disabled_by": DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
"entity_disabled_by": None,
|
"entity_disabled_by": RegistryEntryDisabler.CONFIG_ENTRY,
|
||||||
"device": 1,
|
"device": 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -937,6 +945,8 @@ async def test_migration_from_v1_disabled(
|
|||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
config_entry_disabled_by: list[ConfigEntryDisabler | None],
|
||||||
|
device_disabled_by: list[DeviceEntryDisabler | None],
|
||||||
|
entity_disabled_by: list[RegistryEntryDisabler | None],
|
||||||
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
merged_config_entry_disabled_by: ConfigEntryDisabler | None,
|
||||||
conversation_subentry_data: list[dict[str, Any]],
|
conversation_subentry_data: list[dict[str, Any]],
|
||||||
main_config_entry: int,
|
main_config_entry: int,
|
||||||
@@ -976,7 +986,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="OpenAI",
|
manufacturer="OpenAI",
|
||||||
model="ChatGPT",
|
model="ChatGPT",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
disabled_by=DeviceEntryDisabler.CONFIG_ENTRY,
|
disabled_by=device_disabled_by[0],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -985,7 +995,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry,
|
config_entry=mock_config_entry,
|
||||||
device_id=device_1.id,
|
device_id=device_1.id,
|
||||||
suggested_object_id="chatgpt",
|
suggested_object_id="chatgpt",
|
||||||
disabled_by=RegistryEntryDisabler.CONFIG_ENTRY,
|
disabled_by=entity_disabled_by[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
device_2 = device_registry.async_get_or_create(
|
device_2 = device_registry.async_get_or_create(
|
||||||
@@ -995,6 +1005,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
manufacturer="OpenAI",
|
manufacturer="OpenAI",
|
||||||
model="ChatGPT",
|
model="ChatGPT",
|
||||||
entry_type=dr.DeviceEntryType.SERVICE,
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
|
disabled_by=device_disabled_by[1],
|
||||||
)
|
)
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"conversation",
|
"conversation",
|
||||||
@@ -1003,6 +1014,7 @@ async def test_migration_from_v1_disabled(
|
|||||||
config_entry=mock_config_entry_2,
|
config_entry=mock_config_entry_2,
|
||||||
device_id=device_2.id,
|
device_id=device_2.id,
|
||||||
suggested_object_id="chatgpt_2",
|
suggested_object_id="chatgpt_2",
|
||||||
|
disabled_by=entity_disabled_by[1],
|
||||||
)
|
)
|
||||||
|
|
||||||
devices = [device_1, device_2]
|
devices = [device_1, device_2]
|
||||||
|
@@ -3279,6 +3279,266 @@ async def test_update_suggested_area(
|
|||||||
assert updated_entry.area_id == device_area_id
|
assert updated_entry.area_id == device_area_id
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
(
|
||||||
|
"new_config_entry_disabled_by",
|
||||||
|
"device_disabled_by_initial",
|
||||||
|
"device_disabled_by_updated",
|
||||||
|
"extra_changes",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
# Config entry not disabled, device was disabled by config entry.
|
||||||
|
# Device not disabled when updated.
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
None,
|
||||||
|
{"disabled_by": dr.DeviceEntryDisabler.CONFIG_ENTRY},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.usefixtures("freezer")
|
||||||
|
async def test_update_add_config_entry_disabled_by(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
new_config_entry_disabled_by: config_entries.ConfigEntryDisabler | None,
|
||||||
|
device_disabled_by_initial: dr.DeviceEntryDisabler | None,
|
||||||
|
device_disabled_by_updated: dr.DeviceEntryDisabler | None,
|
||||||
|
extra_changes: dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
"""Check how the disabled_by flag is treated when adding a config entry."""
|
||||||
|
config_entry_1 = MockConfigEntry(title=None)
|
||||||
|
config_entry_1.add_to_hass(hass)
|
||||||
|
config_entry_2 = MockConfigEntry(
|
||||||
|
title=None, disabled_by=new_config_entry_disabled_by
|
||||||
|
)
|
||||||
|
config_entry_2.add_to_hass(hass)
|
||||||
|
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
|
||||||
|
entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=config_entry_1.entry_id,
|
||||||
|
config_subentry_id=None,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||||
|
disabled_by=device_disabled_by_initial,
|
||||||
|
)
|
||||||
|
assert entry.disabled_by == device_disabled_by_initial
|
||||||
|
|
||||||
|
entry2 = device_registry.async_update_device(
|
||||||
|
entry.id, add_config_entry_id=config_entry_2.entry_id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert entry2 == dr.DeviceEntry(
|
||||||
|
config_entries={config_entry_1.entry_id, config_entry_2.entry_id},
|
||||||
|
config_entries_subentries={
|
||||||
|
config_entry_1.entry_id: {None},
|
||||||
|
config_entry_2.entry_id: {None},
|
||||||
|
},
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:ab:cd:ef")},
|
||||||
|
created_at=utcnow(),
|
||||||
|
disabled_by=device_disabled_by_updated,
|
||||||
|
id=entry.id,
|
||||||
|
modified_at=utcnow(),
|
||||||
|
primary_config_entry=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(update_events) == 2
|
||||||
|
assert update_events[0].data == {
|
||||||
|
"action": "create",
|
||||||
|
"device_id": entry.id,
|
||||||
|
}
|
||||||
|
assert update_events[1].data == {
|
||||||
|
"action": "update",
|
||||||
|
"device_id": entry.id,
|
||||||
|
"changes": {
|
||||||
|
"config_entries": {config_entry_1.entry_id},
|
||||||
|
"config_entries_subentries": {config_entry_1.entry_id: {None}},
|
||||||
|
}
|
||||||
|
| extra_changes,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
(
|
||||||
|
"removed_config_entry_disabled_by",
|
||||||
|
"device_disabled_by_initial",
|
||||||
|
"device_disabled_by_updated",
|
||||||
|
"extra_changes",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
# The non-disabled config entry is removed, device changed to
|
||||||
|
# disabled by config entry.
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
{"disabled_by": None},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
# In this test, the device is in an invalid state: config entry disabled,
|
||||||
|
# device not disabled. After removing the config entry, the device is disabled
|
||||||
|
# by checking the remaining config entry.
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
None,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
{"disabled_by": None},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
dr.DeviceEntryDisabler.INTEGRATION,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
config_entries.ConfigEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
dr.DeviceEntryDisabler.USER,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.usefixtures("freezer")
|
||||||
|
async def test_update_remove_config_entry_disabled_by(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
removed_config_entry_disabled_by: config_entries.ConfigEntryDisabler | None,
|
||||||
|
device_disabled_by_initial: dr.DeviceEntryDisabler | None,
|
||||||
|
device_disabled_by_updated: dr.DeviceEntryDisabler | None,
|
||||||
|
extra_changes: dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
"""Check how the disabled_by flag is treated when removing a config entry."""
|
||||||
|
config_entry_1 = MockConfigEntry(
|
||||||
|
title=None, disabled_by=removed_config_entry_disabled_by
|
||||||
|
)
|
||||||
|
config_entry_1.add_to_hass(hass)
|
||||||
|
config_entry_2 = MockConfigEntry(
|
||||||
|
title=None, disabled_by=config_entries.ConfigEntryDisabler.USER
|
||||||
|
)
|
||||||
|
config_entry_2.add_to_hass(hass)
|
||||||
|
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
|
||||||
|
entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=config_entry_1.entry_id,
|
||||||
|
config_subentry_id=None,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||||
|
disabled_by=device_disabled_by_initial,
|
||||||
|
)
|
||||||
|
assert entry.disabled_by == device_disabled_by_initial
|
||||||
|
|
||||||
|
entry2 = device_registry.async_update_device(
|
||||||
|
entry.id, add_config_entry_id=config_entry_2.entry_id
|
||||||
|
)
|
||||||
|
assert entry2.disabled_by == device_disabled_by_initial
|
||||||
|
|
||||||
|
entry3 = device_registry.async_update_device(
|
||||||
|
entry.id, remove_config_entry_id=config_entry_1.entry_id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert entry3 == dr.DeviceEntry(
|
||||||
|
config_entries={config_entry_2.entry_id},
|
||||||
|
config_entries_subentries={config_entry_2.entry_id: {None}},
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:ab:cd:ef")},
|
||||||
|
created_at=utcnow(),
|
||||||
|
disabled_by=device_disabled_by_updated,
|
||||||
|
id=entry.id,
|
||||||
|
modified_at=utcnow(),
|
||||||
|
primary_config_entry=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(update_events) == 3
|
||||||
|
assert update_events[0].data == {
|
||||||
|
"action": "create",
|
||||||
|
"device_id": entry.id,
|
||||||
|
}
|
||||||
|
assert update_events[1].data == {
|
||||||
|
"action": "update",
|
||||||
|
"device_id": entry.id,
|
||||||
|
"changes": {
|
||||||
|
"config_entries": {config_entry_1.entry_id},
|
||||||
|
"config_entries_subentries": {config_entry_1.entry_id: {None}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert update_events[2].data == {
|
||||||
|
"action": "update",
|
||||||
|
"device_id": entry.id,
|
||||||
|
"changes": {
|
||||||
|
"config_entries": {config_entry_1.entry_id, config_entry_2.entry_id},
|
||||||
|
"config_entries_subentries": {
|
||||||
|
config_entry_1.entry_id: {None},
|
||||||
|
config_entry_2.entry_id: {None},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
| extra_changes,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_cleanup_device_registry(
|
async def test_cleanup_device_registry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
|
Reference in New Issue
Block a user