Skip to content

Commit 912c480

Browse files
emontnemeryfrenck
authored andcommitted
Fix incorrect use of zip in service.async_get_all_descriptions (home-assistant#147013)
* Fix incorrect use of zip in service.async_get_all_descriptions * Fix lint errors in test
1 parent 8f13520 commit 912c480

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

homeassistant/helpers/service.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,12 @@ def _load_services_file(hass: HomeAssistant, integration: Integration) -> JSON_T
682682

683683
def _load_services_files(
684684
hass: HomeAssistant, integrations: Iterable[Integration]
685-
) -> list[JSON_TYPE]:
685+
) -> dict[str, JSON_TYPE]:
686686
"""Load service files for multiple integrations."""
687-
return [_load_services_file(hass, integration) for integration in integrations]
687+
return {
688+
integration.domain: _load_services_file(hass, integration)
689+
for integration in integrations
690+
}
688691

689692

690693
@callback
@@ -744,10 +747,9 @@ async def async_get_all_descriptions(
744747
_LOGGER.error("Failed to load integration: %s", domain, exc_info=int_or_exc)
745748

746749
if integrations:
747-
contents = await hass.async_add_executor_job(
750+
loaded = await hass.async_add_executor_job(
748751
_load_services_files, hass, integrations
749752
)
750-
loaded = dict(zip(domains_with_missing_services, contents, strict=False))
751753

752754
# Load translations for all service domains
753755
translations = await translation.async_get_translations(

tests/helpers/test_service.py

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from homeassistant.auth.permissions import PolicyPermissions
1717
import homeassistant.components # noqa: F401
1818
from homeassistant.components.group import DOMAIN as DOMAIN_GROUP, Group
19+
from homeassistant.components.input_button import DOMAIN as DOMAIN_INPUT_BUTTON
1920
from homeassistant.components.logger import DOMAIN as DOMAIN_LOGGER
2021
from homeassistant.components.shell_command import DOMAIN as DOMAIN_SHELL_COMMAND
2122
from homeassistant.components.system_health import DOMAIN as DOMAIN_SYSTEM_HEALTH
@@ -42,7 +43,12 @@
4243
entity_registry as er,
4344
service,
4445
)
45-
from homeassistant.loader import async_get_integration
46+
from homeassistant.helpers.translation import async_get_translations
47+
from homeassistant.loader import (
48+
Integration,
49+
async_get_integration,
50+
async_get_integrations,
51+
)
4652
from homeassistant.setup import async_setup_component
4753
from homeassistant.util.yaml.loader import parse_yaml
4854

@@ -1092,38 +1098,66 @@ async def test_async_get_all_descriptions_failing_integration(
10921098
"""Test async_get_all_descriptions when async_get_integrations returns an exception."""
10931099
group_config = {DOMAIN_GROUP: {}}
10941100
await async_setup_component(hass, DOMAIN_GROUP, group_config)
1095-
descriptions = await service.async_get_all_descriptions(hass)
1096-
1097-
assert len(descriptions) == 1
1098-
1099-
assert "description" in descriptions["group"]["reload"]
1100-
assert "fields" in descriptions["group"]["reload"]
11011101

11021102
logger_config = {DOMAIN_LOGGER: {}}
11031103
await async_setup_component(hass, DOMAIN_LOGGER, logger_config)
1104+
1105+
input_button_config = {DOMAIN_INPUT_BUTTON: {}}
1106+
await async_setup_component(hass, DOMAIN_INPUT_BUTTON, input_button_config)
1107+
1108+
async def wrap_get_integrations(
1109+
hass: HomeAssistant, domains: Iterable[str]
1110+
) -> dict[str, Integration | Exception]:
1111+
integrations = await async_get_integrations(hass, domains)
1112+
integrations[DOMAIN_LOGGER] = ImportError("Failed to load services.yaml")
1113+
return integrations
1114+
1115+
async def wrap_get_translations(
1116+
hass: HomeAssistant,
1117+
language: str,
1118+
category: str,
1119+
integrations: Iterable[str] | None = None,
1120+
config_flow: bool | None = None,
1121+
) -> dict[str, str]:
1122+
translations = await async_get_translations(
1123+
hass, language, category, integrations, config_flow
1124+
)
1125+
return {
1126+
key: value
1127+
for key, value in translations.items()
1128+
if not key.startswith("component.logger.services.")
1129+
}
1130+
11041131
with (
11051132
patch(
11061133
"homeassistant.helpers.service.async_get_integrations",
1107-
return_value={"logger": ImportError},
1134+
wraps=wrap_get_integrations,
11081135
),
11091136
patch(
11101137
"homeassistant.helpers.service.translation.async_get_translations",
1111-
return_value={},
1138+
wrap_get_translations,
11121139
),
11131140
):
11141141
descriptions = await service.async_get_all_descriptions(hass)
11151142

1116-
assert len(descriptions) == 2
1143+
assert len(descriptions) == 3
11171144
assert "Failed to load integration: logger" in caplog.text
11181145

11191146
# Services are empty defaults if the load fails but should
11201147
# not raise
1148+
assert descriptions[DOMAIN_GROUP]["remove"]["description"]
1149+
assert descriptions[DOMAIN_GROUP]["remove"]["fields"]
1150+
11211151
assert descriptions[DOMAIN_LOGGER]["set_level"] == {
11221152
"description": "",
11231153
"fields": {},
11241154
"name": "",
11251155
}
11261156

1157+
assert descriptions[DOMAIN_INPUT_BUTTON]["press"]["description"]
1158+
assert descriptions[DOMAIN_INPUT_BUTTON]["press"]["fields"] == {}
1159+
assert "target" in descriptions[DOMAIN_INPUT_BUTTON]["press"]
1160+
11271161
hass.services.async_register(DOMAIN_LOGGER, "new_service", lambda x: None, None)
11281162
service.async_set_service_schema(
11291163
hass, DOMAIN_LOGGER, "new_service", {"description": "new service"}

0 commit comments

Comments
 (0)