Allow installing component dependencies on the fly

This commit is contained in:
Paulus Schoutsen 2015-07-07 00:00:21 -07:00
parent 90739c9df9
commit b346f6e8ad
3 changed files with 57 additions and 11 deletions

View file

@ -14,8 +14,9 @@ import logging
from collections import defaultdict from collections import defaultdict
import homeassistant import homeassistant
import homeassistant.util as util
import homeassistant.util.dt as date_util import homeassistant.util.dt as date_util
import homeassistant.util.package as pkg_util
import homeassistant.util.location as loc_util
import homeassistant.config as config_util import homeassistant.config as config_util
import homeassistant.loader as loader import homeassistant.loader as loader
import homeassistant.components as core_components import homeassistant.components as core_components
@ -60,6 +61,17 @@ def setup_component(hass, domain, config=None):
return True return True
def _handle_requirements(component, name):
""" Installs requirements for component. """
if hasattr(component, 'REQUIREMENTS'):
for req in component.REQUIREMENTS:
if not pkg_util.install_package(req):
_LOGGER.error('Not initializing %s because could not install '
'dependency %s', name, req)
return False
return True
def _setup_component(hass, domain, config): def _setup_component(hass, domain, config):
""" Setup a component for Home Assistant. """ """ Setup a component for Home Assistant. """
component = loader.get_component(domain) component = loader.get_component(domain)
@ -74,6 +86,9 @@ def _setup_component(hass, domain, config):
return False return False
if not _handle_requirements(component, domain):
return False
try: try:
if component.setup(hass, config): if component.setup(hass, config):
hass.config.components.append(component.DOMAIN) hass.config.components.append(component.DOMAIN)
@ -109,18 +124,22 @@ def prepare_setup_platform(hass, config, domain, platform_name):
if platform is None: if platform is None:
return None return None
# Already loaded or no dependencies # Already loaded
elif (platform_path in hass.config.components or elif platform_path in hass.config.components:
not hasattr(platform, 'DEPENDENCIES')):
return platform return platform
# Load dependencies # Load dependencies
for component in platform.DEPENDENCIES: if hasattr(platform, 'DEPENDENCIES'):
if not setup_component(hass, component, config): for component in platform.DEPENDENCIES:
_LOGGER.error( if not setup_component(hass, component, config):
'Unable to prepare setup for platform %s because dependency ' _LOGGER.error(
'%s could not be initialized', platform_path, component) 'Unable to prepare setup for platform %s because '
return None 'dependency %s could not be initialized', platform_path,
component)
return None
if not _handle_requirements(platform, platform_path):
return None
return platform return platform
@ -276,7 +295,7 @@ def process_ha_core_config(hass, config):
_LOGGER.info('Auto detecting location and temperature unit') _LOGGER.info('Auto detecting location and temperature unit')
info = util.detect_location_info() info = loc_util.detect_location_info()
if info is None: if info is None:
_LOGGER.error('Could not detect location information') _LOGGER.error('Could not detect location information')

View file

@ -0,0 +1,7 @@
""" Environement helpers. """
import sys
def is_virtual():
""" Return if we run in a virtual environtment. """
return sys.base_prefix != sys.prefix

View file

@ -0,0 +1,20 @@
"""Helpers to install PyPi packages."""
import subprocess
from . import environment as env
# If we are not in a virtual environment, install in user space
INSTALL_USER = not env.is_virtual()
def install_package(package, upgrade=False, user=INSTALL_USER):
"""Install a package on PyPi. Accepts pip compatible package strings.
Return boolean if install successfull."""
# Not using 'import pip; pip.main([])' because it breaks the logger
args = ['python3', '-m', 'pip', 'install', '--disable-pip-version-check',
'--quiet', package]
if upgrade:
args.append('--upgrade')
if user:
args.append('--user')
return not subprocess.call(args)