Esempio n. 1
0
def _setup_component(hass, domain, config):
    """Setup a component for Home Assistant."""
    # pylint: disable=too-many-return-statements,too-many-branches
    if domain in hass.config.components:
        return True

    with _SETUP_LOCK:
        # It might have been loaded while waiting for lock
        if domain in hass.config.components:
            return True

        if domain in _CURRENT_SETUP:
            _LOGGER.error('Attempt made to setup %s during setup of %s',
                          domain, domain)
            return False

        component = loader.get_component(domain)
        missing_deps = [
            dep for dep in getattr(component, 'DEPENDENCIES', [])
            if dep not in hass.config.components
        ]

        if missing_deps:
            _LOGGER.error(
                'Not initializing %s because not all dependencies loaded: %s',
                domain, ", ".join(missing_deps))
            return False

        if hasattr(component, 'CONFIG_SCHEMA'):
            try:
                config = component.CONFIG_SCHEMA(config)
            except vol.MultipleInvalid as ex:
                cv.log_exception(_LOGGER, ex, domain, config)
                return False

        elif hasattr(component, 'PLATFORM_SCHEMA'):
            platforms = []
            for p_name, p_config in config_per_platform(config, domain):
                # Validate component specific platform schema
                try:
                    p_validated = component.PLATFORM_SCHEMA(p_config)
                except vol.MultipleInvalid as ex:
                    cv.log_exception(_LOGGER, ex, domain, p_config)
                    return False

                # Not all platform components follow same pattern for platforms
                # So if p_name is None we are not going to validate platform
                # (the automation component is one of them)
                if p_name is None:
                    platforms.append(p_validated)
                    continue

                platform = prepare_setup_platform(hass, config, domain, p_name)

                if platform is None:
                    return False

                # Validate platform specific schema
                if hasattr(platform, 'PLATFORM_SCHEMA'):
                    try:
                        p_validated = platform.PLATFORM_SCHEMA(p_validated)
                    except vol.MultipleInvalid as ex:
                        cv.log_exception(_LOGGER, ex,
                                         '{}.{}'.format(domain,
                                                        p_name), p_validated)
                        return False

                platforms.append(p_validated)

            # Create a copy of the configuration with all config for current
            # component removed and add validated config back in.
            filter_keys = extract_domain_configs(config, domain)
            config = {
                key: value
                for key, value in config.items() if key not in filter_keys
            }
            config[domain] = platforms

        if not _handle_requirements(hass, component, domain):
            return False

        _CURRENT_SETUP.append(domain)

        try:
            if not component.setup(hass, config):
                _LOGGER.error('component %s failed to initialize', domain)
                return False
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception('Error during setup of component %s', domain)
            return False
        finally:
            _CURRENT_SETUP.remove(domain)

        hass.config.components.append(component.DOMAIN)

        # Assumption: if a component does not depend on groups
        # it communicates with devices
        if group.DOMAIN not in getattr(component, 'DEPENDENCIES', []):
            hass.pool.add_worker()

        hass.bus.fire(EVENT_COMPONENT_LOADED,
                      {ATTR_COMPONENT: component.DOMAIN})

        return True
def _setup_component(hass, domain, config):
    """Setup a component for Home Assistant."""
    # pylint: disable=too-many-return-statements,too-many-branches
    if domain in hass.config.components:
        return True

    with _SETUP_LOCK:
        # It might have been loaded while waiting for lock
        if domain in hass.config.components:
            return True

        if domain in _CURRENT_SETUP:
            _LOGGER.error('Attempt made to setup %s during setup of %s',
                          domain, domain)
            return False

        component = loader.get_component(domain)
        missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
                        if dep not in hass.config.components]

        if missing_deps:
            _LOGGER.error(
                'Not initializing %s because not all dependencies loaded: %s',
                domain, ", ".join(missing_deps))
            return False

        if hasattr(component, 'CONFIG_SCHEMA'):
            try:
                config = component.CONFIG_SCHEMA(config)
            except vol.MultipleInvalid as ex:
                cv.log_exception(_LOGGER, ex, domain, config)
                return False

        elif hasattr(component, 'PLATFORM_SCHEMA'):
            platforms = []
            for p_name, p_config in config_per_platform(config, domain):
                # Validate component specific platform schema
                try:
                    p_validated = component.PLATFORM_SCHEMA(p_config)
                except vol.MultipleInvalid as ex:
                    cv.log_exception(_LOGGER, ex, domain, p_config)
                    return False

                # Not all platform components follow same pattern for platforms
                # So if p_name is None we are not going to validate platform
                # (the automation component is one of them)
                if p_name is None:
                    platforms.append(p_validated)
                    continue

                platform = prepare_setup_platform(hass, config, domain,
                                                  p_name)

                if platform is None:
                    return False

                # Validate platform specific schema
                if hasattr(platform, 'PLATFORM_SCHEMA'):
                    try:
                        p_validated = platform.PLATFORM_SCHEMA(p_validated)
                    except vol.MultipleInvalid as ex:
                        cv.log_exception(_LOGGER, ex, '{}.{}'
                                         .format(domain, p_name), p_validated)
                        return False

                platforms.append(p_validated)

            # Create a copy of the configuration with all config for current
            # component removed and add validated config back in.
            filter_keys = extract_domain_configs(config, domain)
            config = {key: value for key, value in config.items()
                      if key not in filter_keys}
            config[domain] = platforms

        if not _handle_requirements(hass, component, domain):
            return False

        _CURRENT_SETUP.append(domain)

        try:
            if not component.setup(hass, config):
                _LOGGER.error('component %s failed to initialize', domain)
                return False
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception('Error during setup of component %s', domain)
            return False
        finally:
            _CURRENT_SETUP.remove(domain)

        hass.config.components.append(component.DOMAIN)

        # Assumption: if a component does not depend on groups
        # it communicates with devices
        if group.DOMAIN not in getattr(component, 'DEPENDENCIES', []):
            hass.pool.add_worker()

        hass.bus.fire(
            EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN})

        return True
Esempio n. 3
0
def from_config_dict(config,
                     hass=None,
                     config_dir=None,
                     enable_log=True,
                     verbose=False,
                     skip_pip=False,
                     log_rotate_days=None):
    """Try to configure Home Assistant from a config dict.

    Dynamically loads required components and its dependencies.
    """
    if hass is None:
        hass = core.HomeAssistant()
        if config_dir is not None:
            config_dir = os.path.abspath(config_dir)
            hass.config.config_dir = config_dir
            _mount_local_lib_path(config_dir)

    core_config = config.get(core.DOMAIN, {})

    try:
        conf_util.process_ha_core_config(hass, core_config)
    except vol.Invalid as ex:
        cv.log_exception(_LOGGER, ex, 'homeassistant', core_config)
        return None

    conf_util.process_ha_config_upgrade(hass)

    if enable_log:
        enable_logging(hass, verbose, log_rotate_days)

    hass.config.skip_pip = skip_pip
    if skip_pip:
        _LOGGER.warning('Skipping pip installation of required modules. '
                        'This may cause issues.')

    _ensure_loader_prepared(hass)

    # Make a copy because we are mutating it.
    # Convert it to defaultdict so components can always have config dict
    # Convert values to dictionaries if they are None
    config = defaultdict(dict,
                         {key: value or {}
                          for key, value in config.items()})

    # Filter out the repeating and common config section [homeassistant]
    components = set(
        key.split(' ')[0] for key in config.keys() if key != core.DOMAIN)

    if not core_components.setup(hass, config):
        _LOGGER.error('Home Assistant core failed to initialize. '
                      'Further initialization aborted.')
        return hass

    persistent_notification.setup(hass, config)

    _LOGGER.info('Home Assistant core initialized')

    # Give event decorators access to HASS
    event_decorators.HASS = hass
    service.HASS = hass

    # Setup the components
    for domain in loader.load_order_components(components):
        _setup_component(hass, domain, config)

    return hass
def from_config_dict(config, hass=None, config_dir=None, enable_log=True,
                     verbose=False, daemon=False, skip_pip=False,
                     log_rotate_days=None):
    """Try to configure Home Assistant from a config dict.

    Dynamically loads required components and its dependencies.
    """
    if hass is None:
        hass = core.HomeAssistant()
        if config_dir is not None:
            config_dir = os.path.abspath(config_dir)
            hass.config.config_dir = config_dir
            mount_local_lib_path(config_dir)

    core_config = config.get(core.DOMAIN, {})

    try:
        process_ha_core_config(hass, config_util.CORE_CONFIG_SCHEMA(
            core_config))
    except vol.MultipleInvalid as ex:
        cv.log_exception(_LOGGER, ex, 'homeassistant', core_config)
        return None

    process_ha_config_upgrade(hass)

    if enable_log:
        enable_logging(hass, verbose, daemon, log_rotate_days)

    hass.config.skip_pip = skip_pip
    if skip_pip:
        _LOGGER.warning('Skipping pip installation of required modules. '
                        'This may cause issues.')

    _ensure_loader_prepared(hass)

    # Make a copy because we are mutating it.
    # Convert it to defaultdict so components can always have config dict
    # Convert values to dictionaries if they are None
    config = defaultdict(
        dict, {key: value or {} for key, value in config.items()})

    # Filter out the repeating and common config section [homeassistant]
    components = set(key.split(' ')[0] for key in config.keys()
                     if key != core.DOMAIN)

    if not core_components.setup(hass, config):
        _LOGGER.error('Home Assistant core failed to initialize. '
                      'Further initialization aborted.')

        return hass

    _LOGGER.info('Home Assistant core initialized')

    # Give event decorators access to HASS
    event_decorators.HASS = hass
    service.HASS = hass

    # Setup the components
    for domain in loader.load_order_components(components):
        _setup_component(hass, domain, config)

    return hass