Extract requirements (#12051)

This commit is contained in:
Paulus Schoutsen
2018-01-30 03:30:47 -08:00
committed by Pascal Vizeli
parent 71cb4df817
commit ec1c395f09
6 changed files with 160 additions and 131 deletions

View File

@@ -1,27 +1,24 @@
"""All methods needed to bootstrap a Home Assistant instance."""
import asyncio
import logging.handlers
import os
from timeit import default_timer as timer
from types import ModuleType
from typing import Optional, Dict
import homeassistant.config as conf_util
import homeassistant.core as core
import homeassistant.loader as loader
import homeassistant.util.package as pkg_util
from homeassistant import requirements, core, loader, config as conf_util
from homeassistant.config import async_notify_setup_error
from homeassistant.const import (
EVENT_COMPONENT_LOADED, PLATFORM_FORMAT, CONSTRAINT_FILE)
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
from homeassistant.exceptions import HomeAssistantError
from homeassistant.util.async import run_coroutine_threadsafe
_LOGGER = logging.getLogger(__name__)
ATTR_COMPONENT = 'component'
DATA_SETUP = 'setup_tasks'
DATA_PIP_LOCK = 'pip_lock'
DATA_DEPS_REQS = 'deps_reqs_processed'
SLOW_SETUP_WARNING = 10
@@ -60,43 +57,6 @@ def async_setup_component(hass: core.HomeAssistant, domain: str,
return (yield from task)
@asyncio.coroutine
def _async_process_requirements(hass: core.HomeAssistant, name: str,
requirements) -> bool:
"""Install the requirements for a component.
This method is a coroutine.
"""
if hass.config.skip_pip:
return True
pip_lock = hass.data.get(DATA_PIP_LOCK)
if pip_lock is None:
pip_lock = hass.data[DATA_PIP_LOCK] = asyncio.Lock(loop=hass.loop)
def pip_install(mod):
"""Install packages."""
if pkg_util.running_under_virtualenv():
return pkg_util.install_package(
mod, constraints=os.path.join(
os.path.dirname(__file__), CONSTRAINT_FILE))
return pkg_util.install_package(
mod, target=hass.config.path('deps'),
constraints=os.path.join(
os.path.dirname(__file__), CONSTRAINT_FILE))
with (yield from pip_lock):
for req in requirements:
ret = yield from hass.async_add_job(pip_install, req)
if not ret:
_LOGGER.error("Not initializing %s because could not install "
"dependency %s", name, req)
async_notify_setup_error(hass, name)
return False
return True
@asyncio.coroutine
def _async_process_dependencies(hass, config, name, dependencies):
"""Ensure all dependencies are set up."""
@@ -162,22 +122,11 @@ def _async_setup_component(hass: core.HomeAssistant,
log_error("Invalid config.")
return False
if not hass.config.skip_pip and hasattr(component, 'REQUIREMENTS'):
req_success = yield from _async_process_requirements(
hass, domain, component.REQUIREMENTS)
if not req_success:
log_error("Could not install all requirements.")
return False
if hasattr(component, 'DEPENDENCIES'):
dep_success = yield from _async_process_dependencies(
hass, config, domain, component.DEPENDENCIES)
if not dep_success:
log_error("Could not setup all dependencies.")
return False
async_comp = hasattr(component, 'async_setup')
try:
yield from _process_deps_reqs(hass, config, domain, component)
except HomeAssistantError as err:
log_error(str(err))
return False
start = timer()
_LOGGER.info("Setting up %s", domain)
@@ -192,7 +141,7 @@ def _async_setup_component(hass: core.HomeAssistant,
domain, SLOW_SETUP_WARNING)
try:
if async_comp:
if hasattr(component, 'async_setup'):
result = yield from component.async_setup(hass, processed_config)
else:
result = yield from hass.async_add_job(
@@ -256,21 +205,40 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
elif platform_path in hass.config.components:
return platform
# Load dependencies
if hasattr(platform, 'DEPENDENCIES'):
dep_success = yield from _async_process_dependencies(
hass, config, platform_path, platform.DEPENDENCIES)
if not dep_success:
log_error("Could not setup all dependencies.")
return None
if not hass.config.skip_pip and hasattr(platform, 'REQUIREMENTS'):
req_success = yield from _async_process_requirements(
hass, platform_path, platform.REQUIREMENTS)
if not req_success:
log_error("Could not install all requirements.")
return None
try:
yield from _process_deps_reqs(hass, config, platform_name, platform)
except HomeAssistantError as err:
log_error(str(err))
return None
return platform
@asyncio.coroutine
def _process_deps_reqs(hass, config, name, module):
"""Process all dependencies and requirements for a module.
Module is a Python module of either a component or platform.
"""
processed = hass.data.get(DATA_DEPS_REQS)
if processed is None:
processed = hass.data[DATA_DEPS_REQS] = set()
elif name in processed:
return
if hasattr(module, 'DEPENDENCIES'):
dep_success = yield from _async_process_dependencies(
hass, config, name, module.DEPENDENCIES)
if not dep_success:
raise HomeAssistantError("Could not setup all dependencies.")
if not hass.config.skip_pip and hasattr(module, 'REQUIREMENTS'):
req_success = yield from requirements.async_process_requirements(
hass, name, module.REQUIREMENTS)
if not req_success:
raise HomeAssistantError("Could not install all requirements.")
processed.add(name)