Deprecate Configurator integration (#180912)

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Josef Zweck <josef@zweck.dev>
This commit is contained in:
Martin Hjelmare
2026-08-31 15:54:16 +02:00
committed by GitHub
co-authored by Copilot Autofix powered by AI Josef Zweck
parent cdd43afd39
commit 4a0594e543
2 changed files with 101 additions and 1 deletions
@@ -24,12 +24,16 @@ from homeassistant.core import (
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import async_generate_entity_id
from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.frame import ReportBehavior, report_usage
from homeassistant.helpers.service import async_register_admin_service
from homeassistant.helpers.typing import ConfigType
from homeassistant.util.async_ import run_callback_threadsafe
_KEY_INSTANCE = "configurator"
# The configurator integration is deprecated and can be removed in HA Core 2027.10
_BREAKS_IN_HA_VERSION = "2027.10"
DATA_REQUESTS = "configurator_requests"
ATTR_CONFIGURE_ID = "configure_id"
@@ -54,6 +58,17 @@ type ConfiguratorCallback = Callable[[list[dict[str, str]]], None]
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
def _report_deprecation() -> None:
"""Report use of the deprecated configurator integration."""
report_usage(
"uses the deprecated configurator integration, which should be replaced "
"by a config flow",
breaks_in_ha_version=_BREAKS_IN_HA_VERSION,
core_behavior=ReportBehavior.LOG,
exclude_integrations={DOMAIN},
)
@async_callback
def async_request_config(
hass: HomeAssistant,
@@ -69,6 +84,38 @@ def async_request_config(
) -> str:
"""Create a new request for configuration.
Will return an ID to be used for subsequent calls.
"""
_report_deprecation()
return _async_request_config(
hass,
name,
callback=callback,
description=description,
description_image=description_image,
submit_caption=submit_caption,
fields=fields,
link_name=link_name,
link_url=link_url,
entity_picture=entity_picture,
)
@async_callback
def _async_request_config(
hass: HomeAssistant,
name: str,
callback: ConfiguratorCallback | None = None,
description: str | None = None,
description_image: str | None = None,
submit_caption: str | None = None,
fields: list[dict[str, str]] | None = None,
link_name: str | None = None,
link_url: str | None = None,
entity_picture: str | None = None,
) -> str:
"""Create a new request for configuration.
Will return an ID to be used for sequent calls.
"""
if description and link_name is not None and link_url is not None:
@@ -97,8 +144,9 @@ def request_config(hass: HomeAssistant, *args: Any, **kwargs: Any) -> str:
Will return an ID to be used for sequent calls.
"""
_report_deprecation()
return run_callback_threadsafe(
hass.loop, ft.partial(async_request_config, hass, *args, **kwargs)
hass.loop, ft.partial(_async_request_config, hass, *args, **kwargs)
).result()
@@ -1,6 +1,8 @@
"""The tests for the Configurator component."""
from collections.abc import Callable, Coroutine
from datetime import timedelta
from typing import Any
import pytest
@@ -150,3 +152,53 @@ async def test_configure_service_requires_admin(
context=Context(user_id=hass_read_only_user.id),
blocking=True,
)
async def _async_request_config(
hass: HomeAssistant, name: str, callback: configurator.ConfiguratorCallback
) -> str:
"""Request config using the async API."""
return configurator.async_request_config(hass, name, callback)
async def _sync_request_config(
hass: HomeAssistant, name: str, callback: configurator.ConfiguratorCallback
) -> str:
"""Request config using the sync API from an executor thread."""
return await hass.async_add_executor_job(
configurator.request_config, hass, name, callback
)
@pytest.mark.parametrize(
"ignore_missing_translations", ["component.configurator.services.configure."]
)
@pytest.mark.parametrize("integration_frame_path", ["custom_components/my_integration"])
@pytest.mark.usefixtures("mock_integration_frame")
@pytest.mark.parametrize(
"request_config",
[_async_request_config, _sync_request_config],
ids=["async", "sync"],
)
async def test_request_config_deprecated(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
request_config: Callable[
[HomeAssistant, str, configurator.ConfiguratorCallback],
Coroutine[Any, Any, str],
],
) -> None:
"""Test that requesting a config warns about the deprecated integration."""
request_id = await request_config(hass, "Test Request", lambda _: None)
states = hass.states.async_all()
assert len(states) == 1
state = states[0]
assert state.state == configurator.STATE_CONFIGURE
assert state.attributes.get(configurator.ATTR_CONFIGURE_ID) == request_id
assert (
"Detected that custom integration 'my_integration' uses the deprecated "
"configurator integration" in caplog.text
)
assert "This will stop working in Home Assistant 2027.10" in caplog.text