Improve formatting of package errors (#103976)
This commit is contained in:
parent
86f87262ed
commit
98030a9ce1
8 changed files with 94 additions and 16 deletions
|
@ -84,11 +84,7 @@ SCRIPT_CONFIG_PATH = "scripts.yaml"
|
||||||
SCENE_CONFIG_PATH = "scenes.yaml"
|
SCENE_CONFIG_PATH = "scenes.yaml"
|
||||||
|
|
||||||
LOAD_EXCEPTIONS = (ImportError, FileNotFoundError)
|
LOAD_EXCEPTIONS = (ImportError, FileNotFoundError)
|
||||||
INTEGRATION_LOAD_EXCEPTIONS = (
|
INTEGRATION_LOAD_EXCEPTIONS = (IntegrationNotFound, RequirementsNotFound)
|
||||||
IntegrationNotFound,
|
|
||||||
RequirementsNotFound,
|
|
||||||
*LOAD_EXCEPTIONS,
|
|
||||||
)
|
|
||||||
|
|
||||||
SAFE_MODE_FILENAME = "safe-mode"
|
SAFE_MODE_FILENAME = "safe-mode"
|
||||||
|
|
||||||
|
@ -812,7 +808,7 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> Non
|
||||||
|
|
||||||
def _log_pkg_error(package: str, component: str, config: dict, message: str) -> None:
|
def _log_pkg_error(package: str, component: str, config: dict, message: str) -> None:
|
||||||
"""Log an error while merging packages."""
|
"""Log an error while merging packages."""
|
||||||
message = f"Package {package} setup failed. Integration {component} {message}"
|
message = f"Package {package} setup failed. {message}"
|
||||||
|
|
||||||
pack_config = config[CONF_CORE][CONF_PACKAGES].get(package, config)
|
pack_config = config[CONF_CORE][CONF_PACKAGES].get(package, config)
|
||||||
message += (
|
message += (
|
||||||
|
@ -897,7 +893,7 @@ async def merge_packages_config(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: dict,
|
config: dict,
|
||||||
packages: dict[str, Any],
|
packages: dict[str, Any],
|
||||||
_log_pkg_error: Callable = _log_pkg_error,
|
_log_pkg_error: Callable[[str, str, dict, str], None] = _log_pkg_error,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Merge packages into the top-level configuration. Mutate config."""
|
"""Merge packages into the top-level configuration. Mutate config."""
|
||||||
PACKAGES_CONFIG_SCHEMA(packages)
|
PACKAGES_CONFIG_SCHEMA(packages)
|
||||||
|
@ -914,6 +910,14 @@ async def merge_packages_config(
|
||||||
hass, domain
|
hass, domain
|
||||||
)
|
)
|
||||||
component = integration.get_component()
|
component = integration.get_component()
|
||||||
|
except LOAD_EXCEPTIONS as ex:
|
||||||
|
_log_pkg_error(
|
||||||
|
pack_name,
|
||||||
|
comp_name,
|
||||||
|
config,
|
||||||
|
f"Integration {comp_name} caused error: {str(ex)}",
|
||||||
|
)
|
||||||
|
continue
|
||||||
except INTEGRATION_LOAD_EXCEPTIONS as ex:
|
except INTEGRATION_LOAD_EXCEPTIONS as ex:
|
||||||
_log_pkg_error(pack_name, comp_name, config, str(ex))
|
_log_pkg_error(pack_name, comp_name, config, str(ex))
|
||||||
continue
|
continue
|
||||||
|
@ -949,7 +953,10 @@ async def merge_packages_config(
|
||||||
|
|
||||||
if not isinstance(comp_conf, dict):
|
if not isinstance(comp_conf, dict):
|
||||||
_log_pkg_error(
|
_log_pkg_error(
|
||||||
pack_name, comp_name, config, "cannot be merged. Expected a dict."
|
pack_name,
|
||||||
|
comp_name,
|
||||||
|
config,
|
||||||
|
f"Integration {comp_name} cannot be merged. Expected a dict.",
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -961,14 +968,17 @@ async def merge_packages_config(
|
||||||
pack_name,
|
pack_name,
|
||||||
comp_name,
|
comp_name,
|
||||||
config,
|
config,
|
||||||
"cannot be merged. Dict expected in main config.",
|
f"Integration {comp_name} cannot be merged. Dict expected in main config.",
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
duplicate_key = _recursive_merge(conf=config[comp_name], package=comp_conf)
|
duplicate_key = _recursive_merge(conf=config[comp_name], package=comp_conf)
|
||||||
if duplicate_key:
|
if duplicate_key:
|
||||||
_log_pkg_error(
|
_log_pkg_error(
|
||||||
pack_name, comp_name, config, f"has duplicate key '{duplicate_key}'"
|
pack_name,
|
||||||
|
comp_name,
|
||||||
|
config,
|
||||||
|
f"Integration {comp_name} has duplicate key '{duplicate_key}'.",
|
||||||
)
|
)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
|
@ -96,7 +96,7 @@ async def async_check_ha_config_file( # noqa: C901
|
||||||
package: str, component: str, config: ConfigType, message: str
|
package: str, component: str, config: ConfigType, message: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle errors from packages."""
|
"""Handle errors from packages."""
|
||||||
message = f"Package {package} setup failed. Component {component} {message}"
|
message = f"Package {package} setup failed. {message}"
|
||||||
domain = f"homeassistant.packages.{package}.{component}"
|
domain = f"homeassistant.packages.{package}.{component}"
|
||||||
pack_config = core_config[CONF_PACKAGES].get(package, config)
|
pack_config = core_config[CONF_PACKAGES].get(package, config)
|
||||||
result.add_warning(message, domain, pack_config)
|
result.add_warning(message, domain, pack_config)
|
||||||
|
|
4
tests/fixtures/core/config/package_exceptions/packages/configuration.yaml
vendored
Normal file
4
tests/fixtures/core/config/package_exceptions/packages/configuration.yaml
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
homeassistant:
|
||||||
|
packages:
|
||||||
|
pack_1:
|
||||||
|
test_domain:
|
3
tests/fixtures/core/config/package_exceptions/packages_include_dir_named/configuration.yaml
vendored
Normal file
3
tests/fixtures/core/config/package_exceptions/packages_include_dir_named/configuration.yaml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
homeassistant:
|
||||||
|
# Load packages
|
||||||
|
packages: !include_dir_named integrations
|
|
@ -0,0 +1 @@
|
||||||
|
test_domain:
|
|
@ -380,7 +380,7 @@ async def test_package_invalid(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
warning = CheckConfigError(
|
warning = CheckConfigError(
|
||||||
(
|
(
|
||||||
"Package p1 setup failed. Component group cannot be merged. Expected a "
|
"Package p1 setup failed. Integration group cannot be merged. Expected a "
|
||||||
"dict."
|
"dict."
|
||||||
),
|
),
|
||||||
"homeassistant.packages.p1.group",
|
"homeassistant.packages.p1.group",
|
||||||
|
|
|
@ -314,16 +314,36 @@
|
||||||
list([
|
list([
|
||||||
'Package pack_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:9).',
|
'Package pack_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:9).',
|
||||||
'Package pack_2 setup failed. Integration adr_0007_2 cannot be merged. Expected a dict. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:13).',
|
'Package pack_2 setup failed. Integration adr_0007_2 cannot be merged. Expected a dict. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:13).',
|
||||||
"Package pack_4 setup failed. Integration adr_0007_3 has duplicate key 'host' (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:20).",
|
"Package pack_4 setup failed. Integration adr_0007_3 has duplicate key 'host'. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:20).",
|
||||||
"Package pack_5 setup failed. Integration unknown_integration Integration 'unknown_integration' not found. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:23).",
|
"Package pack_5 setup failed. Integration 'unknown_integration' not found. (See <BASE_PATH>/fixtures/core/config/package_errors/packages/configuration.yaml:23).",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_package_merge_error[packages_include_dir_named]
|
# name: test_package_merge_error[packages_include_dir_named]
|
||||||
list([
|
list([
|
||||||
'Package adr_0007_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_1.yaml:2).',
|
'Package adr_0007_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_1.yaml:2).',
|
||||||
'Package adr_0007_2 setup failed. Integration adr_0007_2 cannot be merged. Expected a dict. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_2.yaml:2).',
|
'Package adr_0007_2 setup failed. Integration adr_0007_2 cannot be merged. Expected a dict. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_2.yaml:2).',
|
||||||
"Package adr_0007_3_2 setup failed. Integration adr_0007_3 has duplicate key 'host' (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_3_2.yaml:1).",
|
"Package adr_0007_3_2 setup failed. Integration adr_0007_3 has duplicate key 'host'. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_3_2.yaml:1).",
|
||||||
"Package unknown_integration setup failed. Integration unknown_integration Integration 'unknown_integration' not found. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/unknown_integration.yaml:2).",
|
"Package unknown_integration setup failed. Integration 'unknown_integration' not found. (See <BASE_PATH>/fixtures/core/config/package_errors/packages_include_dir_named/integrations/unknown_integration.yaml:2).",
|
||||||
|
])
|
||||||
|
# ---
|
||||||
|
# name: test_package_merge_exception[packages-error0]
|
||||||
|
list([
|
||||||
|
"Package pack_1 setup failed. Integration test_domain caused error: No such file or directory: b'liblibc.a' (See <BASE_PATH>/fixtures/core/config/package_exceptions/packages/configuration.yaml:4).",
|
||||||
|
])
|
||||||
|
# ---
|
||||||
|
# name: test_package_merge_exception[packages-error1]
|
||||||
|
list([
|
||||||
|
"Package pack_1 setup failed. Integration test_domain caused error: ModuleNotFoundError: No module named 'not_installed_something' (See <BASE_PATH>/fixtures/core/config/package_exceptions/packages/configuration.yaml:4).",
|
||||||
|
])
|
||||||
|
# ---
|
||||||
|
# name: test_package_merge_exception[packages_include_dir_named-error0]
|
||||||
|
list([
|
||||||
|
"Package unknown_integration setup failed. Integration test_domain caused error: No such file or directory: b'liblibc.a' (See <BASE_PATH>/fixtures/core/config/package_exceptions/packages_include_dir_named/integrations/unknown_integration.yaml:1).",
|
||||||
|
])
|
||||||
|
# ---
|
||||||
|
# name: test_package_merge_exception[packages_include_dir_named-error1]
|
||||||
|
list([
|
||||||
|
"Package unknown_integration setup failed. Integration test_domain caused error: ModuleNotFoundError: No module named 'not_installed_something' (See <BASE_PATH>/fixtures/core/config/package_exceptions/packages_include_dir_named/integrations/unknown_integration.yaml:1).",
|
||||||
])
|
])
|
||||||
# ---
|
# ---
|
||||||
# name: test_yaml_error[basic]
|
# name: test_yaml_error[basic]
|
||||||
|
|
|
@ -1818,6 +1818,46 @@ async def test_package_merge_error(
|
||||||
assert error_records == snapshot
|
assert error_records == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"error",
|
||||||
|
[
|
||||||
|
FileNotFoundError("No such file or directory: b'liblibc.a'"),
|
||||||
|
ImportError(
|
||||||
|
("ModuleNotFoundError: No module named 'not_installed_something'"),
|
||||||
|
name="not_installed_something",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"config_dir",
|
||||||
|
["packages", "packages_include_dir_named"],
|
||||||
|
)
|
||||||
|
async def test_package_merge_exception(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
config_dir: str,
|
||||||
|
error: Exception,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test exception when merging packages."""
|
||||||
|
base_path = os.path.dirname(__file__)
|
||||||
|
hass.config.config_dir = os.path.join(
|
||||||
|
base_path, "fixtures", "core", "config", "package_exceptions", config_dir
|
||||||
|
)
|
||||||
|
with patch(
|
||||||
|
"homeassistant.config.async_get_integration_with_requirements",
|
||||||
|
side_effect=error,
|
||||||
|
):
|
||||||
|
await config_util.async_hass_config_yaml(hass)
|
||||||
|
|
||||||
|
error_records = [
|
||||||
|
record.message.replace(base_path, "<BASE_PATH>")
|
||||||
|
for record in caplog.get_records("call")
|
||||||
|
if record.levelno == logging.ERROR
|
||||||
|
]
|
||||||
|
assert error_records == snapshot
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"config_dir",
|
"config_dir",
|
||||||
[
|
[
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue