Пример #1
0
async def async_process_component_config(
    hass: HomeAssistant, config: Dict, integration: Integration
) -> Optional[Dict]:
    """Check component configuration and return processed configuration.

    Returns None on error.

    This method must be run in the event loop.
    """
    domain = integration.domain
    try:
        component = integration.get_component()
    except ImportError as ex:
        _LOGGER.error("Unable to import %s: %s", domain, ex)
        return None

    # Check if the integration has a custom config validator
    config_validator = None
    try:
        config_validator = integration.get_platform("config")
    except ImportError:
        pass
    if config_validator is not None and hasattr(
        config_validator, "async_validate_config"
    ):
        try:
            return await config_validator.async_validate_config(  # type: ignore
                hass, config
            )
        except (vol.Invalid, HomeAssistantError) as ex:
            async_log_exception(ex, domain, config, hass)
            return None

    # No custom config validator, proceed with schema validation
    if hasattr(component, "CONFIG_SCHEMA"):
        try:
            return component.CONFIG_SCHEMA(config)  # type: ignore
        except vol.Invalid as ex:
            async_log_exception(ex, domain, config, hass)
            return None

    component_platform_schema = getattr(
        component, "PLATFORM_SCHEMA_BASE", getattr(component, "PLATFORM_SCHEMA", None)
    )

    if component_platform_schema is None:
        return config

    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.Invalid as ex:
            async_log_exception(ex, domain, p_config, hass)
            continue

        # 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

        try:
            p_integration = await async_get_integration_with_requirements(hass, p_name)
        except (RequirementsNotFound, IntegrationNotFound) as ex:
            _LOGGER.error("Platform error: %s - %s", domain, ex)
            continue

        try:
            platform = p_integration.get_platform(domain)
        except ImportError:
            _LOGGER.exception("Platform error: %s", domain)
            continue

        # Validate platform specific schema
        if hasattr(platform, "PLATFORM_SCHEMA"):
            # pylint: disable=no-member
            try:
                p_validated = platform.PLATFORM_SCHEMA(  # type: ignore
                    p_config
                )
            except vol.Invalid as ex:
                async_log_exception(ex, f"{domain}.{p_name}", p_config, hass)
                continue

        platforms.append(p_validated)

    # Create a copy of the configuration with all config for current
    # component removed and add validated config back in.
    config = config_without_domain(config, domain)
    config[domain] = platforms

    return config
Пример #2
0
async def async_process_component_config(
        hass: HomeAssistant, config: Dict, integration: Integration) \
            -> Optional[Dict]:
    """Check component configuration and return processed configuration.

    Returns None on error.

    This method must be run in the event loop.
    """
    domain = integration.domain
    try:
        component = integration.get_component()
    except ImportError as ex:
        _LOGGER.error("Unable to import %s: %s", domain, ex)
        return None

    if hasattr(component, 'CONFIG_SCHEMA'):
        try:
            return component.CONFIG_SCHEMA(config)  # type: ignore
        except vol.Invalid as ex:
            async_log_exception(ex, domain, config, hass)
            return None

    component_platform_schema = getattr(
        component, 'PLATFORM_SCHEMA_BASE',
        getattr(component, 'PLATFORM_SCHEMA', None))

    if component_platform_schema is None:
        return config

    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.Invalid as ex:
            async_log_exception(ex, domain, p_config, hass)
            continue

        # 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

        try:
            p_integration = await async_get_integration(hass, p_name)
        except IntegrationNotFound:
            continue

        if (not hass.config.skip_pip and p_integration.requirements
                and not await async_process_requirements(
                    hass, p_integration.domain, p_integration.requirements)):
            continue

        try:
            platform = p_integration.get_platform(domain)
        except ImportError:
            continue

        # Validate platform specific schema
        if hasattr(platform, 'PLATFORM_SCHEMA'):
            # pylint: disable=no-member
            try:
                p_validated = platform.PLATFORM_SCHEMA(  # type: ignore
                    p_config)
            except vol.Invalid as ex:
                async_log_exception(ex, '{}.{}'.format(domain, p_name),
                                    p_config, hass)
                continue

        platforms.append(p_validated)

    # Create a copy of the configuration with all config for current
    # component removed and add validated config back in.
    config = config_without_domain(config, domain)
    config[domain] = platforms

    return config
Пример #3
0
async def async_process_component_config(  # noqa: C901
        hass: HomeAssistant, config: ConfigType,
        integration: Integration) -> ConfigType | None:
    """Check component configuration and return processed configuration.

    Returns None on error.

    This method must be run in the event loop.
    """
    domain = integration.domain
    try:
        component = integration.get_component()
    except LOAD_EXCEPTIONS as ex:
        _LOGGER.error("Unable to import %s: %s", domain, ex)
        return None

    # Check if the integration has a custom config validator
    config_validator = None
    try:
        config_validator = integration.get_platform("config")
    except ImportError as err:
        # Filter out import error of the config platform.
        # If the config platform contains bad imports, make sure
        # that still fails.
        if err.name != f"{integration.pkg_path}.config":
            _LOGGER.error("Error importing config platform %s: %s", domain,
                          err)
            return None

    if config_validator is not None and hasattr(config_validator,
                                                "async_validate_config"):
        try:
            return await config_validator.async_validate_config(  # type: ignore
                hass, config)
        except (vol.Invalid, HomeAssistantError) as ex:
            async_log_exception(ex, domain, config, hass,
                                integration.documentation)
            return None
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Unknown error calling %s config validator",
                              domain)
            return None

    # No custom config validator, proceed with schema validation
    if hasattr(component, "CONFIG_SCHEMA"):
        try:
            return component.CONFIG_SCHEMA(config)  # type: ignore
        except vol.Invalid as ex:
            async_log_exception(ex, domain, config, hass,
                                integration.documentation)
            return None
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Unknown error calling %s CONFIG_SCHEMA", domain)
            return None

    component_platform_schema = getattr(
        component, "PLATFORM_SCHEMA_BASE",
        getattr(component, "PLATFORM_SCHEMA", None))

    if component_platform_schema is None:
        return config

    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.Invalid as ex:
            async_log_exception(ex, domain, p_config, hass,
                                integration.documentation)
            continue
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception(
                "Unknown error validating %s platform config with %s component platform schema",
                p_name,
                domain,
            )
            continue

        # 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

        try:
            p_integration = await async_get_integration_with_requirements(
                hass, p_name)
        except (RequirementsNotFound, IntegrationNotFound) as ex:
            _LOGGER.error("Platform error: %s - %s", domain, ex)
            continue

        try:
            platform = p_integration.get_platform(domain)
        except LOAD_EXCEPTIONS:
            _LOGGER.exception("Platform error: %s", domain)
            continue

        # Validate platform specific schema
        if hasattr(platform, "PLATFORM_SCHEMA"):
            try:
                p_validated = platform.PLATFORM_SCHEMA(
                    p_config)  # type: ignore
            except vol.Invalid as ex:
                async_log_exception(
                    ex,
                    f"{domain}.{p_name}",
                    p_config,
                    hass,
                    p_integration.documentation,
                )
                continue
            except Exception:  # pylint: disable=broad-except
                _LOGGER.exception(
                    "Unknown error validating config for %s platform for %s component with PLATFORM_SCHEMA",
                    p_name,
                    domain,
                )
                continue

        platforms.append(p_validated)

    # Create a copy of the configuration with all config for current
    # component removed and add validated config back in.
    config = config_without_domain(config, domain)
    config[domain] = platforms

    return config