mirror of
https://github.com/home-assistant/core.git
synced 2026-08-03 20:24:55 +02:00
Deprecate passing add_helper_config_entry_to_device to async_handle_source_entity_changes (#176701)
This commit is contained in:
@@ -27,7 +27,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -105,7 +105,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
# humidifier's device.
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_humidifier_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -33,7 +33,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
# heater's device.
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_humidifier_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -78,7 +78,6 @@ async def async_setup_entry(
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -29,7 +29,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -37,7 +37,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
# to the humidity sensor's device.
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -35,7 +35,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -60,7 +60,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_get_parent_device_id(hass, entity_id),
|
||||
|
||||
@@ -27,7 +27,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -34,7 +34,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -205,7 +205,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
entry.async_on_unload(
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
add_helper_config_entry_to_device=False,
|
||||
helper_config_entry_id=entry.entry_id,
|
||||
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
|
||||
source_device_id=async_entity_id_to_device_id(
|
||||
|
||||
@@ -7,17 +7,18 @@ from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, valid_entity
|
||||
|
||||
from . import device_registry as dr, entity_registry as er
|
||||
from .event import async_track_entity_registry_updated_event
|
||||
from .frame import ReportBehavior, report_usage
|
||||
|
||||
|
||||
def async_handle_source_entity_changes(
|
||||
hass: HomeAssistant,
|
||||
*,
|
||||
add_helper_config_entry_to_device: bool = True,
|
||||
helper_config_entry_id: str,
|
||||
set_source_entity_id_or_uuid: Callable[[str], None],
|
||||
source_device_id: str | None,
|
||||
source_entity_id_or_uuid: str,
|
||||
source_entity_removed: Callable[[], Coroutine[Any, Any, None]] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> CALLBACK_TYPE:
|
||||
"""Handle changes to a helper entity's source entity.
|
||||
|
||||
@@ -31,11 +32,9 @@ def async_handle_source_entity_changes(
|
||||
called. If the source entity is identified by a UUID, the helper config entry
|
||||
is reloaded.
|
||||
- Source entity moved to another device: The helper entity is updated to link
|
||||
to the new device, and the helper config entry removed from the old device
|
||||
and added to the new device. Then the helper config entry is reloaded.
|
||||
to the new device. Then the helper config entry is reloaded.
|
||||
- Source entity removed from the device: The helper entity is updated to link
|
||||
to no device, and the helper config entry removed from the old device. Then
|
||||
the helper config entry is reloaded.
|
||||
to no device. Then the helper config entry is reloaded.
|
||||
|
||||
:param set_source_entity_id_or_uuid: A function which updates the source entity
|
||||
ID or UUID, e.g., in the helper config entry options.
|
||||
@@ -43,6 +42,22 @@ def async_handle_source_entity_changes(
|
||||
is removed. This can be used to clean up any resources related to the source
|
||||
entity or ask the user to select a new source entity.
|
||||
"""
|
||||
if "add_helper_config_entry_to_device" in kwargs:
|
||||
del kwargs["add_helper_config_entry_to_device"]
|
||||
# Adding the helper's config entry to the source device is no longer supported
|
||||
# now that a device belongs to a single config entry; the helper entities link to
|
||||
# the source device via their device_id instead.
|
||||
report_usage(
|
||||
"calls async_handle_source_entity_changes with "
|
||||
"add_helper_config_entry_to_device, which no longer has any effect",
|
||||
core_behavior=ReportBehavior.LOG,
|
||||
breaks_in_ha_version="2027.8.0",
|
||||
)
|
||||
if kwargs:
|
||||
raise TypeError(
|
||||
"async_handle_source_entity_changes() got unexpected keyword arguments "
|
||||
f"{', '.join(map(repr, kwargs))}"
|
||||
)
|
||||
|
||||
async def async_registry_updated(
|
||||
event: Event[er.EventEntityRegistryUpdatedData],
|
||||
@@ -89,9 +104,8 @@ def async_handle_source_entity_changes(
|
||||
# No need to do any cleanup
|
||||
return
|
||||
|
||||
# The source entity has been moved to a different device, update the helper
|
||||
# entities to link to the new device and the helper device to include the
|
||||
# helper config entry
|
||||
# The source entity has been moved to a different device; relink the helper
|
||||
# entities to the new device.
|
||||
for helper_entity in entity_registry.entities.get_entries_for_config_entry_id(
|
||||
helper_config_entry_id
|
||||
):
|
||||
@@ -100,17 +114,6 @@ def async_handle_source_entity_changes(
|
||||
helper_entity.entity_id, device_id=source_entity_entry.device_id
|
||||
)
|
||||
|
||||
if add_helper_config_entry_to_device:
|
||||
if source_entity_entry.device_id is not None:
|
||||
device_registry.async_update_device(
|
||||
source_entity_entry.device_id,
|
||||
add_config_entry_id=helper_config_entry_id,
|
||||
)
|
||||
|
||||
device_registry.async_update_device(
|
||||
source_device_id, remove_config_entry_id=helper_config_entry_id
|
||||
)
|
||||
|
||||
source_device_id = source_entity_entry.device_id
|
||||
|
||||
# Reload the config entry so the helper entity is recreated with
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tests for the helper entity helpers."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -213,6 +213,67 @@ def listen_entity_registry_events(
|
||||
return events
|
||||
|
||||
|
||||
@pytest.mark.parametrize("add_helper_config_entry_to_device", [True, False])
|
||||
async def test_async_handle_source_entity_changes_deprecated_kwarg(
|
||||
hass: HomeAssistant,
|
||||
add_helper_config_entry_to_device: bool,
|
||||
) -> None:
|
||||
"""The removed add_helper_config_entry_to_device kwarg is accepted but reported.
|
||||
|
||||
It is swallowed by **kwargs so callers still passing it don't raise, and reported on
|
||||
its presence rather than its value, since it no longer has any effect either way.
|
||||
"""
|
||||
with patch("homeassistant.helpers.helper_integration.report_usage") as report_usage:
|
||||
unsub = async_handle_source_entity_changes(
|
||||
hass,
|
||||
helper_config_entry_id="helper_config_entry_id",
|
||||
set_source_entity_id_or_uuid=Mock(),
|
||||
source_device_id=None,
|
||||
source_entity_id_or_uuid="sensor.test",
|
||||
add_helper_config_entry_to_device=add_helper_config_entry_to_device,
|
||||
)
|
||||
unsub()
|
||||
|
||||
report_usage.assert_called_once()
|
||||
assert "add_helper_config_entry_to_device" in report_usage.call_args[0][0]
|
||||
|
||||
|
||||
async def test_async_handle_source_entity_changes_rejects_unknown_kwarg(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""An unknown keyword argument still raises, as it did before **kwargs was added.
|
||||
|
||||
**kwargs only exists to swallow the deprecated add_helper_config_entry_to_device;
|
||||
anything else (e.g. a misspelling) must not be silently accepted.
|
||||
"""
|
||||
with pytest.raises(TypeError, match="unexpected keyword arguments 'unknown_kwarg'"):
|
||||
async_handle_source_entity_changes(
|
||||
hass,
|
||||
helper_config_entry_id="helper_config_entry_id",
|
||||
set_source_entity_id_or_uuid=Mock(),
|
||||
source_device_id=None,
|
||||
source_entity_id_or_uuid="sensor.test",
|
||||
unknown_kwarg=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_async_handle_source_entity_changes_without_deprecated_kwarg(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Not passing the removed add_helper_config_entry_to_device kwarg is not reported."""
|
||||
with patch("homeassistant.helpers.helper_integration.report_usage") as report_usage:
|
||||
unsub = async_handle_source_entity_changes(
|
||||
hass,
|
||||
helper_config_entry_id="helper_config_entry_id",
|
||||
set_source_entity_id_or_uuid=Mock(),
|
||||
source_device_id=None,
|
||||
source_entity_id_or_uuid="sensor.test",
|
||||
)
|
||||
unsub()
|
||||
|
||||
report_usage.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("source_entity_removed", [None])
|
||||
@pytest.mark.parametrize("use_entity_registry_id", [True, False])
|
||||
@pytest.mark.usefixtures("mock_helper_flow", "mock_helper_integration")
|
||||
|
||||
Reference in New Issue
Block a user