diff --git a/homeassistant/config.py b/homeassistant/config.py index 272ad59d1f4..2176c111867 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -84,11 +84,7 @@ SCRIPT_CONFIG_PATH = "scripts.yaml" SCENE_CONFIG_PATH = "scenes.yaml" LOAD_EXCEPTIONS = (ImportError, FileNotFoundError) -INTEGRATION_LOAD_EXCEPTIONS = ( - IntegrationNotFound, - RequirementsNotFound, - *LOAD_EXCEPTIONS, -) +INTEGRATION_LOAD_EXCEPTIONS = (IntegrationNotFound, RequirementsNotFound) 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: """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) message += ( @@ -897,7 +893,7 @@ async def merge_packages_config( hass: HomeAssistant, config: dict, packages: dict[str, Any], - _log_pkg_error: Callable = _log_pkg_error, + _log_pkg_error: Callable[[str, str, dict, str], None] = _log_pkg_error, ) -> dict: """Merge packages into the top-level configuration. Mutate config.""" PACKAGES_CONFIG_SCHEMA(packages) @@ -914,6 +910,14 @@ async def merge_packages_config( hass, domain ) 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: _log_pkg_error(pack_name, comp_name, config, str(ex)) continue @@ -949,7 +953,10 @@ async def merge_packages_config( if not isinstance(comp_conf, dict): _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 @@ -961,14 +968,17 @@ async def merge_packages_config( pack_name, comp_name, config, - "cannot be merged. Dict expected in main config.", + f"Integration {comp_name} cannot be merged. Dict expected in main config.", ) continue duplicate_key = _recursive_merge(conf=config[comp_name], package=comp_conf) if duplicate_key: _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 diff --git a/homeassistant/helpers/check_config.py b/homeassistant/helpers/check_config.py index 72bddedd5e4..ddc8dce9ec8 100644 --- a/homeassistant/helpers/check_config.py +++ b/homeassistant/helpers/check_config.py @@ -96,7 +96,7 @@ async def async_check_ha_config_file( # noqa: C901 package: str, component: str, config: ConfigType, message: str ) -> None: """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}" pack_config = core_config[CONF_PACKAGES].get(package, config) result.add_warning(message, domain, pack_config) diff --git a/tests/fixtures/core/config/package_exceptions/packages/configuration.yaml b/tests/fixtures/core/config/package_exceptions/packages/configuration.yaml new file mode 100644 index 00000000000..bf2a79c1307 --- /dev/null +++ b/tests/fixtures/core/config/package_exceptions/packages/configuration.yaml @@ -0,0 +1,4 @@ +homeassistant: + packages: + pack_1: + test_domain: diff --git a/tests/fixtures/core/config/package_exceptions/packages_include_dir_named/configuration.yaml b/tests/fixtures/core/config/package_exceptions/packages_include_dir_named/configuration.yaml new file mode 100644 index 00000000000..d3b52e4d49d --- /dev/null +++ b/tests/fixtures/core/config/package_exceptions/packages_include_dir_named/configuration.yaml @@ -0,0 +1,3 @@ +homeassistant: + # Load packages + packages: !include_dir_named integrations diff --git a/tests/fixtures/core/config/package_exceptions/packages_include_dir_named/integrations/unknown_integration.yaml b/tests/fixtures/core/config/package_exceptions/packages_include_dir_named/integrations/unknown_integration.yaml new file mode 100644 index 00000000000..66a70375f70 --- /dev/null +++ b/tests/fixtures/core/config/package_exceptions/packages_include_dir_named/integrations/unknown_integration.yaml @@ -0,0 +1 @@ +test_domain: diff --git a/tests/helpers/test_check_config.py b/tests/helpers/test_check_config.py index df1aa4f2d2c..589f71a791d 100644 --- a/tests/helpers/test_check_config.py +++ b/tests/helpers/test_check_config.py @@ -380,7 +380,7 @@ async def test_package_invalid(hass: HomeAssistant) -> None: 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." ), "homeassistant.packages.p1.group", diff --git a/tests/snapshots/test_config.ambr b/tests/snapshots/test_config.ambr index 19ff83f0d08..bc0dd8830e0 100644 --- a/tests/snapshots/test_config.ambr +++ b/tests/snapshots/test_config.ambr @@ -314,16 +314,36 @@ list([ 'Package pack_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See /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 /fixtures/core/config/package_errors/packages/configuration.yaml:13).', - "Package pack_4 setup failed. Integration adr_0007_3 has duplicate key 'host' (See /fixtures/core/config/package_errors/packages/configuration.yaml:20).", - "Package pack_5 setup failed. Integration unknown_integration Integration 'unknown_integration' not found. (See /fixtures/core/config/package_errors/packages/configuration.yaml:23).", + "Package pack_4 setup failed. Integration adr_0007_3 has duplicate key 'host'. (See /fixtures/core/config/package_errors/packages/configuration.yaml:20).", + "Package pack_5 setup failed. Integration 'unknown_integration' not found. (See /fixtures/core/config/package_errors/packages/configuration.yaml:23).", ]) # --- # name: test_package_merge_error[packages_include_dir_named] list([ 'Package adr_0007_1 setup failed. Integration adr_0007_1 cannot be merged. Dict expected in main config. (See /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 /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 /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 /fixtures/core/config/package_errors/packages_include_dir_named/integrations/unknown_integration.yaml:2).", + "Package adr_0007_3_2 setup failed. Integration adr_0007_3 has duplicate key 'host'. (See /fixtures/core/config/package_errors/packages_include_dir_named/integrations/adr_0007_3_2.yaml:1).", + "Package unknown_integration setup failed. Integration 'unknown_integration' not found. (See /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 /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 /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 /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 /fixtures/core/config/package_exceptions/packages_include_dir_named/integrations/unknown_integration.yaml:1).", ]) # --- # name: test_yaml_error[basic] diff --git a/tests/test_config.py b/tests/test_config.py index d39a1d4e907..dab8243bb39 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1818,6 +1818,46 @@ async def test_package_merge_error( 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, "") + for record in caplog.get_records("call") + if record.levelno == logging.ERROR + ] + assert error_records == snapshot + + @pytest.mark.parametrize( "config_dir", [