Move signal handling out of core to bootstrap (#5815)
* Move signal handling out of core to bootstrap * Fix tests
This commit is contained in:
parent
7eb4bdc37b
commit
2cbed9cd96
7 changed files with 44 additions and 26 deletions
|
@ -5,6 +5,7 @@ omit =
|
||||||
homeassistant/__main__.py
|
homeassistant/__main__.py
|
||||||
homeassistant/scripts/*.py
|
homeassistant/scripts/*.py
|
||||||
homeassistant/helpers/typing.py
|
homeassistant/helpers/typing.py
|
||||||
|
homeassistant/helpers/signal.py
|
||||||
|
|
||||||
# omit pieces of code that rely on external devices being present
|
# omit pieces of code that rely on external devices being present
|
||||||
homeassistant/components/apcupsd.py
|
homeassistant/components/apcupsd.py
|
||||||
|
|
|
@ -26,6 +26,7 @@ from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
event_decorators, service, config_per_platform, extract_domain_configs)
|
event_decorators, service, config_per_platform, extract_domain_configs)
|
||||||
|
from homeassistant.helpers.signal import async_register_signal_handling
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -435,6 +436,7 @@ def async_from_config_dict(config: Dict[str, Any],
|
||||||
|
|
||||||
yield from hass.async_stop_track_tasks()
|
yield from hass.async_stop_track_tasks()
|
||||||
|
|
||||||
|
async_register_signal_handling(hass)
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import enum
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import signal
|
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ from homeassistant.const import (
|
||||||
ATTR_SERVICE_CALL_ID, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE,
|
ATTR_SERVICE_CALL_ID, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE,
|
||||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||||
EVENT_SERVICE_EXECUTED, EVENT_SERVICE_REGISTERED, EVENT_STATE_CHANGED,
|
EVENT_SERVICE_EXECUTED, EVENT_SERVICE_REGISTERED, EVENT_STATE_CHANGED,
|
||||||
EVENT_TIME_CHANGED, MATCH_ALL, RESTART_EXIT_CODE, __version__)
|
EVENT_TIME_CHANGED, MATCH_ALL, __version__)
|
||||||
from homeassistant.exceptions import (
|
from homeassistant.exceptions import (
|
||||||
HomeAssistantError, InvalidEntityFormatError, ShuttingDown)
|
HomeAssistantError, InvalidEntityFormatError, ShuttingDown)
|
||||||
from homeassistant.util.async import (
|
from homeassistant.util.async import (
|
||||||
|
@ -150,24 +149,6 @@ class HomeAssistant(object):
|
||||||
_LOGGER.info("Starting Home Assistant")
|
_LOGGER.info("Starting Home Assistant")
|
||||||
self.state = CoreState.starting
|
self.state = CoreState.starting
|
||||||
|
|
||||||
# Setup signal handling
|
|
||||||
if sys.platform != 'win32':
|
|
||||||
def _async_signal_handle(exit_code):
|
|
||||||
"""Wrap signal handling."""
|
|
||||||
self.async_add_job(self.async_stop(exit_code))
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.loop.add_signal_handler(
|
|
||||||
signal.SIGTERM, _async_signal_handle, 0)
|
|
||||||
except ValueError:
|
|
||||||
_LOGGER.warning("Could not bind to SIGTERM")
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.loop.add_signal_handler(
|
|
||||||
signal.SIGHUP, _async_signal_handle, RESTART_EXIT_CODE)
|
|
||||||
except ValueError:
|
|
||||||
_LOGGER.warning("Could not bind to SIGHUP")
|
|
||||||
|
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
self.loop._thread_ident = threading.get_ident()
|
self.loop._thread_ident = threading.get_ident()
|
||||||
_async_create_timer(self)
|
_async_create_timer(self)
|
||||||
|
|
31
homeassistant/helpers/signal.py
Normal file
31
homeassistant/helpers/signal.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
"""Signal handling related helpers."""
|
||||||
|
import logging
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.const import RESTART_EXIT_CODE
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_register_signal_handling(hass):
|
||||||
|
"""Register system signal handler for core."""
|
||||||
|
if sys.platform != 'win32':
|
||||||
|
@callback
|
||||||
|
def async_signal_handle(exit_code):
|
||||||
|
"""Wrap signal handling."""
|
||||||
|
hass.async_add_job(hass.async_stop(exit_code))
|
||||||
|
|
||||||
|
try:
|
||||||
|
hass.loop.add_signal_handler(
|
||||||
|
signal.SIGTERM, async_signal_handle, 0)
|
||||||
|
except ValueError:
|
||||||
|
_LOGGER.warning("Could not bind to SIGTERM")
|
||||||
|
|
||||||
|
try:
|
||||||
|
hass.loop.add_signal_handler(
|
||||||
|
signal.SIGHUP, async_signal_handle, RESTART_EXIT_CODE)
|
||||||
|
except ValueError:
|
||||||
|
_LOGGER.warning("Could not bind to SIGHUP")
|
|
@ -108,8 +108,7 @@ def async_test_home_assistant(loop):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def mock_async_start():
|
def mock_async_start():
|
||||||
"""Start the mocking."""
|
"""Start the mocking."""
|
||||||
with patch.object(loop, 'add_signal_handler'), \
|
with patch('homeassistant.core._async_create_timer'):
|
||||||
patch('homeassistant.core._async_create_timer'):
|
|
||||||
yield from orig_start()
|
yield from orig_start()
|
||||||
|
|
||||||
hass.async_start = mock_async_start
|
hass.async_start = mock_async_start
|
||||||
|
|
|
@ -155,7 +155,8 @@ class TestHelpersDiscovery:
|
||||||
assert 'test_component' in self.hass.config.components
|
assert 'test_component' in self.hass.config.components
|
||||||
assert 'switch' in self.hass.config.components
|
assert 'switch' in self.hass.config.components
|
||||||
|
|
||||||
def test_1st_discovers_2nd_component(self):
|
@patch('homeassistant.bootstrap.async_register_signal_handling')
|
||||||
|
def test_1st_discovers_2nd_component(self, mock_signal):
|
||||||
"""Test that we don't break if one component discovers the other.
|
"""Test that we don't break if one component discovers the other.
|
||||||
|
|
||||||
If the first component fires a discovery event to setup the
|
If the first component fires a discovery event to setup the
|
||||||
|
|
|
@ -58,7 +58,8 @@ class TestBootstrap:
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||||
autospec=True, return_value=None)
|
autospec=True, return_value=None)
|
||||||
def test_from_config_file(self, mock_upgrade, mock_detect):
|
@mock.patch('homeassistant.helpers.signal.async_register_signal_handling')
|
||||||
|
def test_from_config_file(self, mock_upgrade, mock_detect, mock_signal):
|
||||||
"""Test with configuration file."""
|
"""Test with configuration file."""
|
||||||
components = ['browser', 'conversation', 'script']
|
components = ['browser', 'conversation', 'script']
|
||||||
files = {
|
files = {
|
||||||
|
@ -289,7 +290,8 @@ class TestBootstrap:
|
||||||
assert 'comp' not in self.hass.config.components
|
assert 'comp' not in self.hass.config.components
|
||||||
|
|
||||||
@mock.patch('homeassistant.bootstrap.enable_logging')
|
@mock.patch('homeassistant.bootstrap.enable_logging')
|
||||||
def test_home_assistant_core_config_validation(self, log_mock):
|
@mock.patch('homeassistant.helpers.signal.async_register_signal_handling')
|
||||||
|
def test_home_assistant_core_config_validation(self, log_mock, sig_mock):
|
||||||
"""Test if we pass in wrong information for HA conf."""
|
"""Test if we pass in wrong information for HA conf."""
|
||||||
# Extensive HA conf validation testing is done in test_config.py
|
# Extensive HA conf validation testing is done in test_config.py
|
||||||
assert None is bootstrap.from_config_dict({
|
assert None is bootstrap.from_config_dict({
|
||||||
|
@ -393,7 +395,8 @@ class TestBootstrap:
|
||||||
assert loader.get_component('disabled_component') is not None
|
assert loader.get_component('disabled_component') is not None
|
||||||
assert 'disabled_component' in self.hass.config.components
|
assert 'disabled_component' in self.hass.config.components
|
||||||
|
|
||||||
def test_all_work_done_before_start(self):
|
@mock.patch('homeassistant.bootstrap.async_register_signal_handling')
|
||||||
|
def test_all_work_done_before_start(self, signal_mock):
|
||||||
"""Test all init work done till start."""
|
"""Test all init work done till start."""
|
||||||
call_order = []
|
call_order = []
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue