mirror of
https://github.com/home-assistant/core.git
synced 2026-04-02 00:20:30 +01:00
Use legacy naming for entities (#166696)
This commit is contained in:
@@ -51,7 +51,6 @@ def _entity_entry_filter(a: attr.Attribute, _: Any) -> bool:
|
||||
return a.name not in (
|
||||
"_cache",
|
||||
"compat_aliases",
|
||||
"compat_name",
|
||||
"original_name_unprefixed",
|
||||
)
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ EVENT_ENTITY_REGISTRY_UPDATED: EventType[EventEntityRegistryUpdatedData] = Event
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
STORAGE_VERSION_MAJOR = 1
|
||||
STORAGE_VERSION_MINOR = 21
|
||||
STORAGE_VERSION_MINOR = 22
|
||||
STORAGE_KEY = "core.entity_registry"
|
||||
|
||||
CLEANUP_INTERVAL = 3600 * 24
|
||||
@@ -240,7 +240,6 @@ class RegistryEntry:
|
||||
|
||||
# For backwards compatibility, should be removed in the future
|
||||
compat_aliases: list[str] = attr.ib(factory=list, eq=False)
|
||||
compat_name: str | None = attr.ib(default=None, eq=False)
|
||||
|
||||
# original_name_unprefixed is used to store the result of stripping
|
||||
# the device name prefix from the original_name, if possible.
|
||||
@@ -413,8 +412,7 @@ class RegistryEntry:
|
||||
"has_entity_name": self.has_entity_name,
|
||||
"labels": list(self.labels),
|
||||
"modified_at": self.modified_at,
|
||||
"name": self.compat_name,
|
||||
"name_v2": self.name,
|
||||
"name": self.name,
|
||||
"object_id_base": self.object_id_base,
|
||||
"options": self.options,
|
||||
"original_device_class": self.original_device_class,
|
||||
@@ -471,6 +469,7 @@ def _async_get_full_entity_name(
|
||||
original_name: str | None,
|
||||
original_name_unprefixed: str | None | UndefinedType = UNDEFINED,
|
||||
overridden_name: str | None = None,
|
||||
use_legacy_naming: bool = False,
|
||||
) -> str:
|
||||
"""Get full name for an entity.
|
||||
|
||||
@@ -480,7 +479,7 @@ def _async_get_full_entity_name(
|
||||
if name is None and overridden_name is not None:
|
||||
name = overridden_name
|
||||
|
||||
else:
|
||||
elif not use_legacy_naming or name is None:
|
||||
device_name: str | None = None
|
||||
if (
|
||||
device_id is not None
|
||||
@@ -533,6 +532,7 @@ def async_get_full_entity_name(
|
||||
name=entry.name,
|
||||
original_name=original_name,
|
||||
original_name_unprefixed=original_name_unprefixed,
|
||||
use_legacy_naming=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -660,7 +660,6 @@ class DeletedRegistryEntry:
|
||||
|
||||
# For backwards compatibility, should be removed in the future
|
||||
compat_aliases: list[str] = attr.ib(factory=list, eq=False)
|
||||
compat_name: str | None = attr.ib(default=None, eq=False)
|
||||
|
||||
_cache: dict[str, Any] = attr.ib(factory=dict, eq=False, init=False)
|
||||
|
||||
@@ -696,8 +695,7 @@ class DeletedRegistryEntry:
|
||||
"id": self.id,
|
||||
"labels": list(self.labels),
|
||||
"modified_at": self.modified_at,
|
||||
"name": self.compat_name,
|
||||
"name_v2": self.name,
|
||||
"name": self.name,
|
||||
"options": self.options if self.options is not UNDEFINED else {},
|
||||
"options_undefined": self.options is UNDEFINED,
|
||||
"orphaned_timestamp": self.orphaned_timestamp,
|
||||
@@ -850,46 +848,37 @@ class EntityRegistryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
|
||||
for entity in data["entities"]:
|
||||
entity["object_id_base"] = entity["original_name"]
|
||||
|
||||
if old_minor_version < 21:
|
||||
# Version 1.21 migrates the full name to include device name,
|
||||
# even if entity name is overwritten by user.
|
||||
# It also adds support for COMPUTED_NAME in aliases and starts preserving their order.
|
||||
# To avoid a major version bump, we keep the old name and aliases as-is
|
||||
# and use new name_v2 and aliases_v2 fields instead.
|
||||
if old_minor_version == 21:
|
||||
# Version 1.21 has been reverted.
|
||||
# It migrated entity names to the new format stored in `name_v2`
|
||||
# field, automatically stripping any device name prefix present.
|
||||
# The old name was stored in `name` field for backwards compatibility.
|
||||
# For users who already migrated to v1.21, we restore old names
|
||||
# but try to preserve any user renames made since that migration.
|
||||
device_registry = dr.async_get(self.hass)
|
||||
|
||||
for entity in data["entities"]:
|
||||
alias_to_add: str | None = None
|
||||
old_name = entity["name"]
|
||||
name = entity.pop("name_v2")
|
||||
if (
|
||||
(name := entity["name"])
|
||||
(name != old_name)
|
||||
and (device_id := entity["device_id"]) is not None
|
||||
and (device := device_registry.async_get(device_id)) is not None
|
||||
and (device_name := device.name_by_user or device.name)
|
||||
):
|
||||
# Strip the device name prefix from the entity name if present,
|
||||
# and add the full generated name as an alias.
|
||||
# If the name doesn't have the device name prefix and the
|
||||
# entity is exposed to a voice assistant, add the previous
|
||||
# name as an alias instead to preserve backwards compatibility.
|
||||
if (
|
||||
new_name := _async_strip_prefix_from_entity_name(
|
||||
name, device_name
|
||||
)
|
||||
) is not None:
|
||||
name = new_name
|
||||
elif any(
|
||||
entity.get("options", {}).get(key, {}).get("should_expose")
|
||||
for key in ("conversation", "cloud.google_assistant")
|
||||
):
|
||||
alias_to_add = name
|
||||
name = f"{device_name} {name}"
|
||||
|
||||
entity["name_v2"] = name
|
||||
entity["aliases_v2"] = [alias_to_add, *entity["aliases"]]
|
||||
entity["name"] = name
|
||||
|
||||
if old_minor_version < 22:
|
||||
# Version 1.22 adds support for COMPUTED_NAME in aliases and starts preserving
|
||||
# their order.
|
||||
# To avoid a major version bump, we keep the old aliases as-is and use aliases_v2
|
||||
# field instead.
|
||||
for entity in data["entities"]:
|
||||
entity["aliases_v2"] = [None, *entity["aliases"]]
|
||||
|
||||
for entity in data["deleted_entities"]:
|
||||
# We don't know what the device name was, so the only thing we can do
|
||||
# is to clear the overwritten name to not mislead users.
|
||||
entity["name_v2"] = None
|
||||
entity["aliases_v2"] = [None, *entity["aliases"]]
|
||||
|
||||
if old_major_version > 1:
|
||||
@@ -1363,7 +1352,6 @@ class EntityRegistry(BaseRegistry):
|
||||
area_id = deleted_entity.area_id
|
||||
categories = deleted_entity.categories
|
||||
compat_aliases = deleted_entity.compat_aliases
|
||||
compat_name = deleted_entity.compat_name
|
||||
created_at = deleted_entity.created_at
|
||||
device_class = deleted_entity.device_class
|
||||
if deleted_entity.disabled_by is not UNDEFINED:
|
||||
@@ -1395,7 +1383,6 @@ class EntityRegistry(BaseRegistry):
|
||||
area_id = None
|
||||
categories = {}
|
||||
compat_aliases = []
|
||||
compat_name = None
|
||||
device_class = None
|
||||
icon = None
|
||||
labels = set()
|
||||
@@ -1443,7 +1430,6 @@ class EntityRegistry(BaseRegistry):
|
||||
categories=categories,
|
||||
capabilities=none_if_undefined(capabilities),
|
||||
compat_aliases=compat_aliases,
|
||||
compat_name=compat_name,
|
||||
config_entry_id=none_if_undefined(config_entry_id),
|
||||
config_subentry_id=none_if_undefined(config_subentry_id),
|
||||
created_at=created_at,
|
||||
@@ -1506,7 +1492,6 @@ class EntityRegistry(BaseRegistry):
|
||||
area_id=entity.area_id,
|
||||
categories=entity.categories,
|
||||
compat_aliases=entity.compat_aliases,
|
||||
compat_name=entity.compat_name,
|
||||
config_entry_id=config_entry_id,
|
||||
config_subentry_id=entity.config_subentry_id,
|
||||
created_at=entity.created_at,
|
||||
@@ -1620,14 +1605,27 @@ class EntityRegistry(BaseRegistry):
|
||||
for entity in entities:
|
||||
if entity.has_entity_name:
|
||||
continue
|
||||
name = (
|
||||
entity.original_name_unprefixed
|
||||
if by_user and entity.name is None
|
||||
else UNDEFINED
|
||||
)
|
||||
|
||||
# When a user renames a device, update entity names to reflect
|
||||
# the new device name.
|
||||
# An empty name_unprefixed means the entity name equals
|
||||
# the device name (e.g. a main sensor); a non-empty one
|
||||
# is appended as a suffix.
|
||||
name: str | None | UndefinedType = UNDEFINED
|
||||
if (
|
||||
by_user
|
||||
and entity.name is None
|
||||
and (name_unprefixed := entity.original_name_unprefixed) is not None
|
||||
):
|
||||
if not name_unprefixed:
|
||||
name = device_name
|
||||
elif device_name:
|
||||
name = f"{device_name} {name_unprefixed}"
|
||||
|
||||
original_name_unprefixed = _async_strip_prefix_from_entity_name(
|
||||
entity.original_name, device_name
|
||||
)
|
||||
|
||||
self._async_update_entity(
|
||||
entity.entity_id,
|
||||
name=name,
|
||||
@@ -1995,7 +1993,6 @@ class EntityRegistry(BaseRegistry):
|
||||
categories=entity["categories"],
|
||||
capabilities=entity["capabilities"],
|
||||
compat_aliases=entity["aliases"],
|
||||
compat_name=entity["name"],
|
||||
config_entry_id=entity["config_entry_id"],
|
||||
config_subentry_id=entity["config_subentry_id"],
|
||||
created_at=datetime.fromisoformat(entity["created_at"]),
|
||||
@@ -2016,7 +2013,7 @@ class EntityRegistry(BaseRegistry):
|
||||
has_entity_name=entity["has_entity_name"],
|
||||
labels=set(entity["labels"]),
|
||||
modified_at=datetime.fromisoformat(entity["modified_at"]),
|
||||
name=entity["name_v2"],
|
||||
name=entity["name"],
|
||||
object_id_base=entity.get("object_id_base"),
|
||||
options=entity["options"],
|
||||
original_device_class=entity["original_device_class"],
|
||||
@@ -2067,7 +2064,6 @@ class EntityRegistry(BaseRegistry):
|
||||
area_id=entity["area_id"],
|
||||
categories=entity["categories"],
|
||||
compat_aliases=entity["aliases"],
|
||||
compat_name=entity["name"],
|
||||
config_entry_id=entity["config_entry_id"],
|
||||
config_subentry_id=entity["config_subentry_id"],
|
||||
created_at=datetime.fromisoformat(entity["created_at"]),
|
||||
@@ -2087,7 +2083,7 @@ class EntityRegistry(BaseRegistry):
|
||||
id=entity["id"],
|
||||
labels=set(entity["labels"]),
|
||||
modified_at=datetime.fromisoformat(entity["modified_at"]),
|
||||
name=entity["name_v2"],
|
||||
name=entity["name"],
|
||||
options=entity["options"]
|
||||
if not entity["options_undefined"]
|
||||
else UNDEFINED,
|
||||
|
||||
@@ -801,7 +801,7 @@ async def test_existing_node_not_replaced_when_not_ready(
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(custom_entity)
|
||||
assert state
|
||||
assert state.name == "Custom Device Name Custom Entity Name"
|
||||
assert state.name == "Custom Entity Name"
|
||||
assert not hass.states.get(motion_entity)
|
||||
|
||||
node_state = deepcopy(zp3111_not_ready_state)
|
||||
@@ -835,7 +835,7 @@ async def test_existing_node_not_replaced_when_not_ready(
|
||||
|
||||
state = hass.states.get(custom_entity)
|
||||
assert state
|
||||
assert state.name == "Custom Device Name Custom Entity Name"
|
||||
assert state.name == "Custom Entity Name"
|
||||
|
||||
event = Event(
|
||||
type="ready",
|
||||
@@ -866,7 +866,7 @@ async def test_existing_node_not_replaced_when_not_ready(
|
||||
state = hass.states.get(custom_entity)
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert state.name == "Custom Device Name Custom Entity Name"
|
||||
assert state.name == "Custom Entity Name"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("client")
|
||||
@@ -1857,7 +1857,7 @@ async def test_node_model_change(
|
||||
assert not hass.states.get(motion_entity)
|
||||
state = hass.states.get(custom_entity)
|
||||
assert state
|
||||
assert state.name == "Custom Device Name Custom Entity Name"
|
||||
assert state.name == "Custom Entity Name"
|
||||
|
||||
# Unload the integration
|
||||
assert await hass.config_entries.async_unload(integration.entry_id)
|
||||
@@ -1887,7 +1887,7 @@ async def test_node_model_change(
|
||||
assert not hass.states.get(motion_entity)
|
||||
state = hass.states.get(custom_entity)
|
||||
assert state
|
||||
assert state.name == "Custom Device Name Custom Entity Name"
|
||||
assert state.name == "Custom Entity Name"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("zp3111", "integration")
|
||||
|
||||
@@ -684,7 +684,6 @@ async def test_load_bad_data(
|
||||
"labels": [],
|
||||
"modified_at": "2024-02-14T12:00:00.900075+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"object_id_base": None,
|
||||
"options": None,
|
||||
"original_device_class": None,
|
||||
@@ -719,7 +718,6 @@ async def test_load_bad_data(
|
||||
"labels": [],
|
||||
"modified_at": "2024-02-14T12:00:00.900075+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"object_id_base": None,
|
||||
"options": None,
|
||||
"original_device_class": None,
|
||||
@@ -754,7 +752,6 @@ async def test_load_bad_data(
|
||||
"labels": [],
|
||||
"modified_at": "2024-02-14T12:00:00.900075+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"options": None,
|
||||
"options_undefined": False,
|
||||
"orphaned_timestamp": None,
|
||||
@@ -780,7 +777,6 @@ async def test_load_bad_data(
|
||||
"labels": [],
|
||||
"modified_at": "2024-02-14T12:00:00.900075+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"options": None,
|
||||
"options_undefined": False,
|
||||
"orphaned_timestamp": None,
|
||||
@@ -1135,7 +1131,6 @@ async def test_migration_1_1(hass: HomeAssistant, hass_storage: dict[str, Any])
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"object_id_base": None,
|
||||
"options": {},
|
||||
"original_device_class": "best_class",
|
||||
@@ -1331,7 +1326,6 @@ async def test_migration_1_11(
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"object_id_base": None,
|
||||
"options": {},
|
||||
"original_device_class": "best_class",
|
||||
@@ -1367,7 +1361,6 @@ async def test_migration_1_11(
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"options": {},
|
||||
"options_undefined": True,
|
||||
"orphaned_timestamp": None,
|
||||
@@ -1500,7 +1493,6 @@ async def test_migration_1_18(
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"object_id_base": "Test Entity",
|
||||
"options": {},
|
||||
"original_device_class": "best_class",
|
||||
@@ -1536,7 +1528,6 @@ async def test_migration_1_18(
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"options": {},
|
||||
"options_undefined": False,
|
||||
"orphaned_timestamp": None,
|
||||
@@ -1554,10 +1545,14 @@ async def test_migration_1_18(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("load_registries", [False])
|
||||
async def test_migration_1_20(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
async def test_migration_1_21(
|
||||
hass: HomeAssistant,
|
||||
hass_storage: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test migration from version 1.20."""
|
||||
"""Test migration from version 1.21.
|
||||
|
||||
Version 1.21 stored entity names in a new format, but was reverted.
|
||||
"""
|
||||
hass_storage[dr.STORAGE_KEY] = {
|
||||
"version": dr.STORAGE_VERSION_MAJOR,
|
||||
"minor_version": dr.STORAGE_VERSION_MINOR,
|
||||
@@ -1565,24 +1560,25 @@ async def test_migration_1_20(
|
||||
"devices": [
|
||||
{
|
||||
"area_id": None,
|
||||
"config_entries": ["mock-config-entry"],
|
||||
"config_entries_subentries": {"mock-config-entry": [None]},
|
||||
"config_entries": ["mock_entry"],
|
||||
"config_entries_subentries": {"mock_entry": [None]},
|
||||
"configuration_url": None,
|
||||
"connections": [],
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"disabled_by": None,
|
||||
"disabled_by_undefined": False,
|
||||
"entry_type": None,
|
||||
"hw_version": None,
|
||||
"id": "device-1",
|
||||
"identifiers": [["test", "device-1"]],
|
||||
"id": "device_1234",
|
||||
"identifiers": [["test", "device_1"]],
|
||||
"labels": [],
|
||||
"manufacturer": None,
|
||||
"model": None,
|
||||
"model_id": None,
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "My Device",
|
||||
"name_by_user": None,
|
||||
"primary_config_entry": "mock-config-entry",
|
||||
"name": "My Device",
|
||||
"primary_config_entry": "mock_entry",
|
||||
"serial_number": None,
|
||||
"sw_version": None,
|
||||
"via_device_id": None,
|
||||
@@ -1591,238 +1587,121 @@ async def test_migration_1_20(
|
||||
"deleted_devices": [],
|
||||
},
|
||||
}
|
||||
|
||||
dr.async_setup(hass)
|
||||
await dr.async_load(hass)
|
||||
|
||||
# Entity registry data at version 1.20
|
||||
entity_base = {
|
||||
"aliases": [],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device_1234",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"has_entity_name": False,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"object_id_base": "Temperature",
|
||||
"options": {},
|
||||
"original_device_class": "temperature",
|
||||
"original_icon": None,
|
||||
"original_name": "Temperature",
|
||||
"platform": "super_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
}
|
||||
hass_storage[er.STORAGE_KEY] = {
|
||||
"version": 1,
|
||||
"minor_version": 20,
|
||||
"minor_version": 21,
|
||||
"data": {
|
||||
"entities": [
|
||||
{
|
||||
# Entity with name=None
|
||||
# name should be preserved
|
||||
# should add None to aliases
|
||||
"aliases": [],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.entity_name_no_custom",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-1",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-1",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
},
|
||||
{
|
||||
# Entity with no device_id
|
||||
# name should be preserved
|
||||
# should add None to aliases
|
||||
"aliases": [],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": None,
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.no_device",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-2",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Standalone Sensor",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-2",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
},
|
||||
{
|
||||
# Entity with name starting with device name
|
||||
# name should be stripped to remove device name prefix
|
||||
# should add None to aliases
|
||||
"aliases": [],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.name_with_device_prefix",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-3",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "My device temperature",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-3",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
},
|
||||
{
|
||||
# Entity with custom name not starting with device name
|
||||
# not exposed to any voice assistant
|
||||
# name should be preserved
|
||||
# should add None to aliases
|
||||
"aliases": [],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
**entity_base,
|
||||
"entity_id": "test.custom_name",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-4",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Living Room Light",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-4",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
"id": "entity_custom_name",
|
||||
"unique_id": "custom_name",
|
||||
"name": "My Custom Name",
|
||||
"name_v2": "My Custom Name",
|
||||
},
|
||||
{
|
||||
# Entity with custom name not starting with device name
|
||||
# exposed to conversation assistant
|
||||
# name should be preserved
|
||||
# should add name to aliases
|
||||
"aliases": [],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.custom_name_exposed",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-5",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Living Room Light",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {
|
||||
"conversation": {"should_expose": True},
|
||||
},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-5",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
**entity_base,
|
||||
"entity_id": "test.stripped",
|
||||
"id": "entity_stripped",
|
||||
"unique_id": "stripped",
|
||||
"name": "My Device Temperature",
|
||||
"name_v2": "Temperature",
|
||||
},
|
||||
{
|
||||
**entity_base,
|
||||
"entity_id": "test.stripped_and_renamed",
|
||||
"id": "entity_stripped_and_renamed",
|
||||
"unique_id": "stripped_and_renamed",
|
||||
"name": "My Device Temperature",
|
||||
"name_v2": "Heat",
|
||||
},
|
||||
],
|
||||
"deleted_entities": [
|
||||
{
|
||||
# Deleted entity
|
||||
# name should be reset to None
|
||||
# should add None to aliases
|
||||
"aliases": ["deleted_alias"],
|
||||
"area_id": None,
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_class": None,
|
||||
"disabled_by": None,
|
||||
"disabled_by_undefined": False,
|
||||
"entity_id": "test.deleted_entity",
|
||||
"hidden_by": None,
|
||||
"hidden_by_undefined": False,
|
||||
"icon": None,
|
||||
"id": "deleted-1",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Deleted Name",
|
||||
"options": {},
|
||||
"options_undefined": False,
|
||||
"orphaned_timestamp": None,
|
||||
"platform": "test_platform",
|
||||
"unique_id": "deleted-unique",
|
||||
}
|
||||
],
|
||||
"deleted_entities": [],
|
||||
},
|
||||
}
|
||||
|
||||
await er.async_load(hass)
|
||||
registry = er.async_get(hass)
|
||||
|
||||
entry = registry.async_get_or_create("test", "super_platform", "custom_name")
|
||||
assert entry.name == "My Custom Name"
|
||||
|
||||
entry = registry.async_get_or_create("test", "super_platform", "stripped")
|
||||
assert entry.name == "My Device Temperature"
|
||||
|
||||
entry = registry.async_get_or_create(
|
||||
"test", "super_platform", "stripped_and_renamed"
|
||||
)
|
||||
assert entry.name == "My Device Heat"
|
||||
|
||||
# Check migrated data
|
||||
await flush_store(registry._store)
|
||||
migrated_data = hass_storage[er.STORAGE_KEY]
|
||||
|
||||
migrated_entity_base = {
|
||||
"aliases": [],
|
||||
"aliases_v2": [None],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device_1234",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"has_entity_name": False,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"object_id_base": "Temperature",
|
||||
"options": {},
|
||||
"original_device_class": "temperature",
|
||||
"original_icon": None,
|
||||
"original_name": "Temperature",
|
||||
"platform": "super_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
}
|
||||
assert migrated_data == {
|
||||
"version": er.STORAGE_VERSION_MAJOR,
|
||||
"minor_version": er.STORAGE_VERSION_MINOR,
|
||||
@@ -1830,211 +1709,28 @@ async def test_migration_1_20(
|
||||
"data": {
|
||||
"entities": [
|
||||
{
|
||||
"aliases": [],
|
||||
"aliases_v2": [None],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.entity_name_no_custom",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-1",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": None,
|
||||
"name_v2": None,
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-1",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
},
|
||||
{
|
||||
"aliases": [],
|
||||
"aliases_v2": [None],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": None,
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.no_device",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-2",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Standalone Sensor",
|
||||
"name_v2": "Standalone Sensor",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-2",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
},
|
||||
{
|
||||
"aliases": [],
|
||||
"aliases_v2": [None],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.name_with_device_prefix",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-3",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "My device temperature",
|
||||
"name_v2": "Temperature",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-3",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
},
|
||||
{
|
||||
"aliases": [],
|
||||
"aliases_v2": [None],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
**migrated_entity_base,
|
||||
"entity_id": "test.custom_name",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-4",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Living Room Light",
|
||||
"name_v2": "Living Room Light",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-4",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
"id": "entity_custom_name",
|
||||
"unique_id": "custom_name",
|
||||
"name": "My Custom Name",
|
||||
},
|
||||
{
|
||||
"aliases": [],
|
||||
"aliases_v2": ["Living Room Light"],
|
||||
"area_id": None,
|
||||
"capabilities": {},
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_id": "device-1",
|
||||
"disabled_by": None,
|
||||
"entity_category": None,
|
||||
"entity_id": "test.custom_name_exposed",
|
||||
"has_entity_name": True,
|
||||
"hidden_by": None,
|
||||
"icon": None,
|
||||
"id": "entity-5",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Living Room Light",
|
||||
"name_v2": "Living Room Light",
|
||||
"object_id_base": "Test entity",
|
||||
"options": {
|
||||
"conversation": {"should_expose": True},
|
||||
},
|
||||
"original_device_class": None,
|
||||
"original_icon": None,
|
||||
"original_name": "Test entity",
|
||||
"platform": "test_platform",
|
||||
"previous_unique_id": None,
|
||||
"suggested_object_id": None,
|
||||
"supported_features": 0,
|
||||
"translation_key": None,
|
||||
"unique_id": "unique-5",
|
||||
"unit_of_measurement": None,
|
||||
"device_class": None,
|
||||
**migrated_entity_base,
|
||||
"entity_id": "test.stripped",
|
||||
"id": "entity_stripped",
|
||||
"unique_id": "stripped",
|
||||
"name": "My Device Temperature",
|
||||
},
|
||||
],
|
||||
"deleted_entities": [
|
||||
{
|
||||
"aliases": ["deleted_alias"],
|
||||
"aliases_v2": [None, "deleted_alias"],
|
||||
"area_id": None,
|
||||
"categories": {},
|
||||
"config_entry_id": None,
|
||||
"config_subentry_id": None,
|
||||
"created_at": "1970-01-01T00:00:00+00:00",
|
||||
"device_class": None,
|
||||
"disabled_by": None,
|
||||
"disabled_by_undefined": False,
|
||||
"entity_id": "test.deleted_entity",
|
||||
"hidden_by": None,
|
||||
"hidden_by_undefined": False,
|
||||
"icon": None,
|
||||
"id": "deleted-1",
|
||||
"labels": [],
|
||||
"modified_at": "1970-01-01T00:00:00+00:00",
|
||||
"name": "Deleted Name",
|
||||
"name_v2": None,
|
||||
"options": {},
|
||||
"options_undefined": False,
|
||||
"orphaned_timestamp": None,
|
||||
"platform": "test_platform",
|
||||
"unique_id": "deleted-unique",
|
||||
**migrated_entity_base,
|
||||
"entity_id": "test.stripped_and_renamed",
|
||||
"id": "entity_stripped_and_renamed",
|
||||
"unique_id": "stripped_and_renamed",
|
||||
"name": "My Device Heat",
|
||||
},
|
||||
],
|
||||
"deleted_entities": [],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3353,7 +3049,7 @@ async def test_has_entity_name_false_device_name_changes(
|
||||
assert updated.original_name_unprefixed == "Light Temperature"
|
||||
|
||||
updated2 = entity_registry.async_get(entry2.entity_id)
|
||||
assert updated2.name == "Brightness"
|
||||
assert updated2.name == "Hue Brightness"
|
||||
assert updated2.original_name_unprefixed is None
|
||||
|
||||
updated3 = entity_registry.async_get(entry3.entity_id)
|
||||
|
||||
@@ -203,7 +203,6 @@ class HomeAssistantSnapshotSerializer(AmberDataSerializer):
|
||||
)
|
||||
serialized.pop("categories")
|
||||
serialized.pop("compat_aliases")
|
||||
serialized.pop("compat_name")
|
||||
serialized.pop("original_name_unprefixed")
|
||||
serialized.pop("_cache")
|
||||
serialized["aliases"] = er._serialize_aliases(serialized["aliases"])
|
||||
|
||||
Reference in New Issue
Block a user