Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ class CoreState(enum.Enum):
"""Represent the current state of Home Assistant."""

not_running = 'NOT_RUNNING'
starting = 'STARTING'
running = 'RUNNING'
stopping = 'STOPPING'

Expand Down Expand Up @@ -134,7 +133,7 @@ def __init__(self, loop=None):
@property
def is_running(self) -> bool:
"""Return if Home Assistant is running."""
return self.state in (CoreState.starting, CoreState.running)
return self.state == CoreState.running

def start(self) -> None:
"""Start home assistant."""
Expand All @@ -159,13 +158,11 @@ def async_start(self):
This method is a coroutine.
"""
_LOGGER.info("Starting Home Assistant")
self.state = CoreState.starting

# pylint: disable=protected-access
self.state = CoreState.running
self.loop._thread_ident = threading.get_ident()
_async_create_timer(self)
self.bus.async_fire(EVENT_HOMEASSISTANT_START)
self.state = CoreState.running

def add_job(self, target: Callable[..., None], *args: Any) -> None:
"""Add job to the executor pool.
Expand Down
23 changes: 12 additions & 11 deletions homeassistant/helpers/restore_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from datetime import timedelta

from homeassistant.core import HomeAssistant, CoreState, callback
from homeassistant.core import HomeAssistant, callback
from homeassistant.const import EVENT_HOMEASSISTANT_START
from homeassistant.components.history import get_states, last_recorder_run
from homeassistant.components.recorder import DOMAIN as _RECORDER
Expand All @@ -21,7 +21,6 @@ def _load_restore_cache(hass: HomeAssistant):
def remove_cache(event):
"""Remove the states cache."""
hass.data.pop(DATA_RESTORE_CACHE, None)

hass.bus.listen_once(EVENT_HOMEASSISTANT_START, remove_cache)

last_run = last_recorder_run()
Expand All @@ -48,14 +47,14 @@ def remove_cache(event):
@asyncio.coroutine
def async_get_last_state(hass, entity_id: str):
"""Helper to restore state."""
if DATA_RESTORE_CACHE in hass.data:
return hass.data[DATA_RESTORE_CACHE].get(entity_id)

if (_RECORDER not in hass.config.components or
hass.state not in (CoreState.starting, CoreState.not_running)):
_LOGGER.error("Cache can only be loaded during startup, not %s",
if _RECORDER not in hass.config.components:
return None
elif hass.is_running:
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enforce that when we're running, we don't restore.

_LOGGER.debug("Cache can only be loaded during startup, not %s",
hass.state)
return None
elif DATA_RESTORE_CACHE in hass.data:
return hass.data[DATA_RESTORE_CACHE].get(entity_id)

if _LOCK not in hass.data:
hass.data[_LOCK] = asyncio.Lock(loop=hass.loop)
Expand All @@ -65,14 +64,16 @@ def async_get_last_state(hass, entity_id: str):
yield from hass.loop.run_in_executor(
None, _load_restore_cache, hass)

return hass.data.get(DATA_RESTORE_CACHE, {}).get(entity_id)
return hass.data[DATA_RESTORE_CACHE].get(entity_id)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All paths ensure _load_restore_cache is set.



@asyncio.coroutine
def async_restore_state(entity, extract_info):
"""Helper to call entity.async_restore_state with cached info."""
if entity.hass.state != CoreState.starting:
_LOGGER.debug("Not restoring state: State is not starting: %s",
if _RECORDER not in entity.hass.config.components:
return
elif entity.hass.is_running:
_LOGGER.debug("Not restoring state: hass is already running: %s",
entity.hass.state)
return

Expand Down
1 change: 0 additions & 1 deletion homeassistant/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ def start(self):
raise HomeAssistantError(
'Unable to setup local API to receive events')

self.state = ha.CoreState.starting
# pylint: disable=protected-access
ha._async_create_timer(self)

Expand Down
4 changes: 1 addition & 3 deletions tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ def async_add_job(target, *args):
if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
yield from loop.run_in_executor(None, loader.prepare, hass)

hass.state = ha.CoreState.running

# Mock async_start
orig_start = hass.async_start

Expand Down Expand Up @@ -237,6 +235,7 @@ def mock_register_view(view):

def mock_http_component_app(hass, api_password=None):
"""Create an aiohttp.web.Application instance for testing."""
hass.state = ha.CoreState.running
if 'http' not in hass.config.components:
mock_http_component(hass, api_password)
app = web.Application(middlewares=[auth_middleware], loop=hass.loop)
Expand Down Expand Up @@ -475,5 +474,4 @@ def mock_restore_cache(hass, states):
_LOGGER.debug('Restore cache: %s', hass.data[DATA_RESTORE_CACHE])
assert len(hass.data[DATA_RESTORE_CACHE]) == len(states), \
"Duplicate entity_id? {}".format(states)
hass.state = ha.CoreState.starting
hass.config.components.add(recorder.DOMAIN)
3 changes: 3 additions & 0 deletions tests/components/camera/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
import asyncio
from unittest import mock

from homeassistant.core import CoreState
from homeassistant.bootstrap import setup_component


@asyncio.coroutine
def test_fetching_url(aioclient_mock, hass, test_client):
"""Test that it fetches the given url."""
hass.state = CoreState.running
aioclient_mock.get('http://example.com', text='hello world')

def setup_platform():
Expand Down Expand Up @@ -39,6 +41,7 @@ def setup_platform():
@asyncio.coroutine
def test_limit_refetch(aioclient_mock, hass, test_client):
"""Test that it fetches the given url."""
hass.state = CoreState.running
aioclient_mock.get('http://example.com/5a', text='hello world')
aioclient_mock.get('http://example.com/10a', text='hello world')
aioclient_mock.get('http://example.com/15a', text='hello planet')
Expand Down
3 changes: 3 additions & 0 deletions tests/components/camera/test_local_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# https://bugs.python.org/issue23004
from mock_open import MockOpen

from homeassistant.core import CoreState
from homeassistant.bootstrap import setup_component

from tests.common import assert_setup_component, mock_http_component
Expand All @@ -14,6 +15,8 @@
@asyncio.coroutine
def test_loading_file(hass, test_client):
"""Test that it loads image from disk."""
hass.state = CoreState.running

@mock.patch('os.path.isfile', mock.Mock(return_value=True))
@mock.patch('os.access', mock.Mock(return_value=True))
def setup_platform():
Expand Down
3 changes: 1 addition & 2 deletions tests/components/light/test_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import asyncio
import unittest

from homeassistant.core import State, CoreState
from homeassistant.core import State
from homeassistant.bootstrap import setup_component, async_setup_component
import homeassistant.components.light as light
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
Expand Down Expand Up @@ -69,7 +69,6 @@ def test_turn_off(self):
def test_restore_state(hass):
"""Test state gets restored."""
hass.config.components.add('recorder')
hass.state = CoreState.starting
hass.data[DATA_RESTORE_CACHE] = {
'light.bed_light': State('light.bed_light', 'on', {
'brightness': 'value-brightness',
Expand Down
3 changes: 1 addition & 2 deletions tests/components/test_input_boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from tests.common import get_test_home_assistant

from homeassistant.core import CoreState, State
from homeassistant.core import State
from homeassistant.bootstrap import setup_component, async_setup_component
from homeassistant.components.input_boolean import (
DOMAIN, is_on, toggle, turn_off, turn_on)
Expand Down Expand Up @@ -117,7 +117,6 @@ def test_restore_state(hass):
'input_boolean.b3': State('input_boolean.b3', 'on'),
}

hass.state = CoreState.starting
hass.config.components.add('recorder')

yield from async_setup_component(hass, DOMAIN, {
Expand Down
3 changes: 2 additions & 1 deletion tests/helpers/test_aiohttp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import aiohttp

from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE
from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE, CoreState
from homeassistant.bootstrap import setup_component
import homeassistant.helpers.aiohttp_client as client
from homeassistant.util.async import run_callback_threadsafe
Expand Down Expand Up @@ -121,6 +121,7 @@ def test_get_clientsession_cleanup_without_ssl(self):
@asyncio.coroutine
def test_fetching_url(aioclient_mock, hass, test_client):
"""Test that it fetches the given url."""
hass.state = CoreState.running
aioclient_mock.get('http://example.com/mjpeg_stream', content=[
b'Frame1', b'Frame2', b'Frame3'
])
Expand Down
4 changes: 1 addition & 3 deletions tests/helpers/test_restore_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from homeassistant.bootstrap import setup_component
from homeassistant.const import EVENT_HOMEASSISTANT_START
from homeassistant.core import CoreState, split_entity_id, State
from homeassistant.core import split_entity_id, State
import homeassistant.util.dt as dt_util
from homeassistant.components import input_boolean, recorder
from homeassistant.helpers.restore_state import (
Expand All @@ -18,7 +18,6 @@
def test_caching_data(hass):
"""Test that we cache data."""
hass.config.components.add('recorder')
hass.state = CoreState.starting

states = [
State('input_boolean.b0', 'on'),
Expand Down Expand Up @@ -81,7 +80,6 @@ def test_filling_the_cache():
test_entity_id2 = 'input_boolean.b2'

hass = get_test_home_assistant()
hass.state = CoreState.starting

init_recorder_component(hass)

Expand Down