From e630476f9f14669be48b3fea1ee532914eca3e24 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 11 May 2015 22:23:20 -0700 Subject: [PATCH 1/3] Allow platforms to specify dependencies --- homeassistant/bootstrap.py | 31 +++++++++++++++++++++++ homeassistant/helpers/entity_component.py | 16 +++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 2544ff5fa79..b650469f2a6 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -30,6 +30,8 @@ _LOGGER = logging.getLogger(__name__) ATTR_COMPONENT = "component" +PLATFORM_FORMAT = '{}.{}' + def setup_component(hass, domain, config=None): """ Setup a component and all its dependencies. """ @@ -95,6 +97,35 @@ def _setup_component(hass, domain, config): return False +def prepare_setup_platform(hass, config, domain, platform_name): + """ Loads a platform and makes sure dependencies are setup. """ + _ensure_loader_prepared(hass) + + platform_path = PLATFORM_FORMAT.format(domain, platform_name) + + platform = loader.get_component(platform_path) + + # Not found + if platform is None: + _LOGGER.error('Unable to find platform %s', platform_path) + return None + + # Already loaded or no dependencies + elif (platform_path in hass.config.components or + not hasattr(platform, 'DEPENDENCIES')): + return platform + + # Load dependencies + for component in platform.DEPENDENCIES: + if not setup_component(hass, component, config): + _LOGGER.error( + 'Unable to prepare setup for platform %s because not all ' + 'dependencies could be initialized', platform_path) + return None + + return platform + + # pylint: disable=too-many-branches, too-many-statements def from_config_dict(config, hass=None): """ diff --git a/homeassistant/helpers/entity_component.py b/homeassistant/helpers/entity_component.py index 1723091d5c2..b7a12233170 100644 --- a/homeassistant/helpers/entity_component.py +++ b/homeassistant/helpers/entity_component.py @@ -4,7 +4,7 @@ homeassistant.helpers.entity_component Provides helpers for components that manage entities. """ -from homeassistant.loader import get_component +from homeassistant.bootstrap import prepare_setup_platform from homeassistant.helpers import ( generate_entity_id, config_per_platform, extract_entity_ids) from homeassistant.components import group, discovery @@ -45,7 +45,7 @@ class EntityComponent(object): for p_type, p_config in \ config_per_platform(config, self.domain, self.logger): - self._setup_platform(p_type, p_config) + self._setup_platform(config, p_type, p_config) if self.discovery_platforms: discovery.listen(self.hass, self.discovery_platforms.keys(), @@ -115,18 +115,20 @@ class EntityComponent(object): self._update_entity_states, second=range(0, 60, self.scan_interval)) - def _setup_platform(self, platform_type, config, discovery_info=None): + def _setup_platform(self, config, platform_type, platform_config, + discovery_info=None): """ Tries to setup a platform for this component. """ - platform_name = '{}.{}'.format(self.domain, platform_type) - platform = get_component(platform_name) + platform = prepare_setup_platform( + self.hass, config, self.domain, platform_type) if platform is None: - self.logger.error('Unable to find platform %s', platform_type) return + platform_name = '{}.{}'.format(self.domain, platform_type) + try: platform.setup_platform( - self.hass, config, self.add_entities, discovery_info) + self.hass, platform_config, self.add_entities, discovery_info) self.hass.config.components.append(platform_name) From 4eeaa16f16a5727d8215b993d96957ffb13011fd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 11 May 2015 22:23:38 -0700 Subject: [PATCH 2/3] Convert some double to single quotes. --- homeassistant/bootstrap.py | 20 ++++++++++---------- homeassistant/helpers/entity_component.py | 11 ++++++----- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index b650469f2a6..8731e09a1e0 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -28,7 +28,7 @@ from homeassistant.const import ( _LOGGER = logging.getLogger(__name__) -ATTR_COMPONENT = "component" +ATTR_COMPONENT = 'component' PLATFORM_FORMAT = '{}.{}' @@ -69,7 +69,7 @@ def _setup_component(hass, domain, config): if missing_deps: _LOGGER.error( - "Not initializing %s because not all dependencies loaded: %s", + 'Not initializing %s because not all dependencies loaded: %s', domain, ", ".join(missing_deps)) return False @@ -89,10 +89,10 @@ def _setup_component(hass, domain, config): return True else: - _LOGGER.error("component %s failed to initialize", domain) + _LOGGER.error('component %s failed to initialize', domain) except Exception: # pylint: disable=broad-except - _LOGGER.exception("Error during setup of component %s", domain) + _LOGGER.exception('Error during setup of component %s', domain) return False @@ -153,12 +153,12 @@ def from_config_dict(config, hass=None): if ' ' not in key and key != homeassistant.DOMAIN) if not core_components.setup(hass, config): - _LOGGER.error("Home Assistant core failed to initialize. " - "Further initialization aborted.") + _LOGGER.error('Home Assistant core failed to initialize. ' + 'Further initialization aborted.') return hass - _LOGGER.info("Home Assistant core initialized") + _LOGGER.info('Home Assistant core initialized') # Setup the components for domain in loader.load_order_components(components): @@ -189,7 +189,7 @@ def enable_logging(hass): logging.basicConfig(level=logging.INFO) # Log errors to a file if we have write access to file or config dir - err_log_path = hass.config.path("home-assistant.log") + err_log_path = hass.config.path('home-assistant.log') err_path_exists = os.path.isfile(err_log_path) # Check if we can write to the error log if it exists or that @@ -208,7 +208,7 @@ def enable_logging(hass): else: _LOGGER.error( - "Unable to setup error log %s (access denied)", err_log_path) + 'Unable to setup error log %s (access denied)', err_log_path) def process_ha_core_config(hass, config): @@ -226,7 +226,7 @@ def process_ha_core_config(hass, config): hac.time_zone = time_zone date_util.set_default_time_zone(time_zone) else: - _LOGGER.error("Received invalid time zone %s", time_zone_str) + _LOGGER.error('Received invalid time zone %s', time_zone_str) for key, attr in ((CONF_LATITUDE, 'latitude'), (CONF_LONGITUDE, 'longitude'), diff --git a/homeassistant/helpers/entity_component.py b/homeassistant/helpers/entity_component.py index b7a12233170..6a0a2527e21 100644 --- a/homeassistant/helpers/entity_component.py +++ b/homeassistant/helpers/entity_component.py @@ -137,15 +137,16 @@ class EntityComponent(object): # Support old deprecated method for now - 3/1/2015 if hasattr(platform, 'get_devices'): self.logger.warning( - "Please upgrade %s to return new entities using " - "setup_platform. See %s/demo.py for an example.", + 'Please upgrade %s to return new entities using ' + 'setup_platform. See %s/demo.py for an example.', platform_name, self.domain) - self.add_entities(platform.get_devices(self.hass, config)) + self.add_entities( + platform.get_devices(self.hass, platform_config)) else: self.logger.exception( - "Error while setting up platform %s", platform_type) + 'Error while setting up platform %s', platform_type) except Exception: # pylint: disable=broad-except self.logger.exception( - "Error while setting up platform %s", platform_type) + 'Error while setting up platform %s', platform_type) From c523a0b5098f46bdd3de7a6c72289b579bd0d683 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 11 May 2015 22:29:53 -0700 Subject: [PATCH 3/3] Improve error message when prepare_setup_platform fails. --- homeassistant/bootstrap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 8731e09a1e0..e674e6e3ab6 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -119,8 +119,8 @@ def prepare_setup_platform(hass, config, domain, platform_name): for component in platform.DEPENDENCIES: if not setup_component(hass, component, config): _LOGGER.error( - 'Unable to prepare setup for platform %s because not all ' - 'dependencies could be initialized', platform_path) + 'Unable to prepare setup for platform %s because dependency ' + '%s could not be initialized', platform_path, component) return None return platform