Raise error for entity services without a correct schema (#151165)

pull/152311/head
G Johansson 2025-09-14 19:17:26 +02:00 committed by GitHub
parent 49e75c9cf8
commit af9717c1cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 26 additions and 35 deletions

View File

@ -1118,18 +1118,14 @@ class ReloadServiceHelper[_T]:
def _validate_entity_service_schema(
schema: VolDictType | VolSchemaType | None,
schema: VolDictType | VolSchemaType | None, service: str
) -> VolSchemaType:
"""Validate that a schema is an entity service schema."""
if schema is None or isinstance(schema, dict):
return cv.make_entity_service_schema(schema)
if not cv.is_entity_service_schema(schema):
from .frame import ReportBehavior, report_usage # noqa: PLC0415
report_usage(
"registers an entity service with a non entity service schema",
core_behavior=ReportBehavior.LOG,
breaks_in_ha_version="2025.9",
raise HomeAssistantError(
f"The {service} service registers an entity service with a non entity service schema"
)
return schema
@ -1153,7 +1149,7 @@ def async_register_entity_service(
EntityPlatform.async_register_entity_service and should not be called
directly by integrations.
"""
schema = _validate_entity_service_schema(schema)
schema = _validate_entity_service_schema(schema, f"{domain}.{name}")
service_func: str | HassJob[..., Any]
service_func = func if isinstance(func, str) else HassJob(func)
@ -1189,7 +1185,7 @@ def async_register_platform_entity_service(
"""Help registering a platform entity service."""
from .entity_platform import DATA_DOMAIN_PLATFORM_ENTITIES # noqa: PLC0415
schema = _validate_entity_service_schema(schema)
schema = _validate_entity_service_schema(schema, f"{service_domain}.{service_name}")
service_func: str | HassJob[..., Any]
service_func = func if isinstance(func, str) else HassJob(func)

View File

@ -560,11 +560,10 @@ async def test_register_entity_service(
async def test_register_entity_service_non_entity_service_schema(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
hass: HomeAssistant,
) -> None:
"""Test attempting to register a service with a non entity service schema."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
expected_message = "registers an entity service with a non entity service schema"
for idx, schema in enumerate(
(
@ -573,9 +572,9 @@ async def test_register_entity_service_non_entity_service_schema(
vol.Any(vol.Schema({"some": str})),
)
):
component.async_register_entity_service(f"hello_{idx}", schema, Mock())
assert expected_message in caplog.text
caplog.clear()
expected_message = f"The test_domain.hello_{idx} service registers an entity service with a non entity service schema"
with pytest.raises(HomeAssistantError, match=expected_message):
component.async_register_entity_service(f"hello_{idx}", schema, Mock())
for idx, schema in enumerate(
(
@ -585,7 +584,6 @@ async def test_register_entity_service_non_entity_service_schema(
)
):
component.async_register_entity_service(f"test_service_{idx}", schema, Mock())
assert expected_message not in caplog.text
async def test_register_entity_service_response_data(hass: HomeAssistant) -> None:

View File

@ -1878,13 +1878,12 @@ async def test_register_entity_service_none_schema(
async def test_register_entity_service_non_entity_service_schema(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
hass: HomeAssistant,
) -> None:
"""Test attempting to register a service with a non entity service schema."""
entity_platform = MockEntityPlatform(
hass, domain="mock_integration", platform_name="mock_platform", platform=None
)
expected_message = "registers an entity service with a non entity service schema"
for idx, schema in enumerate(
(
@ -1893,9 +1892,11 @@ async def test_register_entity_service_non_entity_service_schema(
vol.Any(vol.Schema({"some": str})),
)
):
entity_platform.async_register_entity_service(f"hello_{idx}", schema, Mock())
assert expected_message in caplog.text
caplog.clear()
expected_message = f"The mock_platform.hello_{idx} service registers an entity service with a non entity service schema"
with pytest.raises(HomeAssistantError, match=expected_message):
entity_platform.async_register_entity_service(
f"hello_{idx}", schema, Mock()
)
for idx, schema in enumerate(
(
@ -1907,7 +1908,6 @@ async def test_register_entity_service_non_entity_service_schema(
entity_platform.async_register_entity_service(
f"test_service_{idx}", schema, Mock()
)
assert expected_message not in caplog.text
@pytest.mark.parametrize("update_before_add", [True, False])

View File

@ -5,7 +5,6 @@ from collections.abc import Iterable
from copy import deepcopy
import dataclasses
import io
import logging
from typing import Any
from unittest.mock import AsyncMock, Mock, patch
@ -39,6 +38,7 @@ from homeassistant.core import (
SupportsResponse,
callback,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
area_registry as ar,
config_validation as cv,
@ -2761,7 +2761,7 @@ async def test_register_platform_entity_service_none_schema(
async def test_register_platform_entity_service_non_entity_service_schema(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
hass: HomeAssistant,
) -> None:
"""Test attempting to register a service with a non entity service schema."""
expected_message = "registers an entity service with a non entity service schema"
@ -2773,16 +2773,15 @@ async def test_register_platform_entity_service_non_entity_service_schema(
vol.Any(vol.Schema({"some": str})),
)
):
service.async_register_platform_entity_service(
hass,
"mock_platform",
f"hello_{idx}",
entity_domain="mock_integration",
schema=schema,
func=Mock(),
)
assert expected_message in caplog.text
caplog.clear()
with pytest.raises(HomeAssistantError, match=expected_message):
service.async_register_platform_entity_service(
hass,
"mock_platform",
f"hello_{idx}",
entity_domain="mock_integration",
schema=schema,
func=Mock(),
)
for idx, schema in enumerate(
(
@ -2799,5 +2798,3 @@ async def test_register_platform_entity_service_non_entity_service_schema(
schema=schema,
func=Mock(),
)
assert expected_message not in caplog.text
assert not any(x.levelno > logging.DEBUG for x in caplog.records)