Skip to content

Commit 465512b

Browse files
emontnemeryfrenck
authored andcommitted
Improve migration to device registry version 1.10 (home-assistant#151571)
1 parent 75d6c0b commit 465512b

File tree

2 files changed

+309
-12
lines changed

2 files changed

+309
-12
lines changed

homeassistant/helpers/device_registry.py

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ class DeletedDeviceEntry:
465465
validator=_normalize_connections_validator
466466
)
467467
created_at: datetime = attr.ib()
468-
disabled_by: DeviceEntryDisabler | None = attr.ib()
468+
disabled_by: DeviceEntryDisabler | UndefinedType | None = attr.ib()
469469
id: str = attr.ib()
470470
identifiers: set[tuple[str, str]] = attr.ib()
471471
labels: set[str] = attr.ib()
@@ -480,15 +480,19 @@ def to_device_entry(
480480
config_subentry_id: str | None,
481481
connections: set[tuple[str, str]],
482482
identifiers: set[tuple[str, str]],
483+
disabled_by: DeviceEntryDisabler | UndefinedType | None,
483484
) -> DeviceEntry:
484485
"""Create DeviceEntry from DeletedDeviceEntry."""
485486
# Adjust disabled_by based on config entry state
486-
disabled_by = self.disabled_by
487-
if config_entry.disabled_by:
488-
if disabled_by is None:
489-
disabled_by = DeviceEntryDisabler.CONFIG_ENTRY
490-
elif disabled_by == DeviceEntryDisabler.CONFIG_ENTRY:
491-
disabled_by = None
487+
if self.disabled_by is not UNDEFINED:
488+
disabled_by = self.disabled_by
489+
if config_entry.disabled_by:
490+
if disabled_by is None:
491+
disabled_by = DeviceEntryDisabler.CONFIG_ENTRY
492+
elif disabled_by == DeviceEntryDisabler.CONFIG_ENTRY:
493+
disabled_by = None
494+
else:
495+
disabled_by = disabled_by if disabled_by is not UNDEFINED else None
492496
return DeviceEntry(
493497
area_id=self.area_id,
494498
# type ignores: likely https://github.com/python/mypy/issues/8625
@@ -520,7 +524,10 @@ def as_storage_fragment(self) -> json_fragment:
520524
},
521525
"connections": list(self.connections),
522526
"created_at": self.created_at,
523-
"disabled_by": self.disabled_by,
527+
"disabled_by": self.disabled_by
528+
if self.disabled_by is not UNDEFINED
529+
else None,
530+
"disabled_by_undefined": self.disabled_by is UNDEFINED,
524531
"identifiers": list(self.identifiers),
525532
"id": self.id,
526533
"labels": list(self.labels),
@@ -621,6 +628,11 @@ async def _async_migrate_func( # noqa: C901
621628
device["connections"] = _normalize_connections(
622629
device["connections"]
623630
)
631+
if old_minor_version < 12:
632+
# Version 1.12 adds undefined flags to deleted devices, this is a bugfix
633+
# of version 1.10
634+
for device in old_data["deleted_devices"]:
635+
device["disabled_by_undefined"] = old_minor_version < 10
624636

625637
if old_major_version > 2:
626638
raise NotImplementedError
@@ -934,6 +946,7 @@ def async_get_or_create(
934946
config_subentry_id if config_subentry_id is not UNDEFINED else None,
935947
connections,
936948
identifiers,
949+
disabled_by,
937950
)
938951
disabled_by = UNDEFINED
939952

@@ -1444,7 +1457,21 @@ async def async_load(self) -> None:
14441457
sw_version=device["sw_version"],
14451458
via_device_id=device["via_device_id"],
14461459
)
1460+
14471461
# Introduced in 0.111
1462+
def get_optional_enum[_EnumT: StrEnum](
1463+
cls: type[_EnumT], value: str | None, undefined: bool
1464+
) -> _EnumT | UndefinedType | None:
1465+
"""Convert string to the passed enum, UNDEFINED or None."""
1466+
if undefined:
1467+
return UNDEFINED
1468+
if value is None:
1469+
return None
1470+
try:
1471+
return cls(value)
1472+
except ValueError:
1473+
return None
1474+
14481475
for device in data["deleted_devices"]:
14491476
deleted_devices[device["id"]] = DeletedDeviceEntry(
14501477
area_id=device["area_id"],
@@ -1457,10 +1484,10 @@ async def async_load(self) -> None:
14571484
},
14581485
connections={tuple(conn) for conn in device["connections"]},
14591486
created_at=datetime.fromisoformat(device["created_at"]),
1460-
disabled_by=(
1461-
DeviceEntryDisabler(device["disabled_by"])
1462-
if device["disabled_by"]
1463-
else None
1487+
disabled_by=get_optional_enum(
1488+
DeviceEntryDisabler,
1489+
device["disabled_by"],
1490+
device["disabled_by_undefined"],
14641491
),
14651492
identifiers={tuple(iden) for iden in device["identifiers"]},
14661493
id=device["id"],

0 commit comments

Comments
 (0)