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:
parent
383b0914b3
commit
41f558b181
109 changed files with 764 additions and 848 deletions
|
@ -7,12 +7,10 @@ import threading
|
|||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
import pytest
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||
import homeassistant.config as config_util
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant import bootstrap, loader
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
|
||||
|
@ -79,23 +77,8 @@ class TestBootstrap:
|
|||
patch_yaml_files(files, True):
|
||||
self.hass = bootstrap.from_config_file('config.yaml')
|
||||
|
||||
components.add('group')
|
||||
assert components == self.hass.config.components
|
||||
|
||||
def test_handle_setup_circular_dependency(self):
|
||||
"""Test the setup of circular dependencies."""
|
||||
loader.set_component('comp_b', MockModule('comp_b', ['comp_a']))
|
||||
|
||||
def setup_a(hass, config):
|
||||
"""Setup the another component."""
|
||||
bootstrap.setup_component(hass, 'comp_b')
|
||||
return True
|
||||
|
||||
loader.set_component('comp_a', MockModule('comp_a', setup=setup_a))
|
||||
|
||||
bootstrap.setup_component(self.hass, 'comp_a')
|
||||
assert set(['comp_a']) == self.hass.config.components
|
||||
|
||||
def test_validate_component_config(self):
|
||||
"""Test validating component configuration."""
|
||||
config_schema = vol.Schema({
|
||||
|
@ -109,16 +92,22 @@ class TestBootstrap:
|
|||
with assert_setup_component(0):
|
||||
assert not bootstrap.setup_component(self.hass, 'comp_conf', {})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
|
||||
with assert_setup_component(0):
|
||||
assert not bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||
'comp_conf': None
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
|
||||
with assert_setup_component(0):
|
||||
assert not bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||
'comp_conf': {}
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
|
||||
with assert_setup_component(0):
|
||||
assert not bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||
'comp_conf': {
|
||||
|
@ -127,6 +116,8 @@ class TestBootstrap:
|
|||
}
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
|
||||
with assert_setup_component(1):
|
||||
assert bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||
'comp_conf': {
|
||||
|
@ -154,6 +145,7 @@ class TestBootstrap:
|
|||
}
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('platform_conf')
|
||||
|
||||
with assert_setup_component(1):
|
||||
|
@ -167,6 +159,7 @@ class TestBootstrap:
|
|||
}
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('platform_conf')
|
||||
|
||||
with assert_setup_component(0):
|
||||
|
@ -177,6 +170,7 @@ class TestBootstrap:
|
|||
}
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('platform_conf')
|
||||
|
||||
with assert_setup_component(1):
|
||||
|
@ -187,6 +181,7 @@ class TestBootstrap:
|
|||
}
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('platform_conf')
|
||||
|
||||
with assert_setup_component(1):
|
||||
|
@ -197,6 +192,7 @@ class TestBootstrap:
|
|||
}]
|
||||
})
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('platform_conf')
|
||||
|
||||
# Any falsey platform config will be ignored (None, {}, etc)
|
||||
|
@ -244,22 +240,27 @@ class TestBootstrap:
|
|||
|
||||
def test_component_not_setup_twice_if_loaded_during_other_setup(self):
|
||||
"""Test component setup while waiting for lock is not setup twice."""
|
||||
loader.set_component('comp', MockModule('comp'))
|
||||
|
||||
result = []
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_setup(hass, config):
|
||||
"""Tracking Setup."""
|
||||
result.append(1)
|
||||
|
||||
loader.set_component(
|
||||
'comp', MockModule('comp', async_setup=async_setup))
|
||||
|
||||
def setup_component():
|
||||
"""Setup the component."""
|
||||
result.append(bootstrap.setup_component(self.hass, 'comp'))
|
||||
bootstrap.setup_component(self.hass, 'comp')
|
||||
|
||||
thread = threading.Thread(target=setup_component)
|
||||
thread.start()
|
||||
self.hass.config.components.add('comp')
|
||||
bootstrap.setup_component(self.hass, 'comp')
|
||||
|
||||
thread.join()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0]
|
||||
|
||||
def test_component_not_setup_missing_dependencies(self):
|
||||
"""Test we do not setup a component if not all dependencies loaded."""
|
||||
|
@ -269,8 +270,9 @@ class TestBootstrap:
|
|||
assert not bootstrap.setup_component(self.hass, 'comp', {})
|
||||
assert 'comp' not in self.hass.config.components
|
||||
|
||||
loader.set_component('non_existing', MockModule('non_existing'))
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
|
||||
loader.set_component('non_existing', MockModule('non_existing'))
|
||||
assert bootstrap.setup_component(self.hass, 'comp', {})
|
||||
|
||||
def test_component_failing_setup(self):
|
||||
|
@ -349,6 +351,7 @@ class TestBootstrap:
|
|||
})
|
||||
assert mock_setup.call_count == 0
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('switch')
|
||||
|
||||
with assert_setup_component(0):
|
||||
|
@ -361,6 +364,7 @@ class TestBootstrap:
|
|||
})
|
||||
assert mock_setup.call_count == 0
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
self.hass.config.components.remove('switch')
|
||||
|
||||
with assert_setup_component(1):
|
||||
|
@ -382,6 +386,7 @@ class TestBootstrap:
|
|||
assert loader.get_component('disabled_component') is None
|
||||
assert 'disabled_component' not in self.hass.config.components
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
loader.set_component(
|
||||
'disabled_component',
|
||||
MockModule('disabled_component', setup=lambda hass, config: False))
|
||||
|
@ -390,6 +395,7 @@ class TestBootstrap:
|
|||
assert loader.get_component('disabled_component') is not None
|
||||
assert 'disabled_component' not in self.hass.config.components
|
||||
|
||||
self.hass.data.pop(bootstrap.DATA_SETUP)
|
||||
loader.set_component(
|
||||
'disabled_component',
|
||||
MockModule('disabled_component', setup=lambda hass, config: True))
|
||||
|
@ -435,35 +441,16 @@ class TestBootstrap:
|
|||
|
||||
self.hass.bus.listen_once(EVENT_HOMEASSISTANT_START, track_start)
|
||||
|
||||
self.hass.loop.run_until_complete = \
|
||||
lambda _: self.hass.block_till_done()
|
||||
|
||||
bootstrap.from_config_dict({'test_component1': None}, self.hass)
|
||||
|
||||
self.hass.add_job(bootstrap.async_setup_component(
|
||||
self.hass, 'test_component1', {}))
|
||||
self.hass.block_till_done()
|
||||
self.hass.start()
|
||||
|
||||
assert call_order == [1, 1, 2]
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_component_cannot_depend_config(hass):
|
||||
"""Test config is not allowed to be a dependency."""
|
||||
loader.set_component(
|
||||
'test_component1',
|
||||
MockModule('test_component1', dependencies=['config']))
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
yield from bootstrap.async_from_config_dict(
|
||||
{'test_component1': None}, hass)
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_platform_cannot_depend_config():
|
||||
"""Test config is not allowed to be a dependency."""
|
||||
loader.set_component(
|
||||
'test_component1.test',
|
||||
MockPlatform('whatever', dependencies=['config']))
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
yield from bootstrap.async_prepare_setup_platform(
|
||||
mock.MagicMock(), {}, 'test_component1', 'test')
|
||||
result = yield from bootstrap._async_process_dependencies(
|
||||
hass, None, 'test', ['config'])
|
||||
assert not result
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue