mirror of
https://github.com/home-assistant/core.git
synced 2025-08-31 18:31:35 +02:00
Revert "Fix entities/devices stuck in disabled state after config entry re-add" (#151158)
This commit is contained in:
@@ -1460,18 +1460,12 @@ class DeviceRegistry(BaseRegistry[dict[str, list[dict[str, Any]]]]):
|
||||
if config_entry_id not in config_entries:
|
||||
continue
|
||||
if config_entries == {config_entry_id}:
|
||||
# Clear disabled_by if it was disabled by the config entry
|
||||
if deleted_device.disabled_by is DeviceEntryDisabler.CONFIG_ENTRY:
|
||||
disabled_by = None
|
||||
else:
|
||||
disabled_by = deleted_device.disabled_by
|
||||
# Add a time stamp when the deleted device became orphaned
|
||||
self.deleted_devices[deleted_device.id] = attr.evolve(
|
||||
deleted_device,
|
||||
orphaned_timestamp=now_time,
|
||||
config_entries=set(),
|
||||
config_entries_subentries={},
|
||||
disabled_by=disabled_by,
|
||||
)
|
||||
else:
|
||||
config_entries = config_entries - {config_entry_id}
|
||||
|
@@ -1622,17 +1622,9 @@ class EntityRegistry(BaseRegistry):
|
||||
for key, deleted_entity in list(self.deleted_entities.items()):
|
||||
if config_entry_id != deleted_entity.config_entry_id:
|
||||
continue
|
||||
# Clear disabled_by if it was disabled by the config entry
|
||||
if deleted_entity.disabled_by is RegistryEntryDisabler.CONFIG_ENTRY:
|
||||
disabled_by = None
|
||||
else:
|
||||
disabled_by = deleted_entity.disabled_by
|
||||
# Add a time stamp when the deleted entity became orphaned
|
||||
self.deleted_entities[key] = attr.evolve(
|
||||
deleted_entity,
|
||||
orphaned_timestamp=now_time,
|
||||
config_entry_id=None,
|
||||
disabled_by=disabled_by,
|
||||
deleted_entity, orphaned_timestamp=now_time, config_entry_id=None
|
||||
)
|
||||
self.async_schedule_save()
|
||||
|
||||
|
@@ -3368,98 +3368,6 @@ async def test_cleanup_startup(hass: HomeAssistant) -> None:
|
||||
assert len(mock_call.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_deleted_device_clears_disabled_by_on_config_entry_removal(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test that disabled_by is cleared when config entry is removed."""
|
||||
config_entry = MockConfigEntry(domain="test", entry_id="mock-id-1")
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
# Create a device disabled by the config entry
|
||||
device = device_registry.async_get_or_create(
|
||||
config_entry_id="mock-id-1",
|
||||
identifiers={("test", "device_1")},
|
||||
name="Test Device",
|
||||
disabled_by=dr.DeviceEntryDisabler.CONFIG_ENTRY,
|
||||
)
|
||||
assert device.config_entries == {"mock-id-1"}
|
||||
assert device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
||||
|
||||
# Remove the device (it moves to deleted_devices)
|
||||
device_registry.async_remove_device(device.id)
|
||||
|
||||
assert len(device_registry.devices) == 0
|
||||
assert len(device_registry.deleted_devices) == 1
|
||||
deleted_device = device_registry.deleted_devices[device.id]
|
||||
assert deleted_device.config_entries == {"mock-id-1"}
|
||||
assert deleted_device.disabled_by is dr.DeviceEntryDisabler.CONFIG_ENTRY
|
||||
assert deleted_device.orphaned_timestamp is None
|
||||
|
||||
# Clear the config entry
|
||||
device_registry.async_clear_config_entry("mock-id-1")
|
||||
|
||||
# Verify disabled_by is cleared
|
||||
deleted_device = device_registry.deleted_devices[device.id]
|
||||
assert deleted_device.config_entries == set()
|
||||
assert deleted_device.disabled_by is None # Should be cleared
|
||||
assert deleted_device.orphaned_timestamp is not None
|
||||
|
||||
# Now re-add the config entry and device to verify it can be enabled
|
||||
config_entry2 = MockConfigEntry(domain="test", entry_id="mock-id-2")
|
||||
config_entry2.add_to_hass(hass)
|
||||
|
||||
# Re-create the device with same identifiers
|
||||
device2 = device_registry.async_get_or_create(
|
||||
config_entry_id="mock-id-2",
|
||||
identifiers={("test", "device_1")},
|
||||
name="Test Device",
|
||||
)
|
||||
assert device2.config_entries == {"mock-id-2"}
|
||||
assert device2.disabled_by is None # Should not be disabled anymore
|
||||
assert device2.id == device.id # Should keep the same device id
|
||||
|
||||
|
||||
async def test_deleted_device_disabled_by_user_not_cleared(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test that disabled_by=USER is not cleared when config entry is removed."""
|
||||
config_entry = MockConfigEntry(domain="test", entry_id="mock-id-1")
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
# Create a device disabled by the user
|
||||
device = device_registry.async_get_or_create(
|
||||
config_entry_id="mock-id-1",
|
||||
identifiers={("test", "device_1")},
|
||||
name="Test Device",
|
||||
disabled_by=dr.DeviceEntryDisabler.USER,
|
||||
)
|
||||
assert device.config_entries == {"mock-id-1"}
|
||||
assert device.disabled_by is dr.DeviceEntryDisabler.USER
|
||||
|
||||
# Remove the device (it moves to deleted_devices)
|
||||
device_registry.async_remove_device(device.id)
|
||||
|
||||
assert len(device_registry.devices) == 0
|
||||
assert len(device_registry.deleted_devices) == 1
|
||||
deleted_device = device_registry.deleted_devices[device.id]
|
||||
assert deleted_device.config_entries == {"mock-id-1"}
|
||||
assert deleted_device.disabled_by is dr.DeviceEntryDisabler.USER
|
||||
assert deleted_device.orphaned_timestamp is None
|
||||
|
||||
# Clear the config entry
|
||||
device_registry.async_clear_config_entry("mock-id-1")
|
||||
|
||||
# Verify disabled_by is NOT cleared for USER disabled devices
|
||||
deleted_device = device_registry.deleted_devices[device.id]
|
||||
assert deleted_device.config_entries == set()
|
||||
assert (
|
||||
deleted_device.disabled_by is dr.DeviceEntryDisabler.USER
|
||||
) # Should remain USER
|
||||
assert deleted_device.orphaned_timestamp is not None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("load_registries", [False])
|
||||
async def test_cleanup_entity_registry_change(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
|
@@ -782,97 +782,6 @@ async def test_deleted_entity_removing_config_entry_id(
|
||||
assert entity_registry.deleted_entities[("light", "hue", "1234")] == deleted_entry2
|
||||
|
||||
|
||||
async def test_deleted_entity_clears_disabled_by_on_config_entry_removal(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test that disabled_by is cleared when config entry is removed."""
|
||||
mock_config = MockConfigEntry(domain="light", entry_id="mock-id-1")
|
||||
mock_config.add_to_hass(hass)
|
||||
|
||||
# Create an entity disabled by the config entry
|
||||
entry = entity_registry.async_get_or_create(
|
||||
"light",
|
||||
"hue",
|
||||
"5678",
|
||||
config_entry=mock_config,
|
||||
disabled_by=er.RegistryEntryDisabler.CONFIG_ENTRY,
|
||||
)
|
||||
assert entry.config_entry_id == "mock-id-1"
|
||||
assert entry.disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
||||
|
||||
# Remove the entity (it moves to deleted_entities)
|
||||
entity_registry.async_remove(entry.entity_id)
|
||||
|
||||
assert len(entity_registry.entities) == 0
|
||||
assert len(entity_registry.deleted_entities) == 1
|
||||
deleted_entry = entity_registry.deleted_entities[("light", "hue", "5678")]
|
||||
assert deleted_entry.config_entry_id == "mock-id-1"
|
||||
assert deleted_entry.disabled_by is er.RegistryEntryDisabler.CONFIG_ENTRY
|
||||
assert deleted_entry.orphaned_timestamp is None
|
||||
|
||||
# Clear the config entry
|
||||
entity_registry.async_clear_config_entry("mock-id-1")
|
||||
|
||||
# Verify disabled_by is cleared
|
||||
deleted_entry = entity_registry.deleted_entities[("light", "hue", "5678")]
|
||||
assert deleted_entry.config_entry_id is None
|
||||
assert deleted_entry.disabled_by is None # Should be cleared
|
||||
assert deleted_entry.orphaned_timestamp is not None
|
||||
|
||||
# Now re-add the config entry and entity to verify it can be enabled
|
||||
mock_config2 = MockConfigEntry(domain="light", entry_id="mock-id-2")
|
||||
mock_config2.add_to_hass(hass)
|
||||
|
||||
# Re-create the entity with same unique ID
|
||||
entry2 = entity_registry.async_get_or_create(
|
||||
"light", "hue", "5678", config_entry=mock_config2
|
||||
)
|
||||
assert entry2.config_entry_id == "mock-id-2"
|
||||
assert entry2.disabled_by is None # Should not be disabled anymore
|
||||
|
||||
|
||||
async def test_deleted_entity_disabled_by_user_not_cleared(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test that disabled_by=USER is not cleared when config entry is removed."""
|
||||
mock_config = MockConfigEntry(domain="light", entry_id="mock-id-1")
|
||||
mock_config.add_to_hass(hass)
|
||||
|
||||
# Create an entity disabled by the user
|
||||
entry = entity_registry.async_get_or_create(
|
||||
"light",
|
||||
"hue",
|
||||
"5678",
|
||||
config_entry=mock_config,
|
||||
disabled_by=er.RegistryEntryDisabler.USER,
|
||||
)
|
||||
assert entry.config_entry_id == "mock-id-1"
|
||||
assert entry.disabled_by is er.RegistryEntryDisabler.USER
|
||||
|
||||
# Remove the entity (it moves to deleted_entities)
|
||||
entity_registry.async_remove(entry.entity_id)
|
||||
|
||||
assert len(entity_registry.entities) == 0
|
||||
assert len(entity_registry.deleted_entities) == 1
|
||||
deleted_entry = entity_registry.deleted_entities[("light", "hue", "5678")]
|
||||
assert deleted_entry.config_entry_id == "mock-id-1"
|
||||
assert deleted_entry.disabled_by is er.RegistryEntryDisabler.USER
|
||||
assert deleted_entry.orphaned_timestamp is None
|
||||
|
||||
# Clear the config entry
|
||||
entity_registry.async_clear_config_entry("mock-id-1")
|
||||
|
||||
# Verify disabled_by is NOT cleared for USER disabled entities
|
||||
deleted_entry = entity_registry.deleted_entities[("light", "hue", "5678")]
|
||||
assert deleted_entry.config_entry_id is None
|
||||
assert (
|
||||
deleted_entry.disabled_by is er.RegistryEntryDisabler.USER
|
||||
) # Should remain USER
|
||||
assert deleted_entry.orphaned_timestamp is not None
|
||||
|
||||
|
||||
async def test_removing_config_subentry_id(
|
||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
|
Reference in New Issue
Block a user