Move thread safety in floor_registry sooner (#117044)

This commit is contained in:
J. Nick Koston 2024-05-07 18:48:38 -05:00 committed by GitHub
parent 27d45f04c4
commit 0b2c29fdb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 3 deletions

View File

@ -121,6 +121,7 @@ class FloorRegistry(BaseRegistry[FloorRegistryStoreData]):
level: int | None = None,
) -> FloorEntry:
"""Create a new floor."""
self.hass.verify_event_loop_thread("async_create")
if floor := self.async_get_floor_by_name(name):
raise ValueError(
f"The name {name} ({floor.normalized_name}) is already in use"
@ -139,7 +140,7 @@ class FloorRegistry(BaseRegistry[FloorRegistryStoreData]):
floor_id = floor.floor_id
self.floors[floor_id] = floor
self.async_schedule_save()
self.hass.bus.async_fire(
self.hass.bus.async_fire_internal(
EVENT_FLOOR_REGISTRY_UPDATED,
EventFloorRegistryUpdatedData(
action="create",
@ -151,8 +152,9 @@ class FloorRegistry(BaseRegistry[FloorRegistryStoreData]):
@callback
def async_delete(self, floor_id: str) -> None:
"""Delete floor."""
self.hass.verify_event_loop_thread("async_delete")
del self.floors[floor_id]
self.hass.bus.async_fire(
self.hass.bus.async_fire_internal(
EVENT_FLOOR_REGISTRY_UPDATED,
EventFloorRegistryUpdatedData(
action="remove",
@ -189,10 +191,11 @@ class FloorRegistry(BaseRegistry[FloorRegistryStoreData]):
if not changes:
return old
self.hass.verify_event_loop_thread("async_update")
new = self.floors[floor_id] = dataclasses.replace(old, **changes) # type: ignore[arg-type]
self.async_schedule_save()
self.hass.bus.async_fire(
self.hass.bus.async_fire_internal(
EVENT_FLOOR_REGISTRY_UPDATED,
EventFloorRegistryUpdatedData(
action="update",

View File

@ -1,5 +1,6 @@
"""Tests for the floor registry."""
from functools import partial
import re
from typing import Any
@ -357,3 +358,45 @@ async def test_floor_removed_from_areas(
entries = ar.async_entries_for_floor(area_registry, floor.floor_id)
assert len(entries) == 0
async def test_async_create_thread_safety(
hass: HomeAssistant,
floor_registry: fr.FloorRegistry,
) -> None:
"""Test async_create raises when called from wrong thread."""
with pytest.raises(
RuntimeError,
match="Detected code that calls async_create from a thread. Please report this issue.",
):
await hass.async_add_executor_job(floor_registry.async_create, "any")
async def test_async_delete_thread_safety(
hass: HomeAssistant,
floor_registry: fr.FloorRegistry,
) -> None:
"""Test async_delete raises when called from wrong thread."""
any_floor = floor_registry.async_create("any")
with pytest.raises(
RuntimeError,
match="Detected code that calls async_delete from a thread. Please report this issue.",
):
await hass.async_add_executor_job(floor_registry.async_delete, any_floor)
async def test_async_update_thread_safety(
hass: HomeAssistant,
floor_registry: fr.FloorRegistry,
) -> None:
"""Test async_update raises when called from wrong thread."""
any_floor = floor_registry.async_create("any")
with pytest.raises(
RuntimeError,
match="Detected code that calls async_update from a thread. Please report this issue.",
):
await hass.async_add_executor_job(
partial(floor_registry.async_update, any_floor.floor_id, name="new name")
)