Migrate packages and check config (#23082)

* Migrate packages and check config

* Fix typing

* Fix check config script
This commit is contained in:
Paulus Schoutsen 2019-04-14 07:23:01 -07:00 committed by GitHub
parent 95662f82d4
commit 3368e30279
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 113 additions and 99 deletions

View file

@ -25,7 +25,9 @@ from homeassistant.const import (
CONF_TYPE, CONF_ID)
from homeassistant.core import callback, DOMAIN as CONF_CORE, HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.loader import get_component, get_platform
from homeassistant.loader import (
Integration, async_get_integration, IntegrationNotFound
)
from homeassistant.util.yaml import load_yaml, SECRET_YAML
import homeassistant.helpers.config_validation as cv
from homeassistant.util import dt as date_util, location as loc_util
@ -308,11 +310,14 @@ async def async_hass_config_yaml(hass: HomeAssistant) -> Dict:
raise HomeAssistantError(
"Config file not found in: {}".format(hass.config.config_dir))
config = load_yaml_config_file(path)
core_config = config.get(CONF_CORE, {})
merge_packages_config(hass, config, core_config.get(CONF_PACKAGES, {}))
return config
return await hass.async_add_executor_job(_load_hass_yaml_config)
config = await hass.async_add_executor_job(_load_hass_yaml_config)
core_config = config.get(CONF_CORE, {})
await merge_packages_config(
hass, config, core_config.get(CONF_PACKAGES, {})
)
return config
def find_config_file(config_dir: Optional[str]) -> Optional[str]:
@ -634,8 +639,10 @@ def _recursive_merge(
return error
def merge_packages_config(hass: HomeAssistant, config: Dict, packages: Dict,
_log_pkg_error: Callable = _log_pkg_error) -> Dict:
async def merge_packages_config(hass: HomeAssistant, config: Dict,
packages: Dict,
_log_pkg_error: Callable = _log_pkg_error) \
-> Dict:
"""Merge packages into the top-level configuration. Mutate config."""
# pylint: disable=too-many-nested-blocks
PACKAGES_CONFIG_SCHEMA(packages)
@ -646,12 +653,20 @@ def merge_packages_config(hass: HomeAssistant, config: Dict, packages: Dict,
# If component name is given with a trailing description, remove it
# when looking for component
domain = comp_name.split(' ')[0]
component = get_component(hass, domain)
if component is None:
try:
integration = await async_get_integration(hass, domain)
except IntegrationNotFound:
_log_pkg_error(pack_name, comp_name, config, "does not exist")
continue
try:
component = integration.get_component()
except ImportError:
_log_pkg_error(pack_name, comp_name, config,
"unable to import")
continue
if hasattr(component, 'PLATFORM_SCHEMA'):
if not comp_conf:
continue # Ensure we dont add Falsy items to list
@ -701,72 +716,73 @@ def merge_packages_config(hass: HomeAssistant, config: Dict, packages: Dict,
return config
@callback
def async_process_component_config(
hass: HomeAssistant, config: Dict, domain: str) -> Optional[Dict]:
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.
"""
component = get_component(hass, domain)
domain = integration.domain
component = integration.get_component()
if hasattr(component, 'CONFIG_SCHEMA'):
try:
config = component.CONFIG_SCHEMA(config) # type: ignore
return component.CONFIG_SCHEMA(config) # type: ignore
except vol.Invalid as ex:
async_log_exception(ex, domain, config, hass)
return None
elif (hasattr(component, 'PLATFORM_SCHEMA') or
hasattr(component, 'PLATFORM_SCHEMA_BASE')):
platforms = []
for p_name, p_config in config_per_platform(config, domain):
# Validate component specific platform schema
try:
if hasattr(component, 'PLATFORM_SCHEMA_BASE'):
p_validated = \
component.PLATFORM_SCHEMA_BASE( # type: ignore
p_config)
else:
p_validated = component.PLATFORM_SCHEMA( # type: ignore
p_config)
except vol.Invalid as ex:
async_log_exception(ex, domain, p_config, hass)
continue
component_platform_schema = getattr(
component, 'PLATFORM_SCHEMA_BASE',
getattr(component, 'PLATFORM_SCHEMA', None))
# 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
if component_platform_schema is None:
return config
platform = get_platform(hass, domain, p_name)
if platform is None:
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 = []
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
# 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
try:
p_integration = await async_get_integration(hass, p_name)
platform = p_integration.get_platform(domain)
except (IntegrationNotFound, 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.
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
return config