Allow platforms to specify PLATFORM_SCHEMA

This commit is contained in:
Paulus Schoutsen 2016-04-02 20:10:57 -07:00
parent 4fba89b789
commit f6d584af09
5 changed files with 86 additions and 21 deletions

View file

@ -108,14 +108,33 @@ def _setup_component(hass, domain, config):
elif hasattr(component, 'PLATFORM_SCHEMA'):
platforms = []
for _, platform in config_per_platform(config, domain):
for p_name, p_config in config_per_platform(config, domain):
# Validate component specific platform schema
try:
platforms.append(component.PLATFORM_SCHEMA(platform))
p_validated = component.PLATFORM_SCHEMA(p_config)
except vol.MultipleInvalid as ex:
_LOGGER.error('Invalid platform config for [%s]: %s. %s',
domain, ex, platform)
domain, ex, p_config)
return False
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:
_LOGGER.error(
'Invalid platform config for [%s.%s]: %s. %s',
domain, p_name, ex, p_config)
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)

View file

@ -2,7 +2,7 @@
import voluptuous as vol
from homeassistant.const import (
CONF_PLATFORM, TEMP_CELCIUS, TEMP_FAHRENHEIT)
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELCIUS, TEMP_FAHRENHEIT)
from homeassistant.helpers.entity import valid_entity_id
import homeassistant.util.dt as dt_util
@ -10,6 +10,7 @@ import homeassistant.util.dt as dt_util
PLATFORM_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): str,
CONF_SCAN_INTERVAL: vol.All(vol.Coerce(int), vol.Range(min=1)),
}, extra=vol.ALLOW_EXTRA)
byte = vol.All(vol.Coerce(int), vol.Range(min=0, max=255))

View file

@ -79,24 +79,22 @@ class EntityComponent(object):
platform = prepare_setup_platform(
self.hass, self.config, self.domain, platform_type)
if platform is None:
return
try:
# Config > Platform > Component
scan_interval = platform_config.get(
CONF_SCAN_INTERVAL,
getattr(platform, 'SCAN_INTERVAL', self.scan_interval))
try:
platform.setup_platform(
self.hass, platform_config,
EntityPlatform(self, scan_interval).add_entities,
discovery_info)
platform_name = '{}.{}'.format(self.domain, platform_type)
self.hass.config.components.append(platform_name)
self.hass.config.components.append(
'{}.{}'.format(self.domain, platform_type))
except Exception: # pylint: disable=broad-except
self.logger.exception(
'Error while setting up platform %s', platform_type)
return
def add_entity(self, entity):
"""Add entity to component."""

View file

@ -143,12 +143,12 @@ class MockHTTP(object):
class MockModule(object):
"""Representation of a fake module."""
def __init__(self, domain=None, dependencies=[], setup=None,
requirements=[], config_schema=None, platform_schema=None):
def __init__(self, domain=None, dependencies=None, setup=None,
requirements=None, config_schema=None, platform_schema=None):
"""Initialize the mock module."""
self.DOMAIN = domain
self.DEPENDENCIES = dependencies
self.REQUIREMENTS = requirements
self.DEPENDENCIES = dependencies or []
self.REQUIREMENTS = requirements or []
if config_schema is not None:
self.CONFIG_SCHEMA = config_schema
@ -166,11 +166,15 @@ class MockModule(object):
class MockPlatform(object):
"""Provide a fake platform."""
def __init__(self, setup_platform=None, dependencies=[]):
def __init__(self, setup_platform=None, dependencies=None,
platform_schema=None):
"""Initialize the platform."""
self.DEPENDENCIES = dependencies
self.DEPENDENCIES = dependencies or []
self._setup_platform = setup_platform
if platform_schema is not None:
self.PLATFORM_SCHEMA = platform_schema
def setup_platform(self, hass, config, add_devices, discovery_info=None):
"""Setup the platform."""
if self._setup_platform is not None:

View file

@ -165,11 +165,14 @@ class TestBootstrap:
"""Test validating platform configuration."""
platform_schema = PLATFORM_SCHEMA.extend({
'hello': str,
}, required=True)
})
loader.set_component(
'platform_conf',
MockModule('platform_conf', platform_schema=platform_schema))
loader.set_component(
'platform_conf.whatever', MockPlatform('whatever'))
assert not bootstrap._setup_component(self.hass, 'platform_conf', {
'platform_conf': None
})
@ -196,6 +199,13 @@ class TestBootstrap:
}
})
assert not bootstrap._setup_component(self.hass, 'platform_conf', {
'platform_conf': {
'platform': 'not_existing',
'hello': 'world',
}
})
assert bootstrap._setup_component(self.hass, 'platform_conf', {
'platform_conf': {
'platform': 'whatever',
@ -318,7 +328,7 @@ class TestBootstrap:
loader.set_component('switch.platform_a', MockPlatform('comp_b',
['comp_a']))
assert bootstrap.setup_component(self.hass, 'switch', {
bootstrap.setup_component(self.hass, 'switch', {
'comp_a': {
'valid': True
},
@ -327,3 +337,36 @@ class TestBootstrap:
}
})
assert 'comp_a' in self.hass.config.components
def test_platform_specific_config_validation(self):
"""Test platform that specifies config."""
platform_schema = PLATFORM_SCHEMA.extend({
'valid': True,
}, extra=vol.PREVENT_EXTRA)
loader.set_component(
'switch.platform_a',
MockPlatform('comp_b', platform_schema=platform_schema))
assert not bootstrap.setup_component(self.hass, 'switch', {
'switch': {
'platform': 'platform_a',
'invalid': True
}
})
assert not bootstrap.setup_component(self.hass, 'switch', {
'switch': {
'platform': 'platform_a',
'valid': True,
'invalid_extra': True,
}
})
assert bootstrap.setup_component(self.hass, 'switch', {
'switch': {
'platform': 'platform_a',
'valid': True
}
})