Bootstrap / Component setup async (#6264)

* Bootstrap / Entiy setup async

* Cleanup add_job stuff / return task/future object

* Address paulus comments / part 1

* fix install pip

* Cleanup bootstrap / move config stuff to config.py

* Make demo async

* Further bootstrap improvement

* Address Martin's comments

* Fix initial tests

* Fix final tests

* Fix bug with prepare loader

* Remove no longer needed things

* Log error when invalid config

* More cleanup

* Cleanups platform events & fix lint

* Use a non blocking add_entities callback for platform

* Fix Autoamtion is setup befor entity is ready

* Better automation fix

* Address paulus comments

* Typo

* fix lint

* rename functions

* fix tests

* fix test

* change exceptions

* fix spell
This commit is contained in:
Pascal Vizeli 2017-03-01 05:33:19 +01:00 committed by Paulus Schoutsen
parent 383b0914b3
commit 41f558b181
109 changed files with 764 additions and 848 deletions

View file

@ -4,38 +4,41 @@ import logging
import logging.handlers
import os
import sys
from time import time
from collections import OrderedDict
from types import ModuleType
from typing import Any, Optional, Dict
import voluptuous as vol
from voluptuous.humanize import humanize_error
import homeassistant.components as core_components
from homeassistant.components import persistent_notification
import homeassistant.config as conf_util
from homeassistant.config import async_notify_setup_error
import homeassistant.core as core
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
import homeassistant.loader as loader
import homeassistant.util.package as pkg_util
from homeassistant.util.async import (
run_coroutine_threadsafe, run_callback_threadsafe)
from homeassistant.util.async import run_coroutine_threadsafe
from homeassistant.util.logging import AsyncHandler
from homeassistant.util.yaml import clear_secret_cache
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
event_decorators, service, config_per_platform, extract_domain_configs)
from homeassistant.helpers import event_decorators, service
from homeassistant.helpers.signal import async_register_signal_handling
_LOGGER = logging.getLogger(__name__)
ATTR_COMPONENT = 'component'
DATA_SETUP = 'setup_tasks'
DATA_PIP_LOCK = 'pip_lock'
ERROR_LOG_FILENAME = 'home-assistant.log'
DATA_PERSISTENT_ERRORS = 'bootstrap_persistent_errors'
HA_COMPONENT_URL = '[{}](https://home-assistant.io/components/{}/)'
FIRST_INIT_COMPONENT = set((
'recorder', 'mqtt', 'mqtt_eventstream', 'logger', 'introduction'))
def setup_component(hass: core.HomeAssistant, domain: str,
@ -52,49 +55,82 @@ def async_setup_component(hass: core.HomeAssistant, domain: str,
This method is a coroutine.
"""
if domain in hass.config.components:
_LOGGER.debug('Component %s already set up.', domain)
return True
setup_tasks = hass.data.get(DATA_SETUP)
if not loader.PREPARED:
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
if setup_tasks is not None and domain in setup_tasks:
return (yield from setup_tasks[domain])
if config is None:
config = {}
components = loader.load_order_component(domain)
if setup_tasks is None:
setup_tasks = hass.data[DATA_SETUP] = {}
# OrderedSet is empty if component or dependencies could not be resolved
if not components:
_async_persistent_notification(hass, domain, True)
return False
task = setup_tasks[domain] = hass.async_add_job(
_async_setup_component(hass, domain, config))
for component in components:
res = yield from _async_setup_component(hass, component, config)
if not res:
_LOGGER.error('Component %s failed to setup', component)
_async_persistent_notification(hass, component, True)
return False
return (yield from task)
@asyncio.coroutine
def _async_process_requirements(hass: core.HomeAssistant, name: str,
requirements) -> bool:
"""Install the requirements for a component.
This method is a coroutine.
"""
if hass.config.skip_pip:
return True
pip_lock = hass.data.get(DATA_PIP_LOCK)
if pip_lock is None:
pip_lock = hass.data[DATA_PIP_LOCK] = asyncio.Lock(loop=hass.loop)
def pip_install(mod):
"""Install packages."""
return pkg_util.install_package(mod, target=hass.config.path('deps'))
with (yield from pip_lock):
for req in requirements:
ret = yield from hass.loop.run_in_executor(None, pip_install, req)
if not ret:
_LOGGER.error('Not initializing %s because could not install '
'dependency %s', name, req)
async_notify_setup_error(hass, name)
return False
return True
def _handle_requirements(hass: core.HomeAssistant, component,
name: str) -> bool:
"""Install the requirements for a component.
@asyncio.coroutine
def _async_process_dependencies(hass, config, name, dependencies):
"""Ensure all dependencies are set up."""
blacklisted = [dep for dep in dependencies
if dep in loader.DEPENDENCY_BLACKLIST]
This method needs to run in an executor.
"""
if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'):
if blacklisted:
_LOGGER.error('Unable to setup dependencies of %s: '
'found blacklisted dependencies: %s',
name, ', '.join(blacklisted))
return False
tasks = [async_setup_component(hass, dep, config) for dep
in dependencies]
if not tasks:
return True
for req in component.REQUIREMENTS:
if not pkg_util.install_package(req, target=hass.config.path('deps')):
_LOGGER.error('Not initializing %s because could not install '
'dependency %s', name, req)
_async_persistent_notification(hass, name)
return False
results = yield from asyncio.gather(*tasks, loop=hass.loop)
failed = [dependencies[idx] for idx, res
in enumerate(results) if not res]
if failed:
_LOGGER.error('Unable to setup dependencies of %s. '
'Setup failed for dependencies: %s',
name, ', '.join(failed))
return False
return True
@ -104,172 +140,78 @@ def _async_setup_component(hass: core.HomeAssistant,
"""Setup a component for Home Assistant.
This method is a coroutine.
hass: Home Assistant instance.
domain: Domain of component to setup.
config: The Home Assistant configuration.
"""
# pylint: disable=too-many-return-statements
if domain in hass.config.components:
return True
def log_error(msg):
"""Log helper."""
_LOGGER.error('Setup failed for %s: %s', domain, msg)
async_notify_setup_error(hass, domain, True)
setup_lock = hass.data.get('setup_lock')
if setup_lock is None:
setup_lock = hass.data['setup_lock'] = asyncio.Lock(loop=hass.loop)
# Validate no circular dependencies
components = loader.load_order_component(domain)
setup_progress = hass.data.get('setup_progress')
if setup_progress is None:
setup_progress = hass.data['setup_progress'] = []
if domain in setup_progress:
_LOGGER.error('Attempt made to setup %s during setup of %s',
domain, domain)
_async_persistent_notification(hass, domain, True)
# OrderedSet is empty if component or dependencies could not be resolved
if not components:
log_error('Unable to resolve component or dependencies')
return False
try:
# Used to indicate to discovery that a setup is ongoing and allow it
# to wait till it is done.
did_lock = False
if not setup_lock.locked():
yield from setup_lock.acquire()
did_lock = True
setup_progress.append(domain)
config = yield from async_prepare_setup_component(hass, config, domain)
if config is None:
return False
component = loader.get_component(domain)
if component is None:
_async_persistent_notification(hass, domain)
return False
async_comp = hasattr(component, 'async_setup')
try:
_LOGGER.info("Setting up %s", domain)
if async_comp:
result = yield from component.async_setup(hass, config)
else:
result = yield from hass.loop.run_in_executor(
None, component.setup, hass, config)
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error during setup of component %s', domain)
_async_persistent_notification(hass, domain, True)
return False
if result is False:
_LOGGER.error('component %s failed to initialize', domain)
_async_persistent_notification(hass, domain, True)
return False
elif result is not True:
_LOGGER.error('component %s did not return boolean if setup '
'was successful. Disabling component.', domain)
_async_persistent_notification(hass, domain, True)
loader.set_component(domain, None)
return False
hass.config.components.add(component.DOMAIN)
hass.bus.async_fire(
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}
)
return True
finally:
setup_progress.remove(domain)
if did_lock:
setup_lock.release()
def prepare_setup_component(hass: core.HomeAssistant, config: dict,
domain: str):
"""Prepare setup of a component and return processed config."""
return run_coroutine_threadsafe(
async_prepare_setup_component(hass, config, domain), loop=hass.loop
).result()
@asyncio.coroutine
def async_prepare_setup_component(hass: core.HomeAssistant, config: dict,
domain: str):
"""Prepare setup of a component and return processed config.
This method is a coroutine.
"""
# pylint: disable=too-many-return-statements
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 None
processed_config = \
conf_util.async_process_component_config(hass, config, domain)
if hasattr(component, 'CONFIG_SCHEMA'):
try:
config = component.CONFIG_SCHEMA(config)
except vol.Invalid as ex:
async_log_exception(ex, domain, config, hass)
return None
if processed_config is None:
log_error('Invalid 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.Invalid as ex:
async_log_exception(ex, domain, config, hass)
continue
if not hass.config.skip_pip and hasattr(component, 'REQUIREMENTS'):
req_success = yield from _async_process_requirements(
hass, domain, component.REQUIREMENTS)
if not req_success:
log_error('Could not install all requirements.')
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
if hasattr(component, 'DEPENDENCIES'):
dep_success = yield from _async_process_dependencies(
hass, config, domain, component.DEPENDENCIES)
platform = yield from async_prepare_setup_platform(
hass, config, domain, p_name)
if not dep_success:
log_error('Could not setup all dependencies.')
return False
if platform is None:
continue
async_comp = hasattr(component, 'async_setup')
# Validate platform specific schema
if hasattr(platform, 'PLATFORM_SCHEMA'):
try:
# pylint: disable=no-member
p_validated = platform.PLATFORM_SCHEMA(p_validated)
except vol.Invalid as ex:
async_log_exception(ex, '{}.{}'.format(domain, p_name),
p_validated, hass)
continue
try:
_LOGGER.info("Setting up %s", domain)
if async_comp:
result = yield from component.async_setup(hass, processed_config)
else:
result = yield from hass.loop.run_in_executor(
None, component.setup, hass, processed_config)
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error during setup of component %s', domain)
async_notify_setup_error(hass, domain, True)
return False
platforms.append(p_validated)
if result is False:
log_error('Component failed to initialize.')
return False
elif result is not True:
log_error('Component did not return boolean if setup was successful. '
'Disabling component.')
loader.set_component(domain, None)
return False
# 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
hass.config.components.add(component.DOMAIN)
res = yield from hass.loop.run_in_executor(
None, _handle_requirements, hass, component, domain)
if not res:
return None
hass.bus.async_fire(
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}
)
return config
def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
platform_name: str) -> Optional[ModuleType]:
"""Load a platform and makes sure dependencies are setup."""
return run_coroutine_threadsafe(
async_prepare_setup_platform(hass, config, domain, platform_name),
loop=hass.loop
).result()
return True
@asyncio.coroutine
@ -280,17 +222,19 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
This method is a coroutine.
"""
if not loader.PREPARED:
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
def log_error(msg):
"""Log helper."""
_LOGGER.error('Unable to prepare setup for platform %s: %s',
platform_path, msg)
async_notify_setup_error(hass, platform_path)
platform = loader.get_platform(domain, platform_name)
# Not found
if platform is None:
_LOGGER.error('Unable to find platform %s', platform_path)
_async_persistent_notification(hass, platform_path)
log_error('Unable to find platform')
return None
# Already loaded
@ -298,25 +242,22 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
return platform
# Load dependencies
for component in getattr(platform, 'DEPENDENCIES', []):
if component in loader.DEPENDENCY_BLACKLIST:
raise HomeAssistantError(
'{} is not allowed to be a dependency.'.format(component))
if hasattr(platform, 'DEPENDENCIES'):
dep_success = yield from _async_process_dependencies(
hass, config, platform_path, platform.DEPENDENCIES)
res = yield from async_setup_component(hass, component, config)
if not res:
_LOGGER.error(
'Unable to prepare setup for platform %s because '
'dependency %s could not be initialized', platform_path,
component)
_async_persistent_notification(hass, platform_path, True)
if not dep_success:
log_error('Could not setup all dependencies.')
return False
if not hass.config.skip_pip and hasattr(platform, 'REQUIREMENTS'):
req_success = yield from _async_process_requirements(
hass, platform_path, platform.REQUIREMENTS)
if not req_success:
log_error('Could not install all requirements.')
return None
res = yield from hass.loop.run_in_executor(
None, _handle_requirements, hass, platform, platform_path)
if not res:
return None
return platform
@ -339,23 +280,14 @@ def from_config_dict(config: Dict[str, Any],
hass.config.config_dir = config_dir
mount_local_lib_path(config_dir)
@asyncio.coroutine
def _async_init_from_config_dict(future):
try:
re_hass = yield from async_from_config_dict(
config, hass, config_dir, enable_log, verbose, skip_pip,
log_rotate_days)
future.set_result(re_hass)
# pylint: disable=broad-except
except Exception as exc:
future.set_exception(exc)
# run task
future = asyncio.Future(loop=hass.loop)
hass.async_add_job(_async_init_from_config_dict(future))
hass.loop.run_until_complete(future)
hass = hass.loop.run_until_complete(
async_from_config_dict(
config, hass, config_dir, enable_log, verbose, skip_pip,
log_rotate_days)
)
return future.result()
return hass
@asyncio.coroutine
@ -372,19 +304,15 @@ def async_from_config_dict(config: Dict[str, Any],
Dynamically loads required components and its dependencies.
This method is a coroutine.
"""
start = time()
hass.async_track_tasks()
setup_lock = hass.data.get('setup_lock')
if setup_lock is None:
setup_lock = hass.data['setup_lock'] = asyncio.Lock(loop=hass.loop)
yield from setup_lock.acquire()
core_config = config.get(core.DOMAIN, {})
try:
yield from conf_util.async_process_ha_core_config(hass, core_config)
except vol.Invalid as ex:
async_log_exception(ex, 'homeassistant', core_config, hass)
conf_util.async_log_exception(ex, 'homeassistant', core_config, hass)
return None
yield from hass.loop.run_in_executor(
@ -433,20 +361,25 @@ def async_from_config_dict(config: Dict[str, Any],
event_decorators.HASS = hass
service.HASS = hass
# Setup the components
dependency_blacklist = loader.DEPENDENCY_BLACKLIST - set(components)
# stage 1
for component in components:
if component not in FIRST_INIT_COMPONENT:
continue
hass.async_add_job(async_setup_component(hass, component, config))
for domain in loader.load_order_components(components):
if domain in dependency_blacklist:
raise HomeAssistantError(
'{} is not allowed to be a dependency'.format(domain))
yield from hass.async_block_till_done()
yield from _async_setup_component(hass, domain, config)
setup_lock.release()
# stage 2
for component in components:
if component in FIRST_INIT_COMPONENT:
continue
hass.async_add_job(async_setup_component(hass, component, config))
yield from hass.async_stop_track_tasks()
stop = time()
_LOGGER.info('Home Assistant initialized in %ss', round(stop-start, 2))
async_register_signal_handling(hass)
return hass
@ -464,22 +397,13 @@ def from_config_file(config_path: str,
if hass is None:
hass = core.HomeAssistant()
@asyncio.coroutine
def _async_init_from_config_file(future):
try:
re_hass = yield from async_from_config_file(
config_path, hass, verbose, skip_pip, log_rotate_days)
future.set_result(re_hass)
# pylint: disable=broad-except
except Exception as exc:
future.set_exception(exc)
# run task
future = asyncio.Future(loop=hass.loop)
hass.loop.create_task(_async_init_from_config_file(future))
hass.loop.run_until_complete(future)
hass = hass.loop.run_until_complete(
async_from_config_file(
config_path, hass, verbose, skip_pip, log_rotate_days)
)
return future.result()
return hass
@asyncio.coroutine
@ -588,62 +512,6 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
'Unable to setup error log %s (access denied)', err_log_path)
def log_exception(ex, domain, config, hass):
"""Generate log exception for config validation."""
run_callback_threadsafe(
hass.loop, async_log_exception, ex, domain, config, hass).result()
@core.callback
def _async_persistent_notification(hass: core.HomeAssistant, component: str,
link: Optional[bool]=False):
"""Print a persistent notification.
This method must be run in the event loop.
"""
errors = hass.data.get(DATA_PERSISTENT_ERRORS)
if errors is None:
errors = hass.data[DATA_PERSISTENT_ERRORS] = {}
errors[component] = errors.get(component) or link
_lst = [HA_COMPONENT_URL.format(name.replace('_', '-'), name)
if link else name for name, link in errors.items()]
message = ('The following components and platforms could not be set up:\n'
'* ' + '\n* '.join(list(_lst)) + '\nPlease check your config')
persistent_notification.async_create(
hass, message, 'Invalid config', 'invalid_config')
@core.callback
def async_log_exception(ex, domain, config, hass):
"""Generate log exception for config validation.
This method must be run in the event loop.
"""
message = 'Invalid config for [{}]: '.format(domain)
if hass is not None:
_async_persistent_notification(hass, domain, True)
if 'extra keys not allowed' in ex.error_message:
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
.format(ex.path[-1], domain, domain,
'->'.join(str(m) for m in ex.path))
else:
message += '{}.'.format(humanize_error(config, ex))
domain_config = config.get(domain, config)
message += " (See {}, line {}). ".format(
getattr(domain_config, '__config_file__', '?'),
getattr(domain_config, '__line__', '?'))
if domain != 'homeassistant':
message += ('Please check the docs at '
'https://home-assistant.io/components/{}/'.format(domain))
_LOGGER.error(message)
def mount_local_lib_path(config_dir: str) -> str:
"""Add local library to Python Path.

View file

@ -55,7 +55,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
)
devices.append(device)
yield from async_add_devices(devices)
async_add_devices(devices)
@callback
def alarm_keypress_handler(service):

View file

@ -46,7 +46,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the MQTT platform."""
yield from async_add_devices([MqttAlarm(
async_add_devices([MqttAlarm(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_COMMAND_TOPIC),

View file

@ -28,8 +28,6 @@ import homeassistant.helpers.config_validation as cv
DOMAIN = 'automation'
ENTITY_ID_FORMAT = DOMAIN + '.{}'
DEPENDENCIES = ['group']
GROUP_NAME_ALL_AUTOMATIONS = 'all automations'
CONF_ALIAS = 'alias'
@ -226,7 +224,7 @@ class AutomationEntity(ToggleEntity):
"""Entity to show status of entity."""
def __init__(self, name, async_attach_triggers, cond_func, async_action,
hidden):
hidden, initial_state):
"""Initialize an automation entity."""
self._name = name
self._async_attach_triggers = async_attach_triggers
@ -236,6 +234,7 @@ class AutomationEntity(ToggleEntity):
self._enabled = False
self._last_triggered = None
self._hidden = hidden
self._initial_state = initial_state
@property
def name(self):
@ -264,6 +263,12 @@ class AutomationEntity(ToggleEntity):
"""Return True if entity is on."""
return self._enabled
@asyncio.coroutine
def async_added_to_hass(self) -> None:
"""Startup if initial_state."""
if self._initial_state:
yield from self.async_enable()
@asyncio.coroutine
def async_turn_on(self, **kwargs) -> None:
"""Turn the entity on and update the state."""
@ -322,7 +327,6 @@ def _async_process_config(hass, config, component):
This method is a coroutine.
"""
entities = []
tasks = []
for config_key in extract_domain_configs(config, DOMAIN):
conf = config[config_key]
@ -332,6 +336,7 @@ def _async_process_config(hass, config, component):
list_no)
hidden = config_block[CONF_HIDE_ENTITY]
initial_state = config_block[CONF_INITIAL_STATE]
action = _async_get_action(hass, config_block.get(CONF_ACTION, {}),
name)
@ -348,15 +353,14 @@ def _async_process_config(hass, config, component):
async_attach_triggers = partial(
_async_process_trigger, hass, config,
config_block.get(CONF_TRIGGER, []), name)
entity = AutomationEntity(name, async_attach_triggers, cond_func,
action, hidden)
if config_block[CONF_INITIAL_STATE]:
tasks.append(entity.async_enable())
config_block.get(CONF_TRIGGER, []), name
)
entity = AutomationEntity(
name, async_attach_triggers, cond_func, action, hidden,
initial_state)
entities.append(entity)
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
if entities:
yield from component.async_add_entities(entities)

View file

@ -37,7 +37,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
)
devices.append(device)
yield from async_add_devices(devices)
async_add_devices(devices)
class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):

View file

@ -57,7 +57,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
# generate sensor object
entity = FFmpegMotion(hass, manager, config)
yield from async_add_devices([entity])
async_add_devices([entity])
class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):

View file

@ -54,7 +54,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
# generate sensor object
entity = FFmpegNoise(hass, manager, config)
yield from async_add_devices([entity])
async_add_devices([entity])
class FFmpegNoise(FFmpegBinarySensor):

View file

@ -46,7 +46,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if value_template is not None:
value_template.hass = hass
yield from async_add_devices([MqttBinarySensor(
async_add_devices([MqttBinarySensor(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS),

View file

@ -66,7 +66,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
_LOGGER.error('No sensors added')
return False
yield from async_add_devices(sensors, True)
async_add_devices(sensors, True)
return True

View file

@ -52,7 +52,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
limit_type = config.get(CONF_TYPE)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
yield from async_add_devices(
async_add_devices(
[ThresholdSensor(hass, entity_id, name, threshold, limit_type,
device_class)], True)
return True

View file

@ -34,7 +34,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a FFmpeg Camera."""
if not hass.data[DATA_FFMPEG].async_run_test(config.get(CONF_INPUT)):
return
yield from async_add_devices([FFmpegCamera(hass, config)])
async_add_devices([FFmpegCamera(hass, config)])
class FFmpegCamera(Camera):

View file

@ -44,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a generic IP Camera."""
yield from async_add_devices([GenericCamera(hass, config)])
async_add_devices([GenericCamera(hass, config)])
class GenericCamera(Camera):

View file

@ -45,7 +45,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a MJPEG IP Camera."""
yield from async_add_devices([MjpegCamera(hass, config)])
async_add_devices([MjpegCamera(hass, config)])
def extract_image_from_mjpeg(stream):

View file

@ -153,7 +153,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
)
devices.append(device)
yield from async_add_devices(devices)
async_add_devices(devices)
@asyncio.coroutine

View file

@ -75,4 +75,4 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
_LOGGER.warning('No active cameras found')
return
yield from async_add_devices(cameras)
async_add_devices(cameras)

View file

@ -63,7 +63,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
min_cycle_duration = config.get(CONF_MIN_DUR)
tolerance = config.get(CONF_TOLERANCE)
yield from async_add_devices([GenericThermostat(
async_add_devices([GenericThermostat(
hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp,
target_temp, ac_mode, min_cycle_duration, tolerance)])

View file

@ -54,7 +54,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if value_template is not None:
value_template.hass = hass
yield from async_add_devices([MqttCover(
async_add_devices([MqttCover(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_COMMAND_TOPIC),

View file

@ -4,6 +4,7 @@ Sets up a demo environment that mimics interaction with devices.
For more details about this component, please refer to the documentation
https://home-assistant.io/components/demo/
"""
import asyncio
import time
import homeassistant.bootstrap as bootstrap
@ -34,7 +35,8 @@ COMPONENTS_WITH_DEMO_PLATFORM = [
]
def setup(hass, config):
@asyncio.coroutine
def async_setup(hass, config):
"""Setup a demo environment."""
group = loader.get_component('group')
configurator = loader.get_component('configurator')
@ -44,7 +46,7 @@ def setup(hass, config):
config.setdefault(DOMAIN, {})
if config[DOMAIN].get('hide_demo_state') != 1:
hass.states.set('a.Demo_Mode', 'Enabled')
hass.states.async_set('a.Demo_Mode', 'Enabled')
# Setup sun
if not hass.config.latitude:
@ -53,50 +55,71 @@ def setup(hass, config):
if not hass.config.longitude:
hass.config.longitude = 117.22743
bootstrap.setup_component(hass, 'sun')
tasks = [
bootstrap.async_setup_component(hass, 'sun')
]
# Setup demo platforms
demo_config = config.copy()
for component in COMPONENTS_WITH_DEMO_PLATFORM:
demo_config[component] = {CONF_PLATFORM: 'demo'}
bootstrap.setup_component(hass, component, demo_config)
tasks.append(
bootstrap.async_setup_component(hass, component, demo_config))
# Set up input select
tasks.append(bootstrap.async_setup_component(
hass, 'input_select',
{'input_select':
{'living_room_preset': {'options': ['Visitors',
'Visitors with kids',
'Home Alone']},
'who_cooks': {'icon': 'mdi:panda',
'initial': 'Anne Therese',
'name': 'Cook today',
'options': ['Paulus', 'Anne Therese']}}}))
# Set up input boolean
tasks.append(bootstrap.async_setup_component(
hass, 'input_boolean',
{'input_boolean': {'notify': {
'icon': 'mdi:car',
'initial': False,
'name': 'Notify Anne Therese is home'}}}))
# Set up input boolean
tasks.append(bootstrap.async_setup_component(
hass, 'input_slider',
{'input_slider': {
'noise_allowance': {'icon': 'mdi:bell-ring',
'min': 0,
'max': 10,
'name': 'Allowed Noise',
'unit_of_measurement': 'dB'}}}))
# Set up weblink
tasks.append(bootstrap.async_setup_component(
hass, 'weblink',
{'weblink': {'entities': [{'name': 'Router',
'url': 'http://192.168.1.1'}]}}))
results = yield from asyncio.gather(*tasks, loop=hass.loop)
if any(not result for result in results):
return False
# Setup example persistent notification
persistent_notification.create(
persistent_notification.async_create(
hass, 'This is an example of a persistent notification.',
title='Example Notification')
# Setup room groups
lights = sorted(hass.states.entity_ids('light'))
switches = sorted(hass.states.entity_ids('switch'))
media_players = sorted(hass.states.entity_ids('media_player'))
lights = sorted(hass.states.async_entity_ids('light'))
switches = sorted(hass.states.async_entity_ids('switch'))
media_players = sorted(hass.states.async_entity_ids('media_player'))
group.Group.create_group(hass, 'living room', [
lights[1], switches[0], 'input_select.living_room_preset',
'rollershutter.living_room_window', media_players[1],
'scene.romantic_lights'])
group.Group.create_group(hass, 'bedroom', [
lights[0], switches[1], media_players[0],
'input_slider.noise_allowance'])
group.Group.create_group(hass, 'kitchen', [
lights[2], 'rollershutter.kitchen_window', 'lock.kitchen_door'])
group.Group.create_group(hass, 'doors', [
'lock.front_door', 'lock.kitchen_door',
'garage_door.right_garage_door', 'garage_door.left_garage_door'])
group.Group.create_group(hass, 'automations', [
'input_select.who_cooks', 'input_boolean.notify', ])
group.Group.create_group(hass, 'people', [
'device_tracker.demo_anne_therese', 'device_tracker.demo_home_boy',
'device_tracker.demo_paulus'])
group.Group.create_group(hass, 'downstairs', [
'group.living_room', 'group.kitchen',
'scene.romantic_lights', 'rollershutter.kitchen_window',
'rollershutter.living_room_window', 'group.doors',
'thermostat.ecobee',
], view=True)
tasks2 = []
# Setup scripts
bootstrap.setup_component(
tasks2.append(bootstrap.async_setup_component(
hass, 'script',
{'script': {
'demo': {
@ -115,10 +138,10 @@ def setup(hass, config):
'service': 'light.turn_off',
'data': {ATTR_ENTITY_ID: lights[0]}
}]
}}})
}}}))
# Setup scenes
bootstrap.setup_component(
tasks2.append(bootstrap.async_setup_component(
hass, 'scene',
{'scene': [
{'name': 'Romantic lights',
@ -132,41 +155,37 @@ def setup(hass, config):
switches[0]: True,
switches[1]: False,
}},
]})
]}))
# Set up input select
bootstrap.setup_component(
hass, 'input_select',
{'input_select':
{'living_room_preset': {'options': ['Visitors',
'Visitors with kids',
'Home Alone']},
'who_cooks': {'icon': 'mdi:panda',
'initial': 'Anne Therese',
'name': 'Cook today',
'options': ['Paulus', 'Anne Therese']}}})
# Set up input boolean
bootstrap.setup_component(
hass, 'input_boolean',
{'input_boolean': {'notify': {'icon': 'mdi:car',
'initial': False,
'name': 'Notify Anne Therese is home'}}})
tasks2.append(group.Group.async_create_group(hass, 'living room', [
lights[1], switches[0], 'input_select.living_room_preset',
'rollershutter.living_room_window', media_players[1],
'scene.romantic_lights']))
tasks2.append(group.Group.async_create_group(hass, 'bedroom', [
lights[0], switches[1], media_players[0],
'input_slider.noise_allowance']))
tasks2.append(group.Group.async_create_group(hass, 'kitchen', [
lights[2], 'rollershutter.kitchen_window', 'lock.kitchen_door']))
tasks2.append(group.Group.async_create_group(hass, 'doors', [
'lock.front_door', 'lock.kitchen_door',
'garage_door.right_garage_door', 'garage_door.left_garage_door']))
tasks2.append(group.Group.async_create_group(hass, 'automations', [
'input_select.who_cooks', 'input_boolean.notify', ]))
tasks2.append(group.Group.async_create_group(hass, 'people', [
'device_tracker.demo_anne_therese', 'device_tracker.demo_home_boy',
'device_tracker.demo_paulus']))
tasks2.append(group.Group.async_create_group(hass, 'downstairs', [
'group.living_room', 'group.kitchen',
'scene.romantic_lights', 'rollershutter.kitchen_window',
'rollershutter.living_room_window', 'group.doors',
'thermostat.ecobee',
], view=True))
# Set up input boolean
bootstrap.setup_component(
hass, 'input_slider',
{'input_slider': {
'noise_allowance': {'icon': 'mdi:bell-ring',
'min': 0,
'max': 10,
'name': 'Allowed Noise',
'unit_of_measurement': 'dB'}}})
results = yield from asyncio.gather(*tasks2, loop=hass.loop)
if any(not result for result in results):
return False
# Set up weblink
bootstrap.setup_component(
hass, 'weblink',
{'weblink': {'entities': [{'name': 'Router',
'url': 'http://192.168.1.1'}]}})
# Setup configurator
configurator_ids = []
@ -184,14 +203,17 @@ def setup(hass, config):
else:
configurator.request_done(configurator_ids[0])
request_id = configurator.request_config(
hass, "Philips Hue", hue_configuration_callback,
description=("Press the button on the bridge to register Philips Hue "
"with Home Assistant."),
description_image="/static/images/config_philips_hue.jpg",
submit_caption="I have pressed the button"
)
def setup_configurator():
"""Setup configurator."""
request_id = configurator.request_config(
hass, "Philips Hue", hue_configuration_callback,
description=("Press the button on the bridge to register Philips "
"Hue with Home Assistant."),
description_image="/static/images/config_philips_hue.jpg",
submit_caption="I have pressed the button"
)
configurator_ids.append(request_id)
configurator_ids.append(request_id)
hass.async_add_job(setup_configurator)
return True

View file

@ -14,12 +14,11 @@ import aiohttp
import async_timeout
import voluptuous as vol
from homeassistant.bootstrap import (
async_prepare_setup_platform, async_log_exception)
from homeassistant.bootstrap import async_prepare_setup_platform
from homeassistant.core import callback
from homeassistant.components import group, zone
from homeassistant.components.discovery import SERVICE_NETGEAR
from homeassistant.config import load_yaml_config_file
from homeassistant.config import load_yaml_config_file, async_log_exception
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers import config_per_platform, discovery

View file

@ -78,7 +78,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup MQTT fan platform."""
yield from async_add_devices([MqttFan(
async_add_devices([MqttFan(
config.get(CONF_NAME),
{
key: config.get(key) for key in (

View file

@ -60,7 +60,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
camera[CONF_ENTITY_ID], api, attributes, camera.get(CONF_NAME)
))
yield from async_add_devices(entities)
async_add_devices(entities)
class MicrosoftFaceDetectEntity(ImageProcessingFaceEntity):

View file

@ -54,7 +54,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
camera.get(CONF_NAME)
))
yield from async_add_devices(entities)
async_add_devices(entities)
class ImageProcessingFaceEntity(ImageProcessingEntity):

View file

@ -66,7 +66,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
camera[CONF_ENTITY_ID], params, confidence, camera.get(CONF_NAME)
))
yield from async_add_devices(entities)
async_add_devices(entities)
class OpenAlprCloudEntity(ImageProcessingAlprEntity):

View file

@ -70,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
camera[CONF_ENTITY_ID], command, confidence, camera.get(CONF_NAME)
))
yield from async_add_devices(entities)
async_add_devices(entities)
class ImageProcessingAlprEntity(ImageProcessingEntity):

View file

@ -70,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
config.setdefault(
CONF_STATE_VALUE_TEMPLATE, config.get(CONF_VALUE_TEMPLATE))
yield from async_add_devices([MqttLight(
async_add_devices([MqttLight(
config.get(CONF_NAME),
{
key: config.get(key) for key in (

View file

@ -61,7 +61,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a MQTT JSON Light."""
yield from async_add_devices([MqttJson(
async_add_devices([MqttJson(
config.get(CONF_NAME),
{
key: config.get(key) for key in (

View file

@ -64,7 +64,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a MQTT Template light."""
yield from async_add_devices([MqttTemplate(
async_add_devices([MqttTemplate(
hass,
config.get(CONF_NAME),
config.get(CONF_EFFECT_LIST),

View file

@ -117,7 +117,7 @@ def devices_from_config(domain_config, hass=None):
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Rflink light platform."""
yield from async_add_devices(devices_from_config(config, hass))
async_add_devices(devices_from_config(config, hass))
# Add new (unconfigured) devices to user desired group
if config[CONF_NEW_DEVICES_GROUP]:
@ -136,7 +136,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
device_config = config[CONF_DEVICE_DEFAULTS]
device = entity_class(device_id, hass, **device_config)
yield from async_add_devices([device])
async_add_devices([device])
# Register entity to listen to incoming Rflink events
hass.data[DATA_ENTITY_LOOKUP][
@ -156,7 +156,10 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class RflinkLight(SwitchableRflinkDevice, Light):
"""Representation of a Rflink light."""
pass
@property
def entity_id(self):
"""Return entity id."""
return "light.{}".format(self.name)
class DimmableRflinkLight(SwitchableRflinkDevice, Light):
@ -164,6 +167,11 @@ class DimmableRflinkLight(SwitchableRflinkDevice, Light):
_brightness = 255
@property
def entity_id(self):
"""Return entity id."""
return "light.{}".format(self.name)
@asyncio.coroutine
def async_turn_on(self, **kwargs):
"""Turn the device on."""
@ -202,6 +210,11 @@ class HybridRflinkLight(SwitchableRflinkDevice, Light):
_brightness = 255
@property
def entity_id(self):
"""Return entity id."""
return "light.{}".format(self.name)
@asyncio.coroutine
def async_turn_on(self, **kwargs):
"""Turn the device on and set dim level."""

View file

@ -47,7 +47,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if value_template is not None:
value_template.hass = hass
yield from async_add_devices([MqttLock(
async_add_devices([MqttLock(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_COMMAND_TOPIC),

View file

@ -63,7 +63,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
_LOGGER.debug('dump_rawdata: '+avr.protocol.dump_rawdata)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, device.avr.close)
yield from async_add_devices([device])
async_add_devices([device])
class AnthemAVR(MediaPlayerDevice):

View file

@ -85,7 +85,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
return False
players = yield from lms.create_players()
yield from async_add_devices(players)
async_add_devices(players)
return True

View file

@ -63,7 +63,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
config[CONF_ATTRS]
)
yield from async_add_devices([player])
async_add_devices([player])
def validate_config(config):

View file

@ -18,7 +18,6 @@ from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
DOMAIN = 'scene'
DEPENDENCIES = ['group']
STATE = 'scening'
CONF_ENTITIES = "entities"

View file

@ -13,7 +13,6 @@ from homeassistant.const import (
from homeassistant.core import State
from homeassistant.helpers.state import async_reproduce_state
DEPENDENCIES = ['group']
STATE = 'scening'
CONF_ENTITIES = "entities"
@ -29,7 +28,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if not isinstance(scene_config, list):
scene_config = [scene_config]
yield from async_add_devices(HomeAssistantScene(
async_add_devices(HomeAssistantScene(
hass, _process_config(scene)) for scene in scene_config)
return True

View file

@ -25,7 +25,6 @@ from homeassistant.helpers.script import Script
DOMAIN = "script"
ENTITY_ID_FORMAT = DOMAIN + '.{}'
GROUP_NAME_ALL_SCRIPTS = 'all scripts'
DEPENDENCIES = ["group"]
CONF_SEQUENCE = "sequence"
@ -130,6 +129,7 @@ def async_setup(hass, config):
schema=SCRIPT_TURN_ONOFF_SCHEMA)
hass.services.async_register(DOMAIN, SERVICE_TOGGLE, toggle_service,
schema=SCRIPT_TURN_ONOFF_SCHEMA)
return True

View file

@ -61,7 +61,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, remove_logger)
yield from async_add_devices([entity])
async_add_devices([entity])
class APICount(Entity):

View file

@ -49,7 +49,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
else:
resolver = config.get(CONF_RESOLVER)
yield from async_add_devices([WanIpSensor(
async_add_devices([WanIpSensor(
hass, hostname, resolver, ipv6)], True)

View file

@ -103,7 +103,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
DerivativeDSMREntity('Hourly Gas Consumption', gas_obis),
]
yield from async_add_devices(devices)
async_add_devices(devices)
def update_entities_telegram(telegram):
"""Update entities with latests telegram & trigger state update."""

View file

@ -34,7 +34,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
hass.data[DATA_EVL])
devices.append(device)
yield from async_add_devices(devices)
async_add_devices(devices)
class EnvisalinkSensor(EnvisalinkDevice, Entity):

View file

@ -61,7 +61,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
sensor_type = config.get(CONF_TYPE)
round_digits = config.get(CONF_ROUND_DIGITS)
yield from async_add_devices(
async_add_devices(
[MinMaxSensor(hass, entity_ids, name, sensor_type, round_digits)],
True)
return True

View file

@ -33,7 +33,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Moon sensor."""
name = config.get(CONF_NAME)
yield from async_add_devices([MoonSensor(name)], True)
async_add_devices([MoonSensor(name)], True)
return True

View file

@ -38,7 +38,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if value_template is not None:
value_template.hass = hass
yield from async_add_devices([MqttSensor(
async_add_devices([MqttSensor(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_QOS),

View file

@ -59,7 +59,7 @@ MQTT_PAYLOAD = vol.Schema(vol.All(json.loads, vol.Schema({
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup MQTT Sensor."""
yield from async_add_devices([MQTTRoomSensor(
async_add_devices([MQTTRoomSensor(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_DEVICE_ID),

View file

@ -36,7 +36,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
minimum = config.get(CONF_MINIMUM)
maximum = config.get(CONF_MAXIMUM)
yield from async_add_devices([RandomSensor(name, minimum, maximum)], True)
async_add_devices([RandomSensor(name, minimum, maximum)], True)
return True

View file

@ -74,7 +74,7 @@ def devices_from_config(domain_config, hass=None):
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Rflink platform."""
yield from async_add_devices(devices_from_config(config, hass))
async_add_devices(devices_from_config(config, hass))
# Add new (unconfigured) devices to user desired group
if config[CONF_NEW_DEVICES_GROUP]:
@ -91,7 +91,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
rflinksensor = partial(RflinkSensor, device_id, hass)
device = rflinksensor(event[EVENT_KEY_SENSOR], event[EVENT_KEY_UNIT])
# Add device entity
yield from async_add_devices([device])
async_add_devices([device])
# Register entity to listen to incoming rflink events
hass.data[DATA_ENTITY_LOOKUP][
@ -122,6 +122,11 @@ class RflinkSensor(RflinkDevice):
"""Domain specific event handler."""
self._state = event['value']
@property
def entity_id(self):
"""Return entity id."""
return "sensor.{}".format(self.name)
@property
def unit_of_measurement(self):
"""Return measurement unit."""

View file

@ -50,7 +50,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
name = config.get(CONF_NAME)
sampling_size = config.get(CONF_SAMPLING_SIZE)
yield from async_add_devices(
async_add_devices(
[StatisticsSensor(hass, entity_id, name, sampling_size)], True)
return True

View file

@ -69,7 +69,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
_LOGGER.error("No sensors added")
return False
yield from async_add_devices(sensors, True)
async_add_devices(sensors, True)
return True

View file

@ -46,7 +46,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
for variable in config[CONF_DISPLAY_OPTIONS]:
devices.append(TimeDateSensor(variable))
yield from async_add_devices(devices, True)
async_add_devices(devices, True)
return True

View file

@ -35,7 +35,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
name = config.get(CONF_NAME)
time_zone = dt_util.get_time_zone(config.get(CONF_TIME_ZONE))
yield from async_add_devices([WorldClockSensor(time_zone, name)], True)
async_add_devices([WorldClockSensor(time_zone, name)], True)
return True

View file

@ -78,7 +78,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
dev = []
for sensor_type in config[CONF_MONITORED_CONDITIONS]:
dev.append(YrSensor(sensor_type))
yield from async_add_devices(dev)
async_add_devices(dev)
weather = YrData(hass, coordinates, dev)
# Update weather on the hour, spread seconds

View file

@ -74,7 +74,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if response is not None:
yield from response.release()
yield from async_add_devices(
async_add_devices(
HookSmartHome(
hass,
token,

View file

@ -43,7 +43,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if value_template is not None:
value_template.hass = hass
yield from async_add_devices([MqttSwitch(
async_add_devices([MqttSwitch(
config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC),
config.get(CONF_COMMAND_TOPIC),

View file

@ -72,7 +72,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
if req is not None:
yield from req.release()
yield from async_add_devices(
async_add_devices(
[RestSwitch(hass, name, resource, body_on, body_off,
is_on_template, timeout)])

View file

@ -52,7 +52,7 @@ def devices_from_config(domain_config, hass=None):
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Rflink platform."""
yield from async_add_devices(devices_from_config(config, hass))
async_add_devices(devices_from_config(config, hass))
class RflinkSwitch(SwitchableRflinkDevice, SwitchDevice):

View file

@ -70,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
_LOGGER.error("No switches added")
return False
yield from async_add_devices(switches, True)
async_add_devices(switches, True)
return True

View file

@ -276,7 +276,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
device = hass.data[DATA_ZWAVE_DICT].pop(
discovery_info[const.DISCOVERY_DEVICE])
if device:
yield from async_add_devices([device])
async_add_devices([device])
return True
else:
return False

View file

@ -10,23 +10,27 @@ import sys
from typing import Any, List, Tuple # NOQA
import voluptuous as vol
from voluptuous.humanize import humanize_error
from homeassistant.const import (
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_PACKAGES, CONF_UNIT_SYSTEM,
CONF_TIME_ZONE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
__version__, CONF_CUSTOMIZE, CONF_CUSTOMIZE_DOMAIN, CONF_CUSTOMIZE_GLOB)
from homeassistant.core import DOMAIN as CONF_CORE
from homeassistant.core import callback, DOMAIN as CONF_CORE
from homeassistant.exceptions import HomeAssistantError
from homeassistant.loader import get_component
from homeassistant.loader import get_component, get_platform
from homeassistant.util.yaml import load_yaml
import homeassistant.helpers.config_validation as cv
from homeassistant.util import dt as date_util, location as loc_util
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
from homeassistant.helpers.entity_values import EntityValues
from homeassistant.helpers import config_per_platform, extract_domain_configs
_LOGGER = logging.getLogger(__name__)
DATA_PERSISTENT_ERRORS = 'bootstrap_persistent_errors'
HA_COMPONENT_URL = '[{}](https://home-assistant.io/components/{}/)'
YAML_CONFIG_FILE = 'configuration.yaml'
VERSION_FILE = '.HA_VERSION'
CONFIG_DIR_NAME = '.homeassistant'
@ -274,6 +278,35 @@ def process_ha_config_upgrade(hass):
outp.write(__version__)
@callback
def async_log_exception(ex, domain, config, hass):
"""Generate log exception for config validation.
This method must be run in the event loop.
"""
message = 'Invalid config for [{}]: '.format(domain)
if hass is not None:
async_notify_setup_error(hass, domain, True)
if 'extra keys not allowed' in ex.error_message:
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
.format(ex.path[-1], domain, domain,
'->'.join(str(m) for m in ex.path))
else:
message += '{}.'.format(humanize_error(config, ex))
domain_config = config.get(domain, config)
message += " (See {}, line {}). ".format(
getattr(domain_config, '__config_file__', '?'),
getattr(domain_config, '__line__', '?'))
if domain != 'homeassistant':
message += ('Please check the docs at '
'https://home-assistant.io/components/{}/'.format(domain))
_LOGGER.error(message)
@asyncio.coroutine
def async_process_ha_core_config(hass, config):
"""Process the [homeassistant] section from the config.
@ -483,6 +516,67 @@ def merge_packages_config(config, packages):
return config
@callback
def async_process_component_config(hass, config, domain):
"""Check component config and return processed config.
Raise a vol.Invalid exception on error.
This method must be run in the event loop.
"""
component = get_component(domain)
if hasattr(component, 'CONFIG_SCHEMA'):
try:
config = component.CONFIG_SCHEMA(config)
except vol.Invalid as ex:
async_log_exception(ex, domain, config, hass)
return None
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.Invalid as ex:
async_log_exception(ex, domain, 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
platform = get_platform(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(p_validated)
except vol.Invalid as ex:
async_log_exception(ex, '{}.{}'.format(domain, p_name),
p_validated, 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
@asyncio.coroutine
def async_check_ha_config_file(hass):
"""Check if HA config file valid.
@ -501,3 +595,25 @@ def async_check_ha_config_file(hass):
return None
return re.sub(r'\033\[[^m]*m', '', str(stdout_data, 'utf-8'))
@callback
def async_notify_setup_error(hass, component, link=False):
"""Print a persistent notification.
This method must be run in the event loop.
"""
from homeassistant.components import persistent_notification
errors = hass.data.get(DATA_PERSISTENT_ERRORS)
if errors is None:
errors = hass.data[DATA_PERSISTENT_ERRORS] = {}
errors[component] = errors.get(component) or link
_lst = [HA_COMPONENT_URL.format(name.replace('_', '-'), name)
if link else name for name, link in errors.items()]
message = ('The following components and platforms could not be set up:\n'
'* ' + '\n* '.join(list(_lst)) + '\nPlease check your config')
persistent_notification.async_create(
hass, message, 'Invalid config', 'invalid_config')

View file

@ -122,6 +122,7 @@ class HomeAssistant(object):
self.loop.set_default_executor(self.executor)
self.loop.set_exception_handler(async_loop_exception_handler)
self._pending_tasks = []
self._track_task = False
self.bus = EventBus(self)
self.services = ServiceRegistry(self)
self.states = StateMachine(self.bus, self.loop)
@ -178,28 +179,7 @@ class HomeAssistant(object):
self.loop.call_soon_threadsafe(self.async_add_job, target, *args)
@callback
def _async_add_job(self, target: Callable[..., None], *args: Any) -> None:
"""Add a job from within the eventloop.
This method must be run in the event loop.
target: target to call.
args: parameters for method to call.
"""
if asyncio.iscoroutine(target):
self.loop.create_task(target)
elif is_callback(target):
self.loop.call_soon(target, *args)
elif asyncio.iscoroutinefunction(target):
self.loop.create_task(target(*args))
else:
self.loop.run_in_executor(None, target, *args)
async_add_job = _async_add_job
@callback
def _async_add_job_tracking(self, target: Callable[..., None],
*args: Any) -> None:
def async_add_job(self, target: Callable[..., None], *args: Any) -> None:
"""Add a job from within the eventloop.
This method must be run in the event loop.
@ -219,19 +199,21 @@ class HomeAssistant(object):
task = self.loop.run_in_executor(None, target, *args)
# if a task is sheduled
if task is not None:
if self._track_task and task is not None:
self._pending_tasks.append(task)
return task
@callback
def async_track_tasks(self):
"""Track tasks so you can wait for all tasks to be done."""
self.async_add_job = self._async_add_job_tracking
self._track_task = True
@asyncio.coroutine
def async_stop_track_tasks(self):
"""Track tasks so you can wait for all tasks to be done."""
yield from self.async_block_till_done()
self.async_add_job = self._async_add_job
self._track_task = False
@callback
def async_run_job(self, target: Callable[..., None], *args: Any) -> None:

View file

@ -63,20 +63,8 @@ def async_discover(hass, service, discovered=None, component=None,
'Cannot discover the {} component.'.format(component))
if component is not None and component not in hass.config.components:
did_lock = False
setup_lock = hass.data.get('setup_lock')
if setup_lock and setup_lock.locked():
did_lock = True
yield from setup_lock.acquire()
try:
# Could have been loaded while waiting for lock.
if component not in hass.config.components:
yield from bootstrap.async_setup_component(hass, component,
hass_config)
finally:
if did_lock:
setup_lock.release()
yield from bootstrap.async_setup_component(
hass, component, hass_config)
data = {
ATTR_SERVICE: service
@ -160,22 +148,11 @@ def async_load_platform(hass, component, platform, discovered=None,
raise HomeAssistantError(
'Cannot discover the {} component.'.format(component))
did_lock = False
setup_lock = hass.data.get('setup_lock')
if setup_lock and setup_lock.locked():
did_lock = True
yield from setup_lock.acquire()
setup_success = True
try:
# Could have been loaded while waiting for lock.
if component not in hass.config.components:
setup_success = yield from bootstrap.async_setup_component(
hass, component, hass_config)
finally:
if did_lock:
setup_lock.release()
if component not in hass.config.components:
setup_success = yield from bootstrap.async_setup_component(
hass, component, hass_config)
# No need to fire event if we could not setup component
if not setup_success:

View file

@ -3,8 +3,7 @@ import asyncio
from datetime import timedelta
from homeassistant import config as conf_util
from homeassistant.bootstrap import (
async_prepare_setup_platform, async_prepare_setup_component)
from homeassistant.bootstrap import async_prepare_setup_platform
from homeassistant.const import (
ATTR_ENTITY_ID, CONF_SCAN_INTERVAL, CONF_ENTITY_NAMESPACE,
DEVICE_DEFAULT_NAME)
@ -49,12 +48,9 @@ class EntityComponent(object):
def setup(self, config):
"""Set up a full entity component.
Loads the platforms from the config and will listen for supported
discovered platforms.
This doesn't block the executor to protect from deadlocks.
"""
run_coroutine_threadsafe(
self.async_setup(config), self.hass.loop
).result()
self.hass.add_job(self.async_setup(config))
@asyncio.coroutine
def async_setup(self, config):
@ -143,14 +139,16 @@ class EntityComponent(object):
if getattr(platform, 'async_setup_platform', None):
yield from platform.async_setup_platform(
self.hass, platform_config,
entity_platform.async_add_entities, discovery_info
entity_platform.async_schedule_add_entities, discovery_info
)
else:
yield from self.hass.loop.run_in_executor(
None, platform.setup_platform, self.hass, platform_config,
entity_platform.add_entities, discovery_info
entity_platform.schedule_add_entities, discovery_info
)
yield from entity_platform.async_block_entities_done()
self.hass.config.components.add(
'{}.{}'.format(self.domain, platform_type))
except Exception: # pylint: disable=broad-except
@ -275,7 +273,7 @@ class EntityComponent(object):
self.logger.error(err)
return None
conf = yield from async_prepare_setup_component(
conf = conf_util.async_process_component_config(
self.hass, conf, self.domain)
if conf is None:
@ -295,9 +293,40 @@ class EntityPlatform(object):
self.scan_interval = scan_interval
self.entity_namespace = entity_namespace
self.platform_entities = []
self._tasks = []
self._async_unsub_polling = None
self._process_updates = asyncio.Lock(loop=component.hass.loop)
@asyncio.coroutine
def async_block_entities_done(self):
"""Wait until all entities add to hass."""
if self._tasks:
pending = [task for task in self._tasks if not task.done()]
self._tasks.clear()
if pending:
yield from asyncio.wait(pending, loop=self.component.hass.loop)
def schedule_add_entities(self, new_entities, update_before_add=False):
"""Add entities for a single platform."""
if update_before_add:
for entity in new_entities:
entity.update()
run_callback_threadsafe(
self.component.hass.loop,
self.async_schedule_add_entities, list(new_entities), False
).result()
@callback
def async_schedule_add_entities(self, new_entities,
update_before_add=False):
"""Add entities for a single platform async."""
self._tasks.append(self.component.hass.async_add_job(
self.async_add_entities(
new_entities, update_before_add=update_before_add)
))
def add_entities(self, new_entities, update_before_add=False):
"""Add entities for a single platform."""
if update_before_add:
@ -306,8 +335,7 @@ class EntityPlatform(object):
run_coroutine_threadsafe(
self.async_add_entities(list(new_entities), False),
self.component.hass.loop
).result()
self.component.hass.loop).result()
@asyncio.coroutine
def async_add_entities(self, new_entities, update_before_add=False):
@ -319,8 +347,16 @@ class EntityPlatform(object):
if not new_entities:
return
tasks = [self._async_process_entity(entity, update_before_add)
for entity in new_entities]
@asyncio.coroutine
def async_process_entity(new_entity):
"""Add entities to StateMachine."""
ret = yield from self.component.async_add_entity(
new_entity, self, update_before_add=update_before_add
)
if ret:
self.platform_entities.append(new_entity)
tasks = [async_process_entity(entity) for entity in new_entities]
yield from asyncio.wait(tasks, loop=self.component.hass.loop)
yield from self.component.async_update_group()
@ -334,15 +370,6 @@ class EntityPlatform(object):
self.component.hass, self._update_entity_states, self.scan_interval
)
@asyncio.coroutine
def _async_process_entity(self, new_entity, update_before_add):
"""Add entities to StateMachine."""
ret = yield from self.component.async_add_entity(
new_entity, self, update_before_add=update_before_add
)
if ret:
self.platform_entities.append(new_entity)
@asyncio.coroutine
def async_reset(self):
"""Remove all entities and reset data.

View file

@ -170,41 +170,6 @@ def get_component(comp_name) -> Optional[ModuleType]:
return None
def load_order_components(components: Sequence[str]) -> OrderedSet:
"""Take in a list of components we want to load.
- filters out components we cannot load
- filters out components that have invalid/circular dependencies
- Will make sure the recorder component is loaded first
- Will ensure that all components that do not directly depend on
the group component will be loaded before the group component.
- returns an OrderedSet load order.
- Makes sure MQTT eventstream is available for publish before
components start updating states.
Async friendly.
"""
_check_prepared()
load_order = OrderedSet()
# Sort the list of modules on if they depend on group component or not.
# Components that do not depend on the group usually set up states.
# Components that depend on group usually use states in their setup.
for comp_load_order in sorted((load_order_component(component)
for component in components),
key=lambda order: 'group' in order):
load_order.update(comp_load_order)
# Push some to first place in load order
for comp in ('mqtt_eventstream', 'mqtt', 'recorder',
'introduction', 'logger'):
if comp in load_order:
load_order.promote(comp)
return load_order
def load_order_component(comp_name: str) -> OrderedSet:
"""Return an OrderedSet of components in the correct order of loading.

View file

@ -26,8 +26,8 @@ MOCKS = {
'load*': ("homeassistant.config.load_yaml", yaml.load_yaml),
'get': ("homeassistant.loader.get_component", loader.get_component),
'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml),
'except': ("homeassistant.bootstrap.async_log_exception",
bootstrap.async_log_exception),
'except': ("homeassistant.config.async_log_exception",
config_util.async_log_exception),
'package_error': ("homeassistant.config._log_pkg_error",
config_util._log_pkg_error),
}
@ -211,7 +211,7 @@ def check(config_path):
def mock_except(ex, domain, config, # pylint: disable=unused-variable
hass=None):
"""Mock bootstrap.log_exception."""
"""Mock config.log_exception."""
MOCKS['except'][1](ex, domain, config, hass)
res['except'][domain] = config.get(domain, config)

View file

@ -12,8 +12,8 @@ from contextlib import contextmanager
from aiohttp import web
from homeassistant import core as ha, loader
from homeassistant.bootstrap import (
setup_component, async_prepare_setup_component)
from homeassistant.bootstrap import setup_component, DATA_SETUP
from homeassistant.config import async_process_component_config
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
@ -93,13 +93,16 @@ def async_test_home_assistant(loop):
hass = ha.HomeAssistant(loop)
orig_async_add_job = hass.async_add_job
def async_add_job(target, *args):
"""Add a magic mock."""
if isinstance(target, MagicMock):
return
hass._async_add_job_tracking(target, *args)
return orig_async_add_job(target, *args)
hass.async_add_job = async_add_job
hass.async_track_tasks()
hass.config.location_name = 'test home'
hass.config.config_dir = get_test_config_dir()
@ -230,7 +233,7 @@ def mock_state_change_event(hass, new_state, old_state=None):
def mock_http_component(hass, api_password=None):
"""Mock the HTTP component."""
hass.http = MagicMock(api_password=api_password)
hass.config.components.add('http')
mock_component(hass, 'http')
hass.http.views = {}
def mock_register_view(view):
@ -268,6 +271,19 @@ def mock_mqtt_component(hass):
return mock_mqtt
def mock_component(hass, component):
"""Mock a component is setup."""
setup_tasks = hass.data.get(DATA_SETUP)
if setup_tasks is None:
setup_tasks = hass.data[DATA_SETUP] = {}
if component not in setup_tasks:
AssertionError("Component {} is already setup".format(component))
hass.config.components.add(component)
setup_tasks[component] = asyncio.Task(mock_coro(True), loop=hass.loop)
class MockModule(object):
"""Representation of a fake module."""
@ -439,10 +455,10 @@ def assert_setup_component(count, domain=None):
"""
config = {}
@asyncio.coroutine
@ha.callback
def mock_psc(hass, config_input, domain):
"""Mock the prepare_setup_component to capture config."""
res = yield from async_prepare_setup_component(
res = async_process_component_config(
hass, config_input, domain)
config[domain] = None if res is None else res.get(domain)
_LOGGER.debug('Configuration for %s, Validated: %s, Original %s',
@ -450,7 +466,7 @@ def assert_setup_component(count, domain=None):
return res
assert isinstance(config, dict)
with patch('homeassistant.bootstrap.async_prepare_setup_component',
with patch('homeassistant.config.async_process_component_config',
mock_psc):
yield config

View file

@ -30,7 +30,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_fail_setup_without_state_topic(self):
"""Test for failing with no state topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(0) as config:
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
@ -42,7 +41,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_fail_setup_without_command_topic(self):
"""Test failing with no command topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(0):
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
@ -53,7 +51,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_update_state_via_state_topic(self):
"""Test updating with via state topic."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -77,7 +74,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_ignore_update_state_if_unknown_via_state_topic(self):
"""Test ignoring updates via state topic."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -98,7 +94,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_arm_home_publishes_mqtt(self):
"""Test publishing of MQTT messages while armed."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -115,7 +110,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_arm_home_not_publishes_mqtt_with_invalid_code(self):
"""Test not publishing of MQTT messages with invalid code."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -133,7 +127,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_arm_away_publishes_mqtt(self):
"""Test publishing of MQTT messages while armed."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -150,7 +143,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_arm_away_not_publishes_mqtt_with_invalid_code(self):
"""Test not publishing of MQTT messages with invalid code."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -168,7 +160,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_disarm_publishes_mqtt(self):
"""Test publishing of MQTT messages while disarmed."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',
@ -185,7 +176,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
def test_disarm_not_publishes_mqtt_with_invalid_code(self):
"""Test not publishing of MQTT messages with invalid code."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
alarm_control_panel.DOMAIN: {
'platform': 'mqtt',

View file

@ -5,7 +5,7 @@ from homeassistant.core import callback
from homeassistant.bootstrap import setup_component
import homeassistant.components.automation as automation
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
# pylint: disable=invalid-name
@ -15,7 +15,7 @@ class TestAutomationEvent(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
self.calls = []
@callback

View file

@ -11,7 +11,7 @@ from homeassistant.exceptions import HomeAssistantError
import homeassistant.util.dt as dt_util
from tests.common import get_test_home_assistant, assert_setup_component, \
fire_time_changed
fire_time_changed, mock_component
# pylint: disable=invalid-name
@ -21,7 +21,7 @@ class TestAutomation(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
self.calls = []
@callback

View file

@ -5,7 +5,8 @@ from homeassistant.core import callback
from homeassistant.bootstrap import setup_component
import homeassistant.components.automation as automation
from tests.common import (
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant)
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant,
mock_component)
# pylint: disable=invalid-name
@ -15,7 +16,7 @@ class TestAutomationMQTT(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
mock_mqtt_component(self.hass)
self.calls = []

View file

@ -5,7 +5,7 @@ from homeassistant.core import callback
from homeassistant.bootstrap import setup_component
import homeassistant.components.automation as automation
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
# pylint: disable=invalid-name
@ -15,7 +15,7 @@ class TestAutomationNumericState(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
self.calls = []
@callback

View file

@ -10,7 +10,8 @@ import homeassistant.util.dt as dt_util
import homeassistant.components.automation as automation
from tests.common import (
fire_time_changed, get_test_home_assistant, assert_setup_component)
fire_time_changed, get_test_home_assistant, assert_setup_component,
mock_component)
# pylint: disable=invalid-name
@ -20,7 +21,7 @@ class TestAutomationState(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
self.hass.states.set('test.entity', 'hello')
self.calls = []

View file

@ -10,7 +10,8 @@ from homeassistant.components import sun
import homeassistant.components.automation as automation
import homeassistant.util.dt as dt_util
from tests.common import fire_time_changed, get_test_home_assistant
from tests.common import (
fire_time_changed, get_test_home_assistant, mock_component)
# pylint: disable=invalid-name
@ -20,8 +21,8 @@ class TestAutomationSun(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
self.hass.config.components.add('sun')
mock_component(self.hass, 'group')
mock_component(self.hass, 'sun')
self.calls = []

View file

@ -5,7 +5,8 @@ from homeassistant.core import callback
from homeassistant.bootstrap import setup_component
import homeassistant.components.automation as automation
from tests.common import get_test_home_assistant, assert_setup_component
from tests.common import (
get_test_home_assistant, assert_setup_component, mock_component)
# pylint: disable=invalid-name
@ -15,7 +16,7 @@ class TestAutomationTemplate(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
self.hass.states.set('test.entity', 'hello')
self.calls = []

View file

@ -9,7 +9,8 @@ import homeassistant.util.dt as dt_util
import homeassistant.components.automation as automation
from tests.common import (
fire_time_changed, get_test_home_assistant, assert_setup_component)
fire_time_changed, get_test_home_assistant, assert_setup_component,
mock_component)
# pylint: disable=invalid-name
@ -19,7 +20,7 @@ class TestAutomationTime(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
self.calls = []
@callback

View file

@ -5,7 +5,7 @@ from homeassistant.core import callback
from homeassistant.bootstrap import setup_component
from homeassistant.components import automation, zone
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
# pylint: disable=invalid-name
@ -15,7 +15,7 @@ class TestAutomationZone(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('group')
mock_component(self.hass, 'group')
assert setup_component(self.hass, zone.DOMAIN, {
'zone': {
'name': 'test',

View file

@ -3,10 +3,10 @@ import unittest
from homeassistant.bootstrap import setup_component
import homeassistant.components.binary_sensor as binary_sensor
from tests.common import mock_mqtt_component, fire_mqtt_message
from homeassistant.const import (STATE_OFF, STATE_ON)
from tests.common import get_test_home_assistant
from tests.common import (
get_test_home_assistant, mock_mqtt_component, fire_mqtt_message)
class TestSensorMQTT(unittest.TestCase):
@ -23,7 +23,6 @@ class TestSensorMQTT(unittest.TestCase):
def test_setting_sensor_value_via_mqtt_message(self):
"""Test the setting of the value via MQTT."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, binary_sensor.DOMAIN, {
binary_sensor.DOMAIN: {
'platform': 'mqtt',
@ -49,7 +48,6 @@ class TestSensorMQTT(unittest.TestCase):
def test_valid_device_class(self):
"""Test the setting of a valid sensor class."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, binary_sensor.DOMAIN, {
binary_sensor.DOMAIN: {
'platform': 'mqtt',
@ -64,7 +62,6 @@ class TestSensorMQTT(unittest.TestCase):
def test_invalid_device_class(self):
"""Test the setting of an invalid sensor class."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, binary_sensor.DOMAIN, {
binary_sensor.DOMAIN: {
'platform': 'mqtt',

View file

@ -9,7 +9,7 @@ from uvcclient import nvr
from homeassistant.bootstrap import setup_component
from homeassistant.components.camera import uvc
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_http_component
class TestUVCSetup(unittest.TestCase):
@ -18,8 +18,7 @@ class TestUVCSetup(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.http = mock.MagicMock()
self.hass.config.components = set(['http'])
mock_http_component(self.hass)
def tearDown(self):
"""Stop everything that was started."""

View file

@ -1,10 +1,11 @@
"""The tests for the generic_thermostat."""
import asyncio
import datetime
import unittest
from unittest import mock
from homeassistant.core import callback
from homeassistant.bootstrap import setup_component
from homeassistant.bootstrap import setup_component, async_setup_component
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
SERVICE_TURN_OFF,
@ -105,23 +106,6 @@ class TestClimateGenericThermostat(unittest.TestCase):
self.assertEqual(35, state.attributes.get('max_temp'))
self.assertEqual(None, state.attributes.get('temperature'))
def test_custom_setup_params(self):
"""Test the setup with custom parameters."""
self.hass.config.components.remove(climate.DOMAIN)
assert setup_component(self.hass, climate.DOMAIN, {'climate': {
'platform': 'generic_thermostat',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'min_temp': MIN_TEMP,
'max_temp': MAX_TEMP,
'target_temp': TARGET_TEMP,
}})
state = self.hass.states.get(ENTITY)
self.assertEqual(MIN_TEMP, state.attributes.get('min_temp'))
self.assertEqual(MAX_TEMP, state.attributes.get('max_temp'))
self.assertEqual(TARGET_TEMP, state.attributes.get('temperature'))
def test_set_target_temp(self):
"""Test the setting of the target temperature."""
climate.set_temperature(self.hass, 30)
@ -538,3 +522,23 @@ class TestClimateGenericThermostatMinCycle(unittest.TestCase):
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)
@asyncio.coroutine
def test_custom_setup_params(hass):
"""Test the setup with custom parameters."""
result = yield from async_setup_component(
hass, climate.DOMAIN, {'climate': {
'platform': 'generic_thermostat',
'name': 'test',
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'min_temp': MIN_TEMP,
'max_temp': MAX_TEMP,
'target_temp': TARGET_TEMP,
}})
assert result
state = hass.states.get(ENTITY)
assert state.attributes.get('min_temp') == MIN_TEMP
assert state.attributes.get('max_temp') == MAX_TEMP
assert state.attributes.get('temperature') == TARGET_TEMP

View file

@ -15,6 +15,9 @@ def test_validate_config_ok(hass, test_client):
with patch.object(config, 'SECTIONS', ['core']):
yield from async_setup_component(hass, 'config', {})
# yield from hass.async_block_till_done()
yield from asyncio.sleep(0.1, loop=hass.loop)
hass.http.views[CheckConfigView.name].register(app.router)
client = yield from test_client(app)

View file

@ -8,7 +8,7 @@ from homeassistant.const import EVENT_COMPONENT_LOADED
from homeassistant.bootstrap import async_setup_component, ATTR_COMPONENT
from homeassistant.components import config
from tests.common import mock_http_component, mock_coro
from tests.common import mock_http_component, mock_coro, mock_component
@pytest.fixture(autouse=True)
@ -27,7 +27,7 @@ def test_config_setup(hass, loop):
@asyncio.coroutine
def test_load_on_demand_already_loaded(hass, test_client):
"""Test getting suites."""
hass.config.components.add('zwave')
mock_component(hass, 'zwave')
with patch.object(config, 'SECTIONS', []), \
patch.object(config, 'ON_DEMAND', ['zwave']), \

View file

@ -4,9 +4,9 @@ import unittest
from homeassistant.bootstrap import setup_component
from homeassistant.const import STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN
import homeassistant.components.cover as cover
from tests.common import mock_mqtt_component, fire_mqtt_message
from tests.common import get_test_home_assistant
from tests.common import (
get_test_home_assistant, mock_mqtt_component, fire_mqtt_message)
class TestCoverMQTT(unittest.TestCase):
@ -23,7 +23,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_state_via_state_topic(self):
"""Test the controlling state via topic."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',
@ -72,7 +71,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_state_via_template(self):
"""Test the controlling state via topic."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',
@ -101,7 +99,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_optimistic_state_change(self):
"""Test changing state optimistically."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',
@ -132,7 +129,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_send_open_cover_command(self):
"""Test the sending of open_cover."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',
@ -156,7 +152,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_send_close_cover_command(self):
"""Test the sending of close_cover."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',
@ -180,7 +175,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_send_stop__cover_command(self):
"""Test the sending of stop_cover."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',
@ -204,7 +198,6 @@ class TestCoverMQTT(unittest.TestCase):
def test_current_cover_position(self):
"""Test the current cover position."""
self.hass.config.components = set(['mqtt'])
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
cover.DOMAIN: {
'platform': 'mqtt',

View file

@ -6,7 +6,7 @@ import pytest
from homeassistant.bootstrap import setup_component
from homeassistant.components import rfxtrx as rfxtrx_core
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
@ -16,7 +16,7 @@ class TestCoverRfxtrx(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['rfxtrx'])
mock_component('rfxtrx')
def tearDown(self):
"""Stop everything that was started."""

View file

@ -17,7 +17,8 @@ from homeassistant.const import (CONF_PLATFORM, CONF_PASSWORD, CONF_USERNAME,
CONF_HOST)
from tests.common import (
get_test_home_assistant, get_test_config_dir, assert_setup_component)
get_test_home_assistant, get_test_config_dir, assert_setup_component,
mock_component)
FAKEFILE = None
@ -43,7 +44,7 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase):
def setup_method(self, _):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['zone'])
mock_component(self.hass, 'zone')
def teardown_method(self, _):
"""Stop everything that was started."""

View file

@ -16,7 +16,8 @@ from homeassistant.components.device_tracker import DOMAIN
from homeassistant.util import slugify
from tests.common import (
get_test_home_assistant, assert_setup_component, load_fixture)
get_test_home_assistant, assert_setup_component, load_fixture,
mock_component)
from ...test_util.aiohttp import mock_aiohttp_client
@ -39,7 +40,7 @@ class TestDdwrt(unittest.TestCase):
def setup_method(self, _):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['zone'])
mock_component(self.hass, 'zone')
def teardown_method(self, _):
"""Stop everything that was started."""

View file

@ -43,7 +43,6 @@ class TestComponentsDeviceTrackerMQTT(unittest.TestCase):
dev_id = 'paulus'
topic = '/location/paulus'
self.hass.config.components = set(['mqtt', 'zone'])
assert setup_component(self.hass, device_tracker.DOMAIN, {
device_tracker.DOMAIN: {
CONF_PLATFORM: 'mqtt',

View file

@ -13,7 +13,8 @@ import homeassistant.components.device_tracker.upc_connect as platform
from homeassistant.util.async import run_coroutine_threadsafe
from tests.common import (
get_test_home_assistant, assert_setup_component, load_fixture)
get_test_home_assistant, assert_setup_component, load_fixture,
mock_component)
_LOGGER = logging.getLogger(__name__)
@ -30,7 +31,7 @@ class TestUPCConnect(object):
def setup_method(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['zone'])
mock_component(self.hass, 'zone')
self.host = "127.0.0.1"

View file

@ -1,7 +1,6 @@
"""The tests for the Home Assistant HTTP component."""
import asyncio
import requests
from unittest.mock import MagicMock
from homeassistant import bootstrap, const
import homeassistant.components.http as http
@ -157,46 +156,48 @@ def test_registering_view_while_running(hass, test_client):
assert text == 'hello'
def test_api_base_url(loop):
@asyncio.coroutine
def test_api_base_url_with_domain(hass):
"""Test setting api url."""
hass = MagicMock()
hass.loop = loop
assert loop.run_until_complete(
bootstrap.async_setup_component(hass, 'http', {
'http': {
'base_url': 'example.com'
}
})
)
result = yield from bootstrap.async_setup_component(hass, 'http', {
'http': {
'base_url': 'example.com'
}
})
assert result
assert hass.config.api.base_url == 'http://example.com'
assert loop.run_until_complete(
bootstrap.async_setup_component(hass, 'http', {
'http': {
'server_host': '1.1.1.1'
}
})
)
@asyncio.coroutine
def test_api_base_url_with_ip(hass):
"""Test setting api url."""
result = yield from bootstrap.async_setup_component(hass, 'http', {
'http': {
'server_host': '1.1.1.1'
}
})
assert result
assert hass.config.api.base_url == 'http://1.1.1.1:8123'
assert loop.run_until_complete(
bootstrap.async_setup_component(hass, 'http', {
'http': {
'server_host': '1.1.1.1'
}
})
)
assert hass.config.api.base_url == 'http://1.1.1.1:8123'
@asyncio.coroutine
def test_api_base_url_with_ip_port(hass):
"""Test setting api url."""
result = yield from bootstrap.async_setup_component(hass, 'http', {
'http': {
'base_url': '1.1.1.1:8124'
}
})
assert result
assert hass.config.api.base_url == 'http://1.1.1.1:8124'
assert loop.run_until_complete(
bootstrap.async_setup_component(hass, 'http', {
'http': {
}
})
)
@asyncio.coroutine
def test_api_no_base_url(hass):
"""Test setting api url."""
result = yield from bootstrap.async_setup_component(hass, 'http', {
'http': {
}
})
assert result
assert hass.config.api.base_url == 'http://127.0.0.1:8123'

View file

@ -8,7 +8,7 @@ from homeassistant.bootstrap import setup_component, async_setup_component
import homeassistant.components.light as light
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
ENTITY_LIGHT = 'light.bed_light'
@ -68,7 +68,7 @@ class TestDemoLight(unittest.TestCase):
@asyncio.coroutine
def test_restore_state(hass):
"""Test state gets restored."""
hass.config.components.add('recorder')
mock_component(hass, 'recorder')
hass.state = CoreState.starting
hass.data[DATA_RESTORE_CACHE] = {
'light.bed_light': State('light.bed_light', 'on', {

View file

@ -100,7 +100,6 @@ class TestLightMQTT(unittest.TestCase):
def test_fail_setup_if_no_command_topic(self):
"""Test if command fails with command topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(0):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -113,7 +112,6 @@ class TestLightMQTT(unittest.TestCase):
def test_no_color_or_brightness_or_color_temp_if_no_topics(self): \
# pylint: disable=invalid-name
"""Test if there is no color and brightness if no topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -158,7 +156,6 @@ class TestLightMQTT(unittest.TestCase):
'payload_off': 0
}}
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, config)
@ -214,7 +211,6 @@ class TestLightMQTT(unittest.TestCase):
def test_controlling_scale(self):
"""Test the controlling scale."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -277,7 +273,6 @@ class TestLightMQTT(unittest.TestCase):
'rgb_value_template': '{{ value_json.hello | join(",") }}',
}}
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, config)
@ -317,7 +312,6 @@ class TestLightMQTT(unittest.TestCase):
'payload_off': 'off'
}}
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, config)
@ -367,7 +361,6 @@ class TestLightMQTT(unittest.TestCase):
'state_topic': 'test_light_rgb/status',
}}
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, config)
@ -392,7 +385,6 @@ class TestLightMQTT(unittest.TestCase):
'state_topic': 'test_light_rgb/status'
}}
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, config)

View file

@ -53,7 +53,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_fail_setup_if_no_command_topic(self): \
# pylint: disable=invalid-name
"""Test if setup fails with no command topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(0):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -66,7 +65,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_no_color_or_brightness_if_no_config(self): \
# pylint: disable=invalid-name
"""Test if there is no color and brightness if they aren't defined."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
'platform': 'mqtt_json',
@ -92,7 +90,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_controlling_state_via_topic(self): \
# pylint: disable=invalid-name
"""Test the controlling of the state via topic."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
'platform': 'mqtt_json',
@ -152,7 +149,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_sending_mqtt_commands_and_optimistic(self): \
# pylint: disable=invalid-name
"""Test the sending of command in optimistic mode."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
'platform': 'mqtt_json',
@ -208,7 +204,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_flash_short_and_long(self): \
# pylint: disable=invalid-name
"""Test for flash length being sent when included."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
'platform': 'mqtt_json',
@ -250,7 +245,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_transition(self):
"""Test for transition time being sent when included."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
'platform': 'mqtt_json',
@ -292,7 +286,6 @@ class TestLightMQTTJSON(unittest.TestCase):
def test_invalid_color_and_brightness_values(self): \
# pylint: disable=invalid-name
"""Test that invalid color/brightness values are ignored."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
'platform': 'mqtt_json',

View file

@ -45,7 +45,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_setup_fails(self): \
# pylint: disable=invalid-name
"""Test that setup fails with missing required configuration items."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(0):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -58,7 +57,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_state_change_via_topic(self): \
# pylint: disable=invalid-name
"""Test state change via topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -93,7 +91,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_state_brightness_color_effect_change_via_topic(self): \
# pylint: disable=invalid-name
"""Test state, brightness, color and effect change via topic."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -170,7 +167,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_optimistic(self): \
# pylint: disable=invalid-name
"""Test optimistic mode."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -232,7 +228,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_flash(self): \
# pylint: disable=invalid-name
"""Test flash."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -276,7 +271,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_transition(self):
"""Test for transition time being sent when included."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {
@ -320,7 +314,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
def test_invalid_values(self): \
# pylint: disable=invalid-name
"""Test that invalid values are ignored."""
self.hass.config.components = set(['mqtt'])
with assert_setup_component(1):
assert setup_component(self.hass, light.DOMAIN, {
light.DOMAIN: {

View file

@ -6,7 +6,7 @@ import pytest
from homeassistant.bootstrap import setup_component
from homeassistant.components import rfxtrx as rfxtrx_core
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
@ -16,7 +16,7 @@ class TestLightRfxtrx(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['rfxtrx'])
mock_component(self.hass, 'rfxtrx')
def tearDown(self):
"""Stop everything that was started."""

View file

@ -23,7 +23,6 @@ class TestLockMQTT(unittest.TestCase):
def test_controlling_state_via_topic(self):
"""Test the controlling state via topic."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, lock.DOMAIN, {
lock.DOMAIN: {
'platform': 'mqtt',
@ -53,7 +52,6 @@ class TestLockMQTT(unittest.TestCase):
def test_sending_mqtt_commands_and_optimistic(self):
"""Test the sending MQTT commands in optimistic mode."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, lock.DOMAIN, {
lock.DOMAIN: {
'platform': 'mqtt',
@ -87,7 +85,6 @@ class TestLockMQTT(unittest.TestCase):
def test_controlling_state_via_topic_and_json_message(self):
"""Test the controlling state via topic and JSON message."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, lock.DOMAIN, {
lock.DOMAIN: {
'platform': 'mqtt',

View file

@ -1,5 +1,4 @@
"""The tests for the Universal Media player platform."""
import asyncio
from copy import copy
import unittest
@ -258,7 +257,6 @@ class TestMediaPlayer(unittest.TestCase):
bad_config = {'platform': 'universal'}
entities = []
@asyncio.coroutine
def add_devices(new_entities):
"""Add devices to list."""
for dev in new_entities:

View file

@ -4,7 +4,8 @@ from unittest.mock import Mock, MagicMock, patch
from homeassistant.bootstrap import setup_component
import homeassistant.components.mqtt as mqtt
from tests.common import get_test_home_assistant, mock_coro
from tests.common import (
get_test_home_assistant, mock_coro, mock_http_component)
class TestMQTT:
@ -13,7 +14,7 @@ class TestMQTT:
def setup_method(self, method):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components.add('http')
mock_http_component(self.hass, 'super_secret')
def teardown_method(self, method):
"""Stop everything that was started."""
@ -33,13 +34,21 @@ class TestMQTT:
self.hass.config.api = MagicMock(api_password=password)
assert setup_component(self.hass, mqtt.DOMAIN, {})
assert mock_mqtt.called
from pprint import pprint
pprint(mock_mqtt.mock_calls)
assert mock_mqtt.mock_calls[1][1][5] == 'homeassistant'
assert mock_mqtt.mock_calls[1][1][6] == password
mock_mqtt.reset_mock()
@patch('passlib.apps.custom_app_context', Mock(return_value=''))
@patch('tempfile.NamedTemporaryFile', Mock(return_value=MagicMock()))
@patch('hbmqtt.broker.Broker', Mock(return_value=MagicMock()))
@patch('hbmqtt.broker.Broker.start', Mock(return_value=mock_coro()))
@patch('homeassistant.components.mqtt.MQTT')
def test_creating_config_with_http_no_pass(self, mock_mqtt):
"""Test if the MQTT server gets started and subscribe/publish msg."""
mock_mqtt().async_connect.return_value = mock_coro(True)
self.hass.bus.listen_once = MagicMock()
self.hass.config.components = set(['http'])
self.hass.config.api = MagicMock(api_password=None)
assert setup_component(self.hass, mqtt.DOMAIN, {})
assert mock_mqtt.called

View file

@ -1,5 +1,4 @@
"""The tests for the notify demo platform."""
import asyncio
import unittest
from unittest.mock import patch
@ -17,12 +16,6 @@ CONFIG = {
}
@asyncio.coroutine
def mock_setup_platform():
"""Mock prepare_setup_platform."""
return None
class TestNotifyDemo(unittest.TestCase):
"""Test the demo notify."""
@ -52,15 +45,6 @@ class TestNotifyDemo(unittest.TestCase):
"""Test setup."""
self._setup_notify()
@patch('homeassistant.bootstrap.async_prepare_setup_platform',
return_value=mock_setup_platform())
def test_no_prepare_setup_platform(self, mock_prep_setup_platform):
"""Test missing notify platform."""
with assert_setup_component(0):
setup_component(self.hass, notify.DOMAIN, CONFIG)
assert mock_prep_setup_platform.called
@patch('homeassistant.components.notify.demo.get_service', autospec=True)
def test_no_notify_service(self, mock_demo_get_service):
"""Test missing platform notify service instance."""

View file

@ -5,7 +5,7 @@ from homeassistant.bootstrap import setup_component
import homeassistant.components.sensor as sensor
from tests.common import mock_mqtt_component, fire_mqtt_message
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
class TestSensorMQTT(unittest.TestCase):
@ -22,7 +22,7 @@ class TestSensorMQTT(unittest.TestCase):
def test_setting_sensor_value_via_mqtt_message(self):
"""Test the setting of the value via MQTT."""
self.hass.config.components = set(['mqtt'])
mock_component(self.hass, 'mqtt')
assert setup_component(self.hass, sensor.DOMAIN, {
sensor.DOMAIN: {
'platform': 'mqtt',
@ -42,7 +42,7 @@ class TestSensorMQTT(unittest.TestCase):
def test_setting_sensor_value_via_mqtt_json_message(self):
"""Test the setting of the value via MQTT with JSON playload."""
self.hass.config.components = set(['mqtt'])
mock_component(self.hass, 'mqtt')
assert setup_component(self.hass, sensor.DOMAIN, {
sensor.DOMAIN: {
'platform': 'mqtt',

View file

@ -5,7 +5,8 @@ from homeassistant.bootstrap import setup_component
import homeassistant.components.sensor as sensor
from homeassistant.components import pilight
from tests.common import get_test_home_assistant, assert_setup_component
from tests.common import (
get_test_home_assistant, assert_setup_component, mock_component)
HASS = None
@ -23,7 +24,7 @@ def setup_function():
global HASS
HASS = get_test_home_assistant()
HASS.config.components = set(['pilight'])
mock_component(HASS, 'pilight')
# pylint: disable=invalid-name

View file

@ -7,7 +7,7 @@ from homeassistant.bootstrap import setup_component
from homeassistant.components import rfxtrx as rfxtrx_core
from homeassistant.const import TEMP_CELSIUS
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
@ -17,7 +17,7 @@ class TestSensorRfxtrx(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['rfxtrx'])
mock_component(self.hass, 'rfxtrx')
def tearDown(self):
"""Stop everything that was started."""

View file

@ -22,7 +22,6 @@ class TestSensorMQTT(unittest.TestCase):
def test_controlling_state_via_topic(self):
"""Test the controlling state via topic."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, switch.DOMAIN, {
switch.DOMAIN: {
'platform': 'mqtt',
@ -52,7 +51,6 @@ class TestSensorMQTT(unittest.TestCase):
def test_sending_mqtt_commands_and_optimistic(self):
"""Test the sending MQTT commands in optimistic mode."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, switch.DOMAIN, {
switch.DOMAIN: {
'platform': 'mqtt',
@ -86,7 +84,6 @@ class TestSensorMQTT(unittest.TestCase):
def test_controlling_state_via_topic_and_json_message(self):
"""Test the controlling state via topic and JSON message."""
self.hass.config.components = set(['mqtt'])
assert setup_component(self.hass, switch.DOMAIN, {
switch.DOMAIN: {
'platform': 'mqtt',

View file

@ -6,7 +6,7 @@ import pytest
from homeassistant.bootstrap import setup_component
from homeassistant.components import rfxtrx as rfxtrx_core
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
@ -16,7 +16,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.config.components = set(['rfxtrx'])
mock_component(self.hass, 'rfxtrx')
def tearDown(self):
"""Stop everything that was started."""

View file

@ -4,7 +4,7 @@ import asyncio
import unittest
import logging
from tests.common import get_test_home_assistant
from tests.common import get_test_home_assistant, mock_component
from homeassistant.core import CoreState, State
from homeassistant.bootstrap import setup_component, async_setup_component
@ -118,7 +118,7 @@ def test_restore_state(hass):
}
hass.state = CoreState.starting
hass.config.components.add('recorder')
mock_component(hass, 'recorder')
yield from async_setup_component(hass, DOMAIN, {
DOMAIN: {

Some files were not shown because too many files have changed in this diff Show more