Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions homeassistant/helpers/entity_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,19 +608,12 @@ async def _async_add_entity( # noqa: C901
entity.add_to_platform_abort()
return

if self.config_entry is not None:
config_entry_id: str | None = self.config_entry.entry_id
else:
config_entry_id = None

device_info = entity.device_info
device_id = None
device = None

if config_entry_id is not None and device_info is not None:
processed_dev_info: dict[str, str | None] = {
"config_entry_id": config_entry_id
}
if self.config_entry and device_info is not None:
processed_dev_info: dict[str, str | None] = {}
for key in (
"connections",
"default_manufacturer",
Expand All @@ -641,6 +634,17 @@ async def _async_add_entity( # noqa: C901
key # type: ignore[literal-required]
]

if (
# device info that is purely meant for linking doesn't need default name
any(
key not in {"identifiers", "connections"}
for key in (processed_dev_info)
)
and "default_name" not in processed_dev_info
and not processed_dev_info.get("name")
):
processed_dev_info["name"] = self.config_entry.title
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the title is an empty string? Do we need a default for that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it shouldn't be allowed. The goal is that we always have a device name.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it an idea to only require this when has_entity_name is True?


if "configuration_url" in device_info:
if device_info["configuration_url"] is None:
processed_dev_info["configuration_url"] = None
Expand All @@ -660,7 +664,8 @@ async def _async_add_entity( # noqa: C901

try:
device = device_registry.async_get_or_create(
**processed_dev_info # type: ignore[arg-type]
config_entry_id=self.config_entry.entry_id,
**processed_dev_info, # type: ignore[arg-type]
)
device_id = device.id
except RequiredParameterMissing:
Expand Down
50 changes: 50 additions & 0 deletions tests/helpers/test_entity_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -1827,3 +1827,53 @@ async def async_setup_entry(hass, config_entry, async_add_entities):

assert len(hass.states.async_entity_ids()) == 1
assert registry.async_get(expected_entity_id) is not None


@pytest.mark.parametrize(
("entity_device_name", "entity_device_default_name", "expected_device_name"),
[
(None, None, "Mock Config Entry Title"),
("", None, "Mock Config Entry Title"),
(None, "Hello", "Hello"),
("Mock Device Name", None, "Mock Device Name"),
],
)
async def test_device_name_defaulting_config_entry(
hass: HomeAssistant,
entity_device_name: str,
entity_device_default_name: str,
expected_device_name: str,
) -> None:
"""Test setting the device name based on input info."""
device_info = {
"identifiers": {("hue", "1234")},
"name": entity_device_name,
}

if entity_device_default_name:
device_info["default_name"] = entity_device_default_name

class DeviceNameEntity(Entity):
_attr_unique_id = "qwer"
_attr_device_info = device_info

async def async_setup_entry(hass, config_entry, async_add_entities):
"""Mock setup entry method."""
async_add_entities([DeviceNameEntity()])
return True

platform = MockPlatform(async_setup_entry=async_setup_entry)
config_entry = MockConfigEntry(
title="Mock Config Entry Title", entry_id="super-mock-id"
)
entity_platform = MockEntityPlatform(
hass, platform_name=config_entry.domain, platform=platform
)

assert await entity_platform.async_setup_entry(config_entry)
await hass.async_block_till_done()

dev_reg = dr.async_get(hass)
device = dev_reg.async_get_device({("hue", "1234")})
assert device is not None
assert device.name == expected_device_name