Add aliases to entity registry items (#84239)
This commit is contained in:
parent
8ca92254b6
commit
1f3da9cf1a
5 changed files with 36 additions and 3 deletions
|
@ -102,6 +102,7 @@ def websocket_get_entity(
|
||||||
vol.Required("type"): "config/entity_registry/update",
|
vol.Required("type"): "config/entity_registry/update",
|
||||||
vol.Required("entity_id"): cv.entity_id,
|
vol.Required("entity_id"): cv.entity_id,
|
||||||
# If passed in, we update value. Passing None will remove old value.
|
# If passed in, we update value. Passing None will remove old value.
|
||||||
|
vol.Optional("aliases"): list,
|
||||||
vol.Optional("area_id"): vol.Any(str, None),
|
vol.Optional("area_id"): vol.Any(str, None),
|
||||||
vol.Optional("device_class"): vol.Any(str, None),
|
vol.Optional("device_class"): vol.Any(str, None),
|
||||||
vol.Optional("icon"): vol.Any(str, None),
|
vol.Optional("icon"): vol.Any(str, None),
|
||||||
|
@ -160,6 +161,10 @@ def websocket_update_entity(
|
||||||
if key in msg:
|
if key in msg:
|
||||||
changes[key] = msg[key]
|
changes[key] = msg[key]
|
||||||
|
|
||||||
|
if "aliases" in msg:
|
||||||
|
# Convert aliases to a set
|
||||||
|
changes["aliases"] = set(msg["aliases"])
|
||||||
|
|
||||||
if "disabled_by" in msg and msg["disabled_by"] is None:
|
if "disabled_by" in msg and msg["disabled_by"] is None:
|
||||||
# Don't allow enabling an entity of a disabled device
|
# Don't allow enabling an entity of a disabled device
|
||||||
if entity_entry.device_id:
|
if entity_entry.device_id:
|
||||||
|
@ -265,6 +270,7 @@ def _entry_dict(entry: er.RegistryEntry) -> dict[str, Any]:
|
||||||
def _entry_ext_dict(entry: er.RegistryEntry) -> dict[str, Any]:
|
def _entry_ext_dict(entry: er.RegistryEntry) -> dict[str, Any]:
|
||||||
"""Convert entry to API format."""
|
"""Convert entry to API format."""
|
||||||
data = _entry_dict(entry)
|
data = _entry_dict(entry)
|
||||||
|
data["aliases"] = entry.aliases
|
||||||
data["capabilities"] = entry.capabilities
|
data["capabilities"] = entry.capabilities
|
||||||
data["device_class"] = entry.device_class
|
data["device_class"] = entry.device_class
|
||||||
data["options"] = entry.options
|
data["options"] = entry.options
|
||||||
|
|
|
@ -61,7 +61,7 @@ SAVE_DELAY = 10
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
STORAGE_VERSION_MAJOR = 1
|
STORAGE_VERSION_MAJOR = 1
|
||||||
STORAGE_VERSION_MINOR = 9
|
STORAGE_VERSION_MINOR = 10
|
||||||
STORAGE_KEY = "core.entity_registry"
|
STORAGE_KEY = "core.entity_registry"
|
||||||
|
|
||||||
# Attributes relevant to describing entity
|
# Attributes relevant to describing entity
|
||||||
|
@ -104,6 +104,7 @@ class RegistryEntry:
|
||||||
entity_id: str = attr.ib()
|
entity_id: str = attr.ib()
|
||||||
unique_id: str = attr.ib()
|
unique_id: str = attr.ib()
|
||||||
platform: str = attr.ib()
|
platform: str = attr.ib()
|
||||||
|
aliases: set[str] = attr.ib(factory=set)
|
||||||
area_id: str | None = attr.ib(default=None)
|
area_id: str | None = attr.ib(default=None)
|
||||||
capabilities: Mapping[str, Any] | None = attr.ib(default=None)
|
capabilities: Mapping[str, Any] | None = attr.ib(default=None)
|
||||||
config_entry_id: str | None = attr.ib(default=None)
|
config_entry_id: str | None = attr.ib(default=None)
|
||||||
|
@ -242,6 +243,11 @@ class EntityRegistryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
|
||||||
for entity in data["entities"]:
|
for entity in data["entities"]:
|
||||||
entity["translation_key"] = None
|
entity["translation_key"] = None
|
||||||
|
|
||||||
|
if old_major_version == 1 and old_minor_version < 10:
|
||||||
|
# Version 1.10 adds aliases
|
||||||
|
for entity in data["entities"]:
|
||||||
|
entity["aliases"] = []
|
||||||
|
|
||||||
if old_major_version > 1:
|
if old_major_version > 1:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
return data
|
return data
|
||||||
|
@ -590,6 +596,7 @@ class EntityRegistry:
|
||||||
self,
|
self,
|
||||||
entity_id: str,
|
entity_id: str,
|
||||||
*,
|
*,
|
||||||
|
aliases: set[str] | UndefinedType = UNDEFINED,
|
||||||
area_id: str | None | UndefinedType = UNDEFINED,
|
area_id: str | None | UndefinedType = UNDEFINED,
|
||||||
capabilities: Mapping[str, Any] | None | UndefinedType = UNDEFINED,
|
capabilities: Mapping[str, Any] | None | UndefinedType = UNDEFINED,
|
||||||
config_entry_id: str | None | UndefinedType = UNDEFINED,
|
config_entry_id: str | None | UndefinedType = UNDEFINED,
|
||||||
|
@ -641,6 +648,7 @@ class EntityRegistry:
|
||||||
raise ValueError("entity_category must be a valid EntityCategory instance")
|
raise ValueError("entity_category must be a valid EntityCategory instance")
|
||||||
|
|
||||||
for attr_name, value in (
|
for attr_name, value in (
|
||||||
|
("aliases", aliases),
|
||||||
("area_id", area_id),
|
("area_id", area_id),
|
||||||
("capabilities", capabilities),
|
("capabilities", capabilities),
|
||||||
("config_entry_id", config_entry_id),
|
("config_entry_id", config_entry_id),
|
||||||
|
@ -716,6 +724,7 @@ class EntityRegistry:
|
||||||
self,
|
self,
|
||||||
entity_id: str,
|
entity_id: str,
|
||||||
*,
|
*,
|
||||||
|
aliases: set[str] | UndefinedType = UNDEFINED,
|
||||||
area_id: str | None | UndefinedType = UNDEFINED,
|
area_id: str | None | UndefinedType = UNDEFINED,
|
||||||
capabilities: Mapping[str, Any] | None | UndefinedType = UNDEFINED,
|
capabilities: Mapping[str, Any] | None | UndefinedType = UNDEFINED,
|
||||||
config_entry_id: str | None | UndefinedType = UNDEFINED,
|
config_entry_id: str | None | UndefinedType = UNDEFINED,
|
||||||
|
@ -739,6 +748,7 @@ class EntityRegistry:
|
||||||
"""Update properties of an entity."""
|
"""Update properties of an entity."""
|
||||||
return self._async_update_entity(
|
return self._async_update_entity(
|
||||||
entity_id,
|
entity_id,
|
||||||
|
aliases=aliases,
|
||||||
area_id=area_id,
|
area_id=area_id,
|
||||||
capabilities=capabilities,
|
capabilities=capabilities,
|
||||||
config_entry_id=config_entry_id,
|
config_entry_id=config_entry_id,
|
||||||
|
@ -821,6 +831,7 @@ class EntityRegistry:
|
||||||
entity["entity_category"] = None
|
entity["entity_category"] = None
|
||||||
|
|
||||||
entities[entity["entity_id"]] = RegistryEntry(
|
entities[entity["entity_id"]] = RegistryEntry(
|
||||||
|
aliases=set(entity["aliases"]),
|
||||||
area_id=entity["area_id"],
|
area_id=entity["area_id"],
|
||||||
capabilities=entity["capabilities"],
|
capabilities=entity["capabilities"],
|
||||||
config_entry_id=entity["config_entry_id"],
|
config_entry_id=entity["config_entry_id"],
|
||||||
|
@ -865,6 +876,7 @@ class EntityRegistry:
|
||||||
|
|
||||||
data["entities"] = [
|
data["entities"] = [
|
||||||
{
|
{
|
||||||
|
"aliases": list(entry.aliases),
|
||||||
"area_id": entry.area_id,
|
"area_id": entry.area_id,
|
||||||
"capabilities": entry.capabilities,
|
"capabilities": entry.capabilities,
|
||||||
"config_entry_id": entry.config_entry_id,
|
"config_entry_id": entry.config_entry_id,
|
||||||
|
|
|
@ -24,6 +24,7 @@ pytest-socket==0.5.1
|
||||||
pytest-test-groups==1.0.3
|
pytest-test-groups==1.0.3
|
||||||
pytest-sugar==0.9.5
|
pytest-sugar==0.9.5
|
||||||
pytest-timeout==2.1.0
|
pytest-timeout==2.1.0
|
||||||
|
pytest-unordered==0.5.2
|
||||||
pytest-xdist==2.5.0
|
pytest-xdist==2.5.0
|
||||||
pytest==7.2.0
|
pytest==7.2.0
|
||||||
requests_mock==1.10.0
|
requests_mock==1.10.0
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""Test entity_registry API."""
|
"""Test entity_registry API."""
|
||||||
import pytest
|
import pytest
|
||||||
|
from pytest_unordered import unordered
|
||||||
|
|
||||||
from homeassistant.components.config import entity_registry
|
from homeassistant.components.config import entity_registry
|
||||||
from homeassistant.const import ATTR_ICON
|
from homeassistant.const import ATTR_ICON
|
||||||
|
@ -159,6 +160,7 @@ async def test_get_entity(hass, client):
|
||||||
msg = await client.receive_json()
|
msg = await client.receive_json()
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
|
"aliases": [],
|
||||||
"area_id": None,
|
"area_id": None,
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
@ -191,6 +193,7 @@ async def test_get_entity(hass, client):
|
||||||
msg = await client.receive_json()
|
msg = await client.receive_json()
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
|
"aliases": [],
|
||||||
"area_id": None,
|
"area_id": None,
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
@ -244,6 +247,7 @@ async def test_update_entity(hass, client):
|
||||||
"id": 6,
|
"id": 6,
|
||||||
"type": "config/entity_registry/update",
|
"type": "config/entity_registry/update",
|
||||||
"entity_id": "test_domain.world",
|
"entity_id": "test_domain.world",
|
||||||
|
"aliases": ["alias_1", "alias_2"],
|
||||||
"area_id": "mock-area-id",
|
"area_id": "mock-area-id",
|
||||||
"device_class": "custom_device_class",
|
"device_class": "custom_device_class",
|
||||||
"hidden_by": "user", # We exchange strings over the WS API, not enums
|
"hidden_by": "user", # We exchange strings over the WS API, not enums
|
||||||
|
@ -256,6 +260,7 @@ async def test_update_entity(hass, client):
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
"entity_entry": {
|
"entity_entry": {
|
||||||
|
"aliases": unordered(["alias_1", "alias_2"]),
|
||||||
"area_id": "mock-area-id",
|
"area_id": "mock-area-id",
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
@ -330,6 +335,7 @@ async def test_update_entity(hass, client):
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
"entity_entry": {
|
"entity_entry": {
|
||||||
|
"aliases": unordered(["alias_1", "alias_2"]),
|
||||||
"area_id": "mock-area-id",
|
"area_id": "mock-area-id",
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
@ -369,6 +375,7 @@ async def test_update_entity(hass, client):
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
"entity_entry": {
|
"entity_entry": {
|
||||||
|
"aliases": unordered(["alias_1", "alias_2"]),
|
||||||
"area_id": "mock-area-id",
|
"area_id": "mock-area-id",
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
@ -420,6 +427,7 @@ async def test_update_entity_require_restart(hass, client):
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
"entity_entry": {
|
"entity_entry": {
|
||||||
|
"aliases": [],
|
||||||
"area_id": None,
|
"area_id": None,
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": config_entry.entry_id,
|
"config_entry_id": config_entry.entry_id,
|
||||||
|
@ -527,6 +535,7 @@ async def test_update_entity_no_changes(hass, client):
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
"entity_entry": {
|
"entity_entry": {
|
||||||
|
"aliases": [],
|
||||||
"area_id": None,
|
"area_id": None,
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
@ -615,6 +624,7 @@ async def test_update_entity_id(hass, client):
|
||||||
|
|
||||||
assert msg["result"] == {
|
assert msg["result"] == {
|
||||||
"entity_entry": {
|
"entity_entry": {
|
||||||
|
"aliases": [],
|
||||||
"area_id": None,
|
"area_id": None,
|
||||||
"capabilities": None,
|
"capabilities": None,
|
||||||
"config_entry_id": None,
|
"config_entry_id": None,
|
||||||
|
|
|
@ -136,6 +136,7 @@ def test_get_or_create_updates_data(registry):
|
||||||
"light.hue_5678",
|
"light.hue_5678",
|
||||||
"5678",
|
"5678",
|
||||||
"hue",
|
"hue",
|
||||||
|
aliases=set(),
|
||||||
area_id=None,
|
area_id=None,
|
||||||
capabilities={"new-max": 150},
|
capabilities={"new-max": 150},
|
||||||
config_entry_id=new_config_entry.entry_id,
|
config_entry_id=new_config_entry.entry_id,
|
||||||
|
@ -179,6 +180,7 @@ def test_get_or_create_updates_data(registry):
|
||||||
"light.hue_5678",
|
"light.hue_5678",
|
||||||
"5678",
|
"5678",
|
||||||
"hue",
|
"hue",
|
||||||
|
aliases=set(),
|
||||||
area_id=None,
|
area_id=None,
|
||||||
capabilities=None,
|
capabilities=None,
|
||||||
config_entry_id=None,
|
config_entry_id=None,
|
||||||
|
@ -253,6 +255,7 @@ async def test_loading_saving_data(hass, registry):
|
||||||
)
|
)
|
||||||
registry.async_update_entity(
|
registry.async_update_entity(
|
||||||
orig_entry2.entity_id,
|
orig_entry2.entity_id,
|
||||||
|
aliases={"initial_alias_1", "initial_alias_2"},
|
||||||
area_id="mock-area-id",
|
area_id="mock-area-id",
|
||||||
device_class="user-class",
|
device_class="user-class",
|
||||||
name="User Name",
|
name="User Name",
|
||||||
|
@ -663,9 +666,10 @@ async def test_update_entity(registry):
|
||||||
)
|
)
|
||||||
|
|
||||||
for attr_name, new_value in (
|
for attr_name, new_value in (
|
||||||
("name", "new name"),
|
("aliases", {"alias_1", "alias_2"}),
|
||||||
("icon", "new icon"),
|
|
||||||
("disabled_by", er.RegistryEntryDisabler.USER),
|
("disabled_by", er.RegistryEntryDisabler.USER),
|
||||||
|
("icon", "new icon"),
|
||||||
|
("name", "new name"),
|
||||||
):
|
):
|
||||||
changes = {attr_name: new_value}
|
changes = {attr_name: new_value}
|
||||||
updated_entry = registry.async_update_entity(entry.entity_id, **changes)
|
updated_entry = registry.async_update_entity(entry.entity_id, **changes)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue