mirror of
https://github.com/home-assistant/core.git
synced 2025-07-31 17:18:23 +00:00
Raise in EntityComponent.async_prepare_reload on configuration error
This commit is contained in:
parent
07ceafed62
commit
fca50bfbf8
@ -333,8 +333,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Remove all automations and load new ones from config."""
|
"""Remove all automations and load new ones from config."""
|
||||||
await async_get_blueprints(hass).async_reset_cache()
|
await async_get_blueprints(hass).async_reset_cache()
|
||||||
if (conf := await component.async_prepare_reload(skip_reset=True)) is None:
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
return
|
|
||||||
if automation_id := service_call.data.get(CONF_ID):
|
if automation_id := service_call.data.get(CONF_ID):
|
||||||
await _async_process_single_config(hass, conf, component, automation_id)
|
await _async_process_single_config(hass, conf, component, automation_id)
|
||||||
else:
|
else:
|
||||||
|
@ -194,8 +194,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
- Remove group.group entities not created by service calls and set them up again
|
- Remove group.group entities not created by service calls and set them up again
|
||||||
- Reload xxx.group platforms
|
- Reload xxx.group platforms
|
||||||
"""
|
"""
|
||||||
if (conf := await component.async_prepare_reload(skip_reset=True)) is None:
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
return
|
|
||||||
|
|
||||||
# Simplified + modified version of EntityPlatform.async_reset:
|
# Simplified + modified version of EntityPlatform.async_reset:
|
||||||
# - group.group never retries setup
|
# - group.group never retries setup
|
||||||
|
@ -121,8 +121,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Remove all input booleans and load new ones from config."""
|
"""Remove all input booleans and load new ones from config."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
return
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[
|
[
|
||||||
{CONF_ID: id_, **(conf or {})}
|
{CONF_ID: id_, **(conf or {})}
|
||||||
|
@ -106,8 +106,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Remove all input buttons and load new ones from config."""
|
"""Remove all input buttons and load new ones from config."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
return
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[
|
[
|
||||||
{CONF_ID: id_, **(conf or {})}
|
{CONF_ID: id_, **(conf or {})}
|
||||||
|
@ -159,8 +159,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Reload yaml entities."""
|
"""Reload yaml entities."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
conf = {DOMAIN: {}}
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
||||||
)
|
)
|
||||||
|
@ -137,8 +137,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Reload yaml entities."""
|
"""Reload yaml entities."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
conf = {DOMAIN: {}}
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[{CONF_ID: id_, **conf} for id_, conf in conf.get(DOMAIN, {}).items()]
|
[{CONF_ID: id_, **conf} for id_, conf in conf.get(DOMAIN, {}).items()]
|
||||||
)
|
)
|
||||||
|
@ -167,8 +167,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Reload yaml entities."""
|
"""Reload yaml entities."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
conf = {DOMAIN: {}}
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
||||||
)
|
)
|
||||||
|
@ -137,8 +137,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Reload yaml entities."""
|
"""Reload yaml entities."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
conf = {DOMAIN: {}}
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[{CONF_ID: id_, **(cfg or {})} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
[{CONF_ID: id_, **(cfg or {})} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
||||||
)
|
)
|
||||||
|
@ -403,8 +403,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def async_reload_yaml(call: ServiceCall) -> None:
|
async def async_reload_yaml(call: ServiceCall) -> None:
|
||||||
"""Reload YAML."""
|
"""Reload YAML."""
|
||||||
conf = await entity_component.async_prepare_reload(skip_reset=True)
|
conf = await entity_component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
return
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
await filter_yaml_data(hass, conf.get(DOMAIN, []))
|
await filter_yaml_data(hass, conf.get(DOMAIN, []))
|
||||||
)
|
)
|
||||||
|
@ -187,8 +187,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Reload yaml entities."""
|
"""Reload yaml entities."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
conf = {DOMAIN: {}}
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
||||||
)
|
)
|
||||||
|
@ -229,8 +229,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service(service: ServiceCall) -> None:
|
async def reload_service(service: ServiceCall) -> None:
|
||||||
"""Call a service to reload scripts."""
|
"""Call a service to reload scripts."""
|
||||||
await async_get_blueprints(hass).async_reset_cache()
|
await async_get_blueprints(hass).async_reset_cache()
|
||||||
if (conf := await component.async_prepare_reload(skip_reset=True)) is None:
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
return
|
|
||||||
await _async_process_config(hass, conf, component)
|
await _async_process_config(hass, conf, component)
|
||||||
|
|
||||||
async def turn_on_service(service: ServiceCall) -> None:
|
async def turn_on_service(service: ServiceCall) -> None:
|
||||||
|
@ -141,8 +141,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Reload yaml entities."""
|
"""Reload yaml entities."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
conf = {DOMAIN: {}}
|
|
||||||
await yaml_collection.async_load(
|
await yaml_collection.async_load(
|
||||||
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
[{CONF_ID: id_, **cfg} for id_, cfg in conf.get(DOMAIN, {}).items()]
|
||||||
)
|
)
|
||||||
|
@ -265,8 +265,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Remove all zones and load new ones from config."""
|
"""Remove all zones and load new ones from config."""
|
||||||
conf = await component.async_prepare_reload(skip_reset=True)
|
conf = await component.async_prepare_reload(skip_reset=True)
|
||||||
if conf is None:
|
|
||||||
return
|
|
||||||
await yaml_collection.async_load(conf[DOMAIN])
|
await yaml_collection.async_load(conf[DOMAIN])
|
||||||
|
|
||||||
service.async_register_admin_service(
|
service.async_register_admin_service(
|
||||||
|
@ -16,7 +16,7 @@ from pathlib import Path
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, Literal, overload
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from awesomeversion import AwesomeVersion
|
from awesomeversion import AwesomeVersion
|
||||||
@ -1208,6 +1208,39 @@ def _get_log_message_and_stack_print_pref(
|
|||||||
return (log_message, show_stack_trace, placeholders)
|
return (log_message, show_stack_trace, placeholders)
|
||||||
|
|
||||||
|
|
||||||
|
# The complicated overloads are due to a limitation in mypy, details in
|
||||||
|
# https://github.com/python/mypy/issues/7333
|
||||||
|
@overload
|
||||||
|
@callback
|
||||||
|
async def async_process_component_and_handle_errors(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigType,
|
||||||
|
integration: Integration,
|
||||||
|
) -> ConfigType | None: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
@callback
|
||||||
|
async def async_process_component_and_handle_errors(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigType,
|
||||||
|
integration: Integration,
|
||||||
|
*,
|
||||||
|
raise_on_failure: Literal[True],
|
||||||
|
) -> ConfigType: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
@callback
|
||||||
|
async def async_process_component_and_handle_errors(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigType,
|
||||||
|
integration: Integration,
|
||||||
|
*,
|
||||||
|
raise_on_failure: bool,
|
||||||
|
) -> ConfigType | None: ...
|
||||||
|
|
||||||
|
|
||||||
async def async_process_component_and_handle_errors(
|
async def async_process_component_and_handle_errors(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: ConfigType,
|
config: ConfigType,
|
||||||
@ -1226,7 +1259,7 @@ async def async_process_component_and_handle_errors(
|
|||||||
hass, config, integration
|
hass, config, integration
|
||||||
)
|
)
|
||||||
async_handle_component_errors(
|
async_handle_component_errors(
|
||||||
hass, integration_config_info, integration, raise_on_failure
|
hass, integration_config_info, integration, raise_on_failure=raise_on_failure
|
||||||
)
|
)
|
||||||
return async_drop_config_annotations(integration_config_info, integration)
|
return async_drop_config_annotations(integration_config_info, integration)
|
||||||
|
|
||||||
|
@ -348,28 +348,19 @@ class EntityComponent(Generic[_EntityT]):
|
|||||||
if found:
|
if found:
|
||||||
await found.async_remove_entity(entity_id)
|
await found.async_remove_entity(entity_id)
|
||||||
|
|
||||||
async def async_prepare_reload(
|
async def async_prepare_reload(self, *, skip_reset: bool = False) -> ConfigType:
|
||||||
self, *, skip_reset: bool = False
|
|
||||||
) -> ConfigType | None:
|
|
||||||
"""Prepare reloading this entity component.
|
"""Prepare reloading this entity component.
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
try:
|
conf = await conf_util.async_hass_config_yaml(self.hass)
|
||||||
conf = await conf_util.async_hass_config_yaml(self.hass)
|
|
||||||
except HomeAssistantError as err:
|
|
||||||
self.logger.error(err)
|
|
||||||
return None
|
|
||||||
|
|
||||||
integration = await async_get_integration(self.hass, self.domain)
|
integration = await async_get_integration(self.hass, self.domain)
|
||||||
|
|
||||||
processed_conf = await conf_util.async_process_component_and_handle_errors(
|
processed_conf = await conf_util.async_process_component_and_handle_errors(
|
||||||
self.hass, conf, integration
|
self.hass, conf, integration, raise_on_failure=True
|
||||||
)
|
)
|
||||||
|
|
||||||
if processed_conf is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not skip_reset:
|
if not skip_reset:
|
||||||
await self._async_reset()
|
await self._async_reset()
|
||||||
|
|
||||||
|
@ -136,6 +136,8 @@ async def _async_reconfig_platform(
|
|||||||
await asyncio.gather(*tasks)
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
|
||||||
|
# The complicated overloads are due to a limitation in mypy, details in
|
||||||
|
# https://github.com/python/mypy/issues/7333
|
||||||
@overload
|
@overload
|
||||||
async def async_integration_yaml_config(
|
async def async_integration_yaml_config(
|
||||||
hass: HomeAssistant, integration_name: str
|
hass: HomeAssistant, integration_name: str
|
||||||
|
@ -704,9 +704,12 @@ async def test_reload_config_handles_load_fails(
|
|||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert calls[0].data.get("event") == "test_event"
|
assert calls[0].data.get("event") == "test_event"
|
||||||
|
|
||||||
with patch(
|
with (
|
||||||
"homeassistant.config.load_yaml_config_file",
|
patch(
|
||||||
side_effect=HomeAssistantError("bla"),
|
"homeassistant.config.load_yaml_config_file",
|
||||||
|
side_effect=HomeAssistantError("bla"),
|
||||||
|
),
|
||||||
|
pytest.raises(HomeAssistantError),
|
||||||
):
|
):
|
||||||
await hass.services.async_call(automation.DOMAIN, SERVICE_RELOAD, blocking=True)
|
await hass.services.async_call(automation.DOMAIN, SERVICE_RELOAD, blocking=True)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user