Skip to content

Commit

Permalink
Use relative paths in configuration validation error messages (#104064)
Browse files Browse the repository at this point in the history
  • Loading branch information
emontnemery committed Nov 16, 2023
1 parent 98030a9 commit d8a49b1
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 113 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ async def async_check_config_schema(
integration = await async_get_integration(hass, DOMAIN)
# pylint: disable-next=protected-access
message = conf_util.format_schema_error(
ex, domain, config, integration.documentation
hass, ex, domain, config, integration.documentation
)
raise ServiceValidationError(
message,
Expand Down
49 changes: 36 additions & 13 deletions homeassistant/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ def async_log_schema_error(
"""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)
message = format_schema_error(hass, ex, domain, config, link)
_LOGGER.error(message)


Expand Down Expand Up @@ -590,7 +590,13 @@ def find_annotation_rec(
return find_annotation_rec(config, list(path), None)


def _relpath(hass: HomeAssistant, path: str) -> str:
"""Return path relative to the Home Assistant config dir."""
return os.path.relpath(path, hass.config.config_dir)


def stringify_invalid(
hass: HomeAssistant,
ex: vol.Invalid,
domain: str,
config: dict,
Expand All @@ -613,7 +619,7 @@ def stringify_invalid(
else:
message_suffix = ""
if annotation := find_annotation(config, ex.path):
message_prefix += f" at {annotation[0]}, line {annotation[1]}"
message_prefix += f" at {_relpath(hass, annotation[0])}, line {annotation[1]}"
path = "->".join(str(m) for m in ex.path)
if ex.error_message == "extra keys not allowed":
return (
Expand Down Expand Up @@ -643,6 +649,7 @@ def stringify_invalid(


def humanize_error(
hass: HomeAssistant,
validation_error: vol.Invalid,
domain: str,
config: dict,
Expand All @@ -657,12 +664,14 @@ def humanize_error(
if isinstance(validation_error, vol.MultipleInvalid):
return "\n".join(
sorted(
humanize_error(sub_error, domain, config, link, max_sub_error_length)
humanize_error(
hass, sub_error, domain, config, link, max_sub_error_length
)
for sub_error in validation_error.errors
)
)
return stringify_invalid(
validation_error, domain, config, link, max_sub_error_length
hass, validation_error, domain, config, link, max_sub_error_length
)


Expand All @@ -681,10 +690,14 @@ def format_homeassistant_error(

@callback
def format_schema_error(
ex: vol.Invalid, domain: str, config: dict, link: str | None = None
hass: HomeAssistant,
ex: vol.Invalid,
domain: str,
config: dict,
link: str | None = None,
) -> str:
"""Format configuration validation error."""
return humanize_error(ex, domain, config, link)
return humanize_error(hass, ex, domain, config, link)


async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> None:
Expand Down Expand Up @@ -806,15 +819,19 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> Non
hac.units = get_unit_system(config[CONF_UNIT_SYSTEM])


def _log_pkg_error(package: str, component: str, config: dict, message: str) -> None:
def _log_pkg_error(
hass: HomeAssistant, package: str, component: str, config: dict, message: str
) -> None:
"""Log an error while merging packages."""
message = f"Package {package} setup failed. {message}"

pack_config = config[CONF_CORE][CONF_PACKAGES].get(package, config)
message += (
f" (See {getattr(pack_config, '__config_file__', '?')}:"
f"{getattr(pack_config, '__line__', '?')})."
)
config_file = getattr(pack_config, "__config_file__", None)
if config_file:
config_file = _relpath(hass, config_file)
else:
config_file = "?"
message += f" (See {config_file}:{getattr(pack_config, '__line__', '?')})."

_LOGGER.error(message)

Expand Down Expand Up @@ -893,7 +910,9 @@ async def merge_packages_config(
hass: HomeAssistant,
config: dict,
packages: dict[str, Any],
_log_pkg_error: Callable[[str, str, dict, str], None] = _log_pkg_error,
_log_pkg_error: Callable[
[HomeAssistant, str, str, dict, str], None
] = _log_pkg_error,
) -> dict:
"""Merge packages into the top-level configuration. Mutate config."""
PACKAGES_CONFIG_SCHEMA(packages)
Expand All @@ -912,14 +931,15 @@ async def merge_packages_config(
component = integration.get_component()
except LOAD_EXCEPTIONS as ex:
_log_pkg_error(
hass,
pack_name,
comp_name,
config,
f"Integration {comp_name} caused error: {str(ex)}",
)
continue
except INTEGRATION_LOAD_EXCEPTIONS as ex:
_log_pkg_error(pack_name, comp_name, config, str(ex))
_log_pkg_error(hass, pack_name, comp_name, config, str(ex))
continue

try:
Expand Down Expand Up @@ -953,6 +973,7 @@ async def merge_packages_config(

if not isinstance(comp_conf, dict):
_log_pkg_error(
hass,
pack_name,
comp_name,
config,
Expand All @@ -965,6 +986,7 @@ async def merge_packages_config(

if not isinstance(config[comp_name], dict):
_log_pkg_error(
hass,
pack_name,
comp_name,
config,
Expand All @@ -975,6 +997,7 @@ async def merge_packages_config(
duplicate_key = _recursive_merge(conf=config[comp_name], package=comp_conf)
if duplicate_key:
_log_pkg_error(
hass,
pack_name,
comp_name,
config,
Expand Down
12 changes: 9 additions & 3 deletions homeassistant/helpers/check_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ async def async_check_ha_config_file( # noqa: C901
async_clear_install_history(hass)

def _pack_error(
package: str, component: str, config: ConfigType, message: str
hass: HomeAssistant,
package: str,
component: str,
config: ConfigType,
message: str,
) -> None:
"""Handle errors from packages."""
message = f"Package {package} setup failed. {message}"
Expand All @@ -109,7 +113,7 @@ def _comp_error(
) -> None:
"""Handle errors from components."""
if isinstance(ex, vol.Invalid):
message = format_schema_error(ex, domain, component_config)
message = format_schema_error(hass, ex, domain, component_config)
else:
message = format_homeassistant_error(ex, domain, component_config)
if domain in frontend_dependencies:
Expand Down Expand Up @@ -158,7 +162,9 @@ async def _get_integration(
result[CONF_CORE] = core_config
except vol.Invalid as err:
result.add_error(
format_schema_error(err, CONF_CORE, core_config), CONF_CORE, core_config
format_schema_error(hass, err, CONF_CORE, core_config),
CONF_CORE,
core_config,
)
core_config = {}

Expand Down
5 changes: 2 additions & 3 deletions tests/helpers/test_check_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,8 @@ async def test_bad_core_config(hass: HomeAssistant) -> None:

error = CheckConfigError(
(
"Invalid config for [homeassistant] at "
f"{hass.config.path(YAML_CONFIG_FILE)}, line 2: "
"not a valid value for dictionary value 'unit_system', got 'bad'."
f"Invalid config for [homeassistant] at {YAML_CONFIG_FILE}, line 2:"
" not a valid value for dictionary value 'unit_system', got 'bad'."
),
"homeassistant",
{"unit_system": "bad"},
Expand Down

0 comments on commit d8a49b1

Please sign in to comment.