Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor config.async_log_exception #104034

Merged
merged 3 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ async def async_from_config_dict(
try:
await conf_util.async_process_ha_core_config(hass, core_config)
except vol.Invalid as config_err:
conf_util.async_log_exception(config_err, "homeassistant", core_config, hass)
conf_util.async_log_schema_error(config_err, "homeassistant", core_config, hass)
return None
except HomeAssistantError:
_LOGGER.error(
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/device_tracker/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from homeassistant import util
from homeassistant.backports.functools import cached_property
from homeassistant.components import zone
from homeassistant.config import async_log_exception, load_yaml_config_file
from homeassistant.config import async_log_schema_error, load_yaml_config_file
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_GPS_ACCURACY,
Expand Down Expand Up @@ -1006,7 +1006,7 @@ async def async_load_config(
device = dev_schema(device)
device["dev_id"] = cv.slugify(dev_id)
except vol.Invalid as exp:
async_log_exception(exp, dev_id, devices, hass)
async_log_schema_error(exp, dev_id, devices, hass)
else:
result.append(Device(hass, **device))
return result
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ async def async_check_config_schema(
except vol.Invalid as ex:
integration = await async_get_integration(hass, DOMAIN)
# pylint: disable-next=protected-access
message, _ = conf_util._format_config_error(
message = conf_util._format_schema_error(
ex, domain, config, integration.documentation
)
raise ServiceValidationError(
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/template/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN
from homeassistant.config import async_log_exception, config_without_domain
from homeassistant.config import async_log_schema_error, config_without_domain
from homeassistant.const import CONF_BINARY_SENSORS, CONF_SENSORS, CONF_UNIQUE_ID
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.trigger import async_validate_trigger_config
Expand Down Expand Up @@ -80,7 +80,7 @@ async def async_validate_config(hass, config):
hass, cfg[CONF_TRIGGER]
)
except vol.Invalid as err:
async_log_exception(err, DOMAIN, cfg, hass)
async_log_schema_error(err, DOMAIN, cfg, hass)
continue

legacy_warn_printed = False
Expand Down
71 changes: 45 additions & 26 deletions homeassistant/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,21 +490,37 @@


@callback
def async_log_exception(
ex: Exception,
def async_log_schema_error(
ex: vol.Invalid,
domain: str,
config: dict,
hass: HomeAssistant,
link: str | None = None,
) -> None:
"""Log an error for configuration validation.
"""Log a schema validation error."""
if hass is not None:
async_notify_setup_error(hass, domain, link)
message = _format_schema_error(ex, domain, config, link)
_LOGGER.error(message)


@callback
def async_log_config_validator_error(
ex: vol.Invalid | HomeAssistantError,
domain: str,
config: dict,
hass: HomeAssistant,
link: str | None = None,
) -> None:
"""Log an error from a custom config validator."""
if isinstance(ex, vol.Invalid):
async_log_schema_error(ex, domain, config, hass, link)
return

This method must be run in the event loop.
"""
if hass is not None:
async_notify_setup_error(hass, domain, link)
message, is_friendly = _format_config_error(ex, domain, config, link)
_LOGGER.error(message, exc_info=not is_friendly and ex)
message = _format_homeassistant_error(ex, domain, config, link)
_LOGGER.error(message, exc_info=ex)


def _get_annotation(item: Any) -> tuple[str, int | str] | None:
Expand Down Expand Up @@ -655,25 +671,24 @@


@callback
def _format_config_error(
ex: Exception, domain: str, config: dict, link: str | None = None
) -> tuple[str, bool]:
"""Generate log exception for configuration validation.
def _format_homeassistant_error(
ex: HomeAssistantError, domain: str, config: dict, link: str | None = None
) -> str:
"""Format HomeAssistantError thrown by a custom config validator."""
message = f"Invalid config for [{domain}]: {str(ex) or repr(ex)}"

This method must be run in the event loop.
"""
is_friendly = False
if domain != CONF_CORE and link:
message += f" Please check the docs at {link}."

Check warning on line 681 in homeassistant/config.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/config.py#L681

Added line #L681 was not covered by tests

if isinstance(ex, vol.Invalid):
message = humanize_error(ex, domain, config, link)
is_friendly = True
else:
message = f"Invalid config for [{domain}]: {str(ex) or repr(ex)}"
return message

if domain != CONF_CORE and link:
message += f" Please check the docs at {link}."

return message, is_friendly
@callback
def _format_schema_error(
MartinHjelmare marked this conversation as resolved.
Show resolved Hide resolved
ex: vol.Invalid, domain: str, config: dict, link: str | None = None
) -> str:
"""Format configuration validation error."""
return humanize_error(ex, domain, config, link)


async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> None:
Expand Down Expand Up @@ -995,7 +1010,9 @@
await config_validator.async_validate_config(hass, config)
)
except (vol.Invalid, HomeAssistantError) as ex:
async_log_exception(ex, domain, config, hass, integration.documentation)
async_log_config_validator_error(
ex, domain, config, hass, integration.documentation
)
return None
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unknown error calling %s config validator", domain)
Expand All @@ -1006,7 +1023,7 @@
try:
return component.CONFIG_SCHEMA(config) # type: ignore[no-any-return]
except vol.Invalid as ex:
async_log_exception(ex, domain, config, hass, integration.documentation)
async_log_schema_error(ex, domain, config, hass, integration.documentation)
return None
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unknown error calling %s CONFIG_SCHEMA", domain)
Expand All @@ -1025,7 +1042,9 @@
try:
p_validated = component_platform_schema(p_config)
except vol.Invalid as ex:
async_log_exception(ex, domain, p_config, hass, integration.documentation)
async_log_schema_error(
ex, domain, p_config, hass, integration.documentation
)
continue
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
Expand Down Expand Up @@ -1062,7 +1081,7 @@
try:
p_validated = platform.PLATFORM_SCHEMA(p_config)
except vol.Invalid as ex:
async_log_exception(
async_log_schema_error(
ex,
f"{domain}.{p_name}",
p_config,
Expand Down
18 changes: 12 additions & 6 deletions homeassistant/helpers/check_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
CONF_PACKAGES,
CORE_CONFIG_SCHEMA,
YAML_CONFIG_FILE,
_format_config_error,
_format_homeassistant_error,
_format_schema_error,
config_per_platform,
extract_domain_configs,
load_yaml_config_file,
Expand Down Expand Up @@ -94,15 +95,20 @@
def _pack_error(
package: str, component: str, config: ConfigType, message: str
) -> None:
"""Handle errors from packages: _log_pkg_error."""
"""Handle errors from packages."""
message = f"Package {package} setup failed. Component {component} {message}"
domain = f"homeassistant.packages.{package}.{component}"
pack_config = core_config[CONF_PACKAGES].get(package, config)
result.add_warning(message, domain, pack_config)

def _comp_error(ex: Exception, domain: str, component_config: ConfigType) -> None:
"""Handle errors from components: async_log_exception."""
message = _format_config_error(ex, domain, component_config)[0]
def _comp_error(
ex: vol.Invalid | HomeAssistantError, domain: str, component_config: ConfigType
) -> None:
"""Handle errors from components."""
if isinstance(ex, vol.Invalid):
message = _format_schema_error(ex, domain, component_config)
else:
message = _format_homeassistant_error(ex, domain, component_config)

Check warning on line 111 in homeassistant/helpers/check_config.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/helpers/check_config.py#L111

Added line #L111 was not covered by tests
if domain in frontend_dependencies:
result.add_error(message, domain, component_config)
else:
Expand Down Expand Up @@ -149,7 +155,7 @@
result[CONF_CORE] = core_config
except vol.Invalid as err:
result.add_error(
_format_config_error(err, CONF_CORE, core_config)[0], CONF_CORE, core_config
_format_schema_error(err, CONF_CORE, core_config), CONF_CORE, core_config
)
core_config = {}

Expand Down