Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check aliases in get_by_name functions for areas/floors #118995

Closed
wants to merge 2 commits into from
Closed
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
20 changes: 16 additions & 4 deletions homeassistant/helpers/area_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,19 @@ def async_get_area(self, area_id: str) -> AreaEntry | None:

@callback
def async_get_area_by_name(self, name: str) -> AreaEntry | None:
Copy link
Member

Choose a reason for hiding this comment

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

This should be added as a a new function so we don't have unintended side effects.

We should then update template method to call it. Probably also update suggested_area processing in device registry to use it.

"""Get area by name."""
return self.areas.get_by_name(name)
"""Get area by name or alias."""
if area := self.areas.get_by_name(name):
return area

# Check aliases
normalized_name = normalize_name(name)
Copy link
Member

Choose a reason for hiding this comment

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

This is not using an index and will be very inefficient. Shouldn't we add a secondary alias index so we can call areas.get_by_alias(name) ?

for area in self.async_list_areas():
for alias in area.aliases:
normalized_alias = normalize_name(alias)
if normalized_name == normalized_alias:
return area

return None

@callback
def async_list_areas(self) -> Iterable[AreaEntry]:
Expand Down Expand Up @@ -404,8 +415,9 @@ def _async_setup_cleanup(self) -> None:

@callback
def _removed_from_registry_filter(
event_data: fr.EventFloorRegistryUpdatedData
| lr.EventLabelRegistryUpdatedData,
event_data: (
fr.EventFloorRegistryUpdatedData | lr.EventLabelRegistryUpdatedData
),
) -> bool:
"""Filter all except for the item removed from registry events."""
return event_data["action"] == "remove"
Expand Down
15 changes: 13 additions & 2 deletions homeassistant/helpers/floor_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,19 @@ def async_get_floor(self, floor_id: str) -> FloorEntry | None:

@callback
def async_get_floor_by_name(self, name: str) -> FloorEntry | None:
"""Get floor by name."""
return self.floors.get_by_name(name)
"""Get floor by name or alias."""
if floor := self.floors.get_by_name(name):
return floor

# Check aliases
normalized_name = normalize_name(name)
for floor in self.async_list_floors():
for alias in floor.aliases:
normalized_alias = normalize_name(alias)
if normalized_name == normalized_alias:
return floor

return None

@callback
def async_list_floors(self) -> Iterable[FloorEntry]:
Expand Down
6 changes: 6 additions & 0 deletions tests/components/config/test_area_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,9 @@ async def test_update_area_with_name_already_in_use(
assert msg["error"]["code"] == "invalid_info"
assert msg["error"]["message"] == "The name mock 2 (mock2) is already in use"
assert len(area_registry.areas) == 2


async def test_get_area_by_alias(area_registry: ar.AreaRegistry) -> None:
"""Test async_get_area_by_name also works with aliases."""
area = area_registry.async_create("area 1", aliases={"alias 1"})
assert area_registry.async_get_area_by_name("alias 1") == area
6 changes: 6 additions & 0 deletions tests/components/config/test_floor_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,9 @@ async def test_update_with_name_already_in_use(
== "The name Second floor (secondfloor) is already in use"
)
assert len(floor_registry.floors) == 2


async def test_get_floor_by_alias(floor_registry: fr.FloorRegistry) -> None:
"""Test async_get_floor_by_name also works with aliases."""
floor = floor_registry.async_create("floor 1", aliases={"alias 1"})
assert floor_registry.async_get_floor_by_name("alias 1") == floor