Only load services.yaml for integrations that have it (#112732)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
ec89886fac
commit
145657dc21
7 changed files with 43 additions and 7 deletions
|
@ -633,16 +633,18 @@ async def async_get_all_descriptions(
|
||||||
ints_or_excs = await async_get_integrations(hass, domains_with_missing_services)
|
ints_or_excs = await async_get_integrations(hass, domains_with_missing_services)
|
||||||
integrations: list[Integration] = []
|
integrations: list[Integration] = []
|
||||||
for domain, int_or_exc in ints_or_excs.items():
|
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)
|
integrations.append(int_or_exc)
|
||||||
continue
|
continue
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
assert isinstance(int_or_exc, Exception)
|
assert isinstance(int_or_exc, Exception)
|
||||||
_LOGGER.error("Failed to load integration: %s", domain, exc_info=int_or_exc)
|
_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
|
if integrations:
|
||||||
)
|
contents = await hass.async_add_executor_job(
|
||||||
loaded = dict(zip(domains_with_missing_services, contents))
|
_load_services_files, hass, integrations
|
||||||
|
)
|
||||||
|
loaded = dict(zip(domains_with_missing_services, contents))
|
||||||
|
|
||||||
# Load translations for all service domains
|
# Load translations for all service domains
|
||||||
translations = await translation.async_get_translations(
|
translations = await translation.async_get_translations(
|
||||||
|
|
|
@ -838,6 +838,11 @@ class Integration:
|
||||||
"""Return if the integration has translations."""
|
"""Return if the integration has translations."""
|
||||||
return "translations" in self._top_level_files
|
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
|
@property
|
||||||
def mqtt(self) -> list[str] | None:
|
def mqtt(self) -> list[str] | None:
|
||||||
"""Return Integration MQTT entries."""
|
"""Return Integration MQTT entries."""
|
||||||
|
|
|
@ -35,6 +35,7 @@ from homeassistant.helpers import (
|
||||||
template,
|
template,
|
||||||
)
|
)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.loader import async_get_integration
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
|
@ -564,14 +565,29 @@ async def test_async_get_all_descriptions(hass: HomeAssistant) -> None:
|
||||||
"""Test async_get_all_descriptions."""
|
"""Test async_get_all_descriptions."""
|
||||||
group = hass.components.group
|
group = hass.components.group
|
||||||
group_config = {group.DOMAIN: {}}
|
group_config = {group.DOMAIN: {}}
|
||||||
await async_setup_component(hass, group.DOMAIN, group_config)
|
assert await async_setup_component(hass, group.DOMAIN, group_config)
|
||||||
descriptions = await service.async_get_all_descriptions(hass)
|
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 len(descriptions) == 1
|
||||||
|
|
||||||
assert "description" in descriptions["group"]["reload"]
|
assert "description" in descriptions["group"]["reload"]
|
||||||
assert "fields" 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 = hass.components.logger
|
||||||
logger_config = {logger.DOMAIN: {}}
|
logger_config = {logger.DOMAIN: {}}
|
||||||
|
|
||||||
|
|
|
@ -1685,3 +1685,11 @@ async def test_integration_warnings(
|
||||||
"""Test integration warnings."""
|
"""Test integration warnings."""
|
||||||
await loader.async_get_integration(hass, "test_package_loaded_loop")
|
await loader.async_get_integration(hass, "test_package_loaded_loop")
|
||||||
assert "configured to to import its code in the event loop" in caplog.text
|
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
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
"""Provide a mock integration."""
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"domain": "test_with_services",
|
||||||
|
"version": "1.0"
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue