Only load services.yaml for integrations that have it (#112732)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Paulus Schoutsen 2024-03-11 14:05:32 -04:00 committed by GitHub
parent ec89886fac
commit 145657dc21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 43 additions and 7 deletions

View file

@ -633,16 +633,18 @@ async def async_get_all_descriptions(
ints_or_excs = await async_get_integrations(hass, domains_with_missing_services)
integrations: list[Integration] = []
for domain, int_or_exc in ints_or_excs.items():
if type(int_or_exc) is Integration: # noqa: E721
if type(int_or_exc) is Integration and int_or_exc.has_services: # noqa: E721
integrations.append(int_or_exc)
continue
if TYPE_CHECKING:
assert isinstance(int_or_exc, Exception)
_LOGGER.error("Failed to load integration: %s", domain, exc_info=int_or_exc)
contents = await hass.async_add_executor_job(
_load_services_files, hass, integrations
)
loaded = dict(zip(domains_with_missing_services, contents))
if integrations:
contents = await hass.async_add_executor_job(
_load_services_files, hass, integrations
)
loaded = dict(zip(domains_with_missing_services, contents))
# Load translations for all service domains
translations = await translation.async_get_translations(

View file

@ -838,6 +838,11 @@ class Integration:
"""Return if the integration has translations."""
return "translations" in self._top_level_files
@cached_property
def has_services(self) -> bool:
"""Return if the integration has services."""
return "services.yaml" in self._top_level_files
@property
def mqtt(self) -> list[str] | None:
"""Return Integration MQTT entries."""

View file

@ -35,6 +35,7 @@ from homeassistant.helpers import (
template,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.loader import async_get_integration
from homeassistant.setup import async_setup_component
from tests.common import (
@ -564,14 +565,29 @@ async def test_async_get_all_descriptions(hass: HomeAssistant) -> None:
"""Test async_get_all_descriptions."""
group = hass.components.group
group_config = {group.DOMAIN: {}}
await async_setup_component(hass, group.DOMAIN, group_config)
descriptions = await service.async_get_all_descriptions(hass)
assert await async_setup_component(hass, group.DOMAIN, group_config)
assert await async_setup_component(hass, "system_health", {})
with patch(
"homeassistant.helpers.service._load_services_files",
side_effect=service._load_services_files,
) as proxy_load_services_files:
descriptions = await service.async_get_all_descriptions(hass)
# Test we only load services.yaml for integrations with services.yaml
# And system_health has no services
assert proxy_load_services_files.mock_calls[0][1][1] == [
await async_get_integration(hass, "group")
]
assert len(descriptions) == 1
assert "description" in descriptions["group"]["reload"]
assert "fields" in descriptions["group"]["reload"]
# Does not have services
assert "system_health" not in descriptions
logger = hass.components.logger
logger_config = {logger.DOMAIN: {}}

View file

@ -1685,3 +1685,11 @@ async def test_integration_warnings(
"""Test integration warnings."""
await loader.async_get_integration(hass, "test_package_loaded_loop")
assert "configured to to import its code in the event loop" in caplog.text
async def test_has_services(hass: HomeAssistant, enable_custom_integrations) -> None:
"""Test has_services."""
integration = await loader.async_get_integration(hass, "test")
assert integration.has_services is False
integration = await loader.async_get_integration(hass, "test_with_services")
assert integration.has_services is True

View file

@ -0,0 +1 @@
"""Provide a mock integration."""

View file

@ -0,0 +1,4 @@
{
"domain": "test_with_services",
"version": "1.0"
}