Migrate packages and check config (#23082)
* Migrate packages and check config * Fix typing * Fix check config script
This commit is contained in:
parent
95662f82d4
commit
3368e30279
7 changed files with 113 additions and 99 deletions
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue