From 08af42b00ee3d9b2593a8afda53da7ababd1d76c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 12 Jul 2023 14:39:51 -1000 Subject: [PATCH] Fix mixed case service schema registration (#96448) --- homeassistant/core.py | 2 +- homeassistant/helpers/service.py | 3 +++ tests/helpers/test_service.py | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/homeassistant/core.py b/homeassistant/core.py index 82ea7228157..54f44d0998c 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1770,7 +1770,7 @@ class ServiceRegistry: the context. Will return NONE if the service does not exist as there is other error handling when calling the service if it does not exist. """ - if not (handler := self._services[domain][service]): + if not (handler := self._services[domain.lower()][service.lower()]): return SupportsResponse.NONE return handler.supports_response diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index ab0b4ea32e9..16a79b3ae12 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -701,6 +701,9 @@ def async_set_service_schema( hass: HomeAssistant, domain: str, service: str, schema: dict[str, Any] ) -> None: """Register a description for a service.""" + domain = domain.lower() + service = service.lower() + descriptions_cache: dict[ tuple[str, str], dict[str, Any] | None ] = hass.data.setdefault(SERVICE_DESCRIPTION_CACHE, {}) diff --git a/tests/helpers/test_service.py b/tests/helpers/test_service.py index 674d2e1af4c..d41b55c0b48 100644 --- a/tests/helpers/test_service.py +++ b/tests/helpers/test_service.py @@ -762,6 +762,27 @@ async def test_async_get_all_descriptions_dynamically_created_services( } +async def test_register_with_mixed_case(hass: HomeAssistant) -> None: + """Test registering a service with mixed case. + + For backwards compatibility, we have historically allowed mixed case, + and automatically converted it to lowercase. + """ + logger = hass.components.logger + logger_config = {logger.DOMAIN: {}} + await async_setup_component(hass, logger.DOMAIN, logger_config) + logger_domain_mixed = "LoGgEr" + hass.services.async_register( + logger_domain_mixed, "NeW_SeRVICE", lambda x: None, None + ) + service.async_set_service_schema( + hass, logger_domain_mixed, "NeW_SeRVICE", {"description": "new service"} + ) + descriptions = await service.async_get_all_descriptions(hass) + assert "description" in descriptions[logger.DOMAIN]["new_service"] + assert descriptions[logger.DOMAIN]["new_service"]["description"] == "new service" + + async def test_call_with_required_features(hass: HomeAssistant, mock_entities) -> None: """Test service calls invoked only if entity has required features.""" test_service_mock = AsyncMock(return_value=None)