Allow installing component dependencies on the fly
This commit is contained in:
parent
90739c9df9
commit
b346f6e8ad
3 changed files with 57 additions and 11 deletions
|
@ -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')
|
||||||
|
|
7
homeassistant/util/environment.py
Normal file
7
homeassistant/util/environment.py
Normal 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
|
20
homeassistant/util/package.py
Normal file
20
homeassistant/util/package.py
Normal 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)
|
Loading…
Add table
Add a link
Reference in a new issue