diff --git a/homeassistant/components/apache_kafka/__init__.py b/homeassistant/components/apache_kafka/__init__.py index e0bcc04360b..a0bb5d20abe 100644 --- a/homeassistant/components/apache_kafka/__init__.py +++ b/homeassistant/components/apache_kafka/__init__.py @@ -60,7 +60,7 @@ async def async_setup(hass, config): conf.get(CONF_PASSWORD), ) - hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, kafka.shutdown()) + hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, kafka.shutdown) await kafka.start() @@ -130,7 +130,7 @@ class KafkaManager: self._hass.bus.async_listen(EVENT_STATE_CHANGED, self.write) await self._producer.start() - async def shutdown(self): + async def shutdown(self, _): """Shut the manager down.""" await self._producer.stop() diff --git a/homeassistant/config.py b/homeassistant/config.py index d0df72a810a..de0b1c3b1f8 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -750,8 +750,14 @@ async def async_process_component_config( config_validator = None try: config_validator = integration.get_platform("config") - except ImportError: - pass + except ImportError as err: + # Filter out import error of the config platform. + # If the config platform contains bad imports, make sure + # that still fails. + if err.name != f"{integration.pkg_path}.config": + _LOGGER.error("Error importing config platform %s: %s", domain, err) + return None + if config_validator is not None and hasattr( config_validator, "async_validate_config" ): diff --git a/homeassistant/loader.py b/homeassistant/loader.py index 4538e6f3669..cb701213fe7 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -419,11 +419,13 @@ class Integration: cache = self.hass.data.setdefault(DATA_COMPONENTS, {}) full_name = f"{self.domain}.{platform_name}" if full_name not in cache: - cache[full_name] = importlib.import_module( - f"{self.pkg_path}.{platform_name}" - ) + cache[full_name] = self._import_platform(platform_name) return cache[full_name] # type: ignore + def _import_platform(self, platform_name: str) -> ModuleType: + """Import the platform.""" + return importlib.import_module(f"{self.pkg_path}.{platform_name}") + def __repr__(self) -> str: """Text representation of class.""" return f"" diff --git a/tests/common.py b/tests/common.py index d516873786b..8f4ceb57546 100644 --- a/tests/common.py +++ b/tests/common.py @@ -973,6 +973,14 @@ def mock_integration(hass, module): hass, f"homeassistant.components.{module.DOMAIN}", None, module.mock_manifest() ) + def mock_import_platform(platform_name): + raise ImportError( + f"Mocked unable to import platform '{platform_name}'", + name=f"{integration.pkg_path}.{platform_name}", + ) + + integration._import_platform = mock_import_platform + _LOGGER.info("Adding mock integration: %s", module.DOMAIN) hass.data.setdefault(loader.DATA_INTEGRATIONS, {})[module.DOMAIN] = integration hass.data.setdefault(loader.DATA_COMPONENTS, {})[module.DOMAIN] = module diff --git a/tests/components/modbus/conftest.py b/tests/components/modbus/conftest.py index 226ce572b58..ca3e44dbe1d 100644 --- a/tests/components/modbus/conftest.py +++ b/tests/components/modbus/conftest.py @@ -14,17 +14,18 @@ from homeassistant.const import CONF_PLATFORM, CONF_SCAN_INTERVAL from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util -from tests.common import MockModule, async_fire_time_changed, mock_integration +from tests.async_mock import patch +from tests.common import async_fire_time_changed @pytest.fixture() def mock_hub(hass): """Mock hub.""" - mock_integration(hass, MockModule(DOMAIN)) - hub = mock.MagicMock() - hub.name = "hub" - hass.data[DOMAIN] = {DEFAULT_HUB: hub} - return hub + with patch("homeassistant.components.modbus.setup", return_value=True): + hub = mock.MagicMock() + hub.name = "hub" + hass.data[DOMAIN] = {DEFAULT_HUB: hub} + yield hub class ReadResult: diff --git a/tests/test_config.py b/tests/test_config.py index 368b11c1503..bfda156f2b7 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1064,6 +1064,30 @@ async def test_component_config_exceptions(hass, caplog): in caplog.text ) + # get_platform("config") raising + caplog.clear() + assert ( + await config_util.async_process_component_config( + hass, + {"test_domain": {}}, + integration=Mock( + pkg_path="homeassistant.components.test_domain", + domain="test_domain", + get_platform=Mock( + side_effect=ImportError( + "ModuleNotFoundError: No module named 'not_installed_something'", + name="not_installed_something", + ) + ), + ), + ) + is None + ) + assert ( + "Error importing config platform test_domain: ModuleNotFoundError: No module named 'not_installed_something'" + in caplog.text + ) + @pytest.mark.parametrize( "domain, schema, expected",