Don't swallow all errors when checking for config validator platform (#42058)

This commit is contained in:
Paulus Schoutsen 2020-10-19 17:09:57 +02:00 committed by GitHub
parent 8d4675713a
commit 440570244d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 13 deletions

View File

@ -60,7 +60,7 @@ async def async_setup(hass, config):
conf.get(CONF_PASSWORD), 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() await kafka.start()
@ -130,7 +130,7 @@ class KafkaManager:
self._hass.bus.async_listen(EVENT_STATE_CHANGED, self.write) self._hass.bus.async_listen(EVENT_STATE_CHANGED, self.write)
await self._producer.start() await self._producer.start()
async def shutdown(self): async def shutdown(self, _):
"""Shut the manager down.""" """Shut the manager down."""
await self._producer.stop() await self._producer.stop()

View File

@ -750,8 +750,14 @@ async def async_process_component_config(
config_validator = None config_validator = None
try: try:
config_validator = integration.get_platform("config") config_validator = integration.get_platform("config")
except ImportError: except ImportError as err:
pass # 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( if config_validator is not None and hasattr(
config_validator, "async_validate_config" config_validator, "async_validate_config"
): ):

View File

@ -419,11 +419,13 @@ class Integration:
cache = self.hass.data.setdefault(DATA_COMPONENTS, {}) cache = self.hass.data.setdefault(DATA_COMPONENTS, {})
full_name = f"{self.domain}.{platform_name}" full_name = f"{self.domain}.{platform_name}"
if full_name not in cache: if full_name not in cache:
cache[full_name] = importlib.import_module( cache[full_name] = self._import_platform(platform_name)
f"{self.pkg_path}.{platform_name}"
)
return cache[full_name] # type: ignore 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: def __repr__(self) -> str:
"""Text representation of class.""" """Text representation of class."""
return f"<Integration {self.domain}: {self.pkg_path}>" return f"<Integration {self.domain}: {self.pkg_path}>"

View File

@ -973,6 +973,14 @@ def mock_integration(hass, module):
hass, f"homeassistant.components.{module.DOMAIN}", None, module.mock_manifest() 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) _LOGGER.info("Adding mock integration: %s", module.DOMAIN)
hass.data.setdefault(loader.DATA_INTEGRATIONS, {})[module.DOMAIN] = integration hass.data.setdefault(loader.DATA_INTEGRATIONS, {})[module.DOMAIN] = integration
hass.data.setdefault(loader.DATA_COMPONENTS, {})[module.DOMAIN] = module hass.data.setdefault(loader.DATA_COMPONENTS, {})[module.DOMAIN] = module

View File

@ -14,17 +14,18 @@ from homeassistant.const import CONF_PLATFORM, CONF_SCAN_INTERVAL
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util 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() @pytest.fixture()
def mock_hub(hass): def mock_hub(hass):
"""Mock hub.""" """Mock hub."""
mock_integration(hass, MockModule(DOMAIN)) with patch("homeassistant.components.modbus.setup", return_value=True):
hub = mock.MagicMock() hub = mock.MagicMock()
hub.name = "hub" hub.name = "hub"
hass.data[DOMAIN] = {DEFAULT_HUB: hub} hass.data[DOMAIN] = {DEFAULT_HUB: hub}
return hub yield hub
class ReadResult: class ReadResult:

View File

@ -1064,6 +1064,30 @@ async def test_component_config_exceptions(hass, caplog):
in caplog.text 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( @pytest.mark.parametrize(
"domain, schema, expected", "domain, schema, expected",