Limit dependencies of HA core (#2762)

This commit is contained in:
Paulus Schoutsen 2016-08-08 20:21:40 -07:00 committed by GitHub
parent 915b9cb3eb
commit 640a8b5a7f
13 changed files with 53 additions and 62 deletions

View file

@ -11,7 +11,6 @@ import itertools as it
import logging import logging
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.helpers.entity import split_entity_id
from homeassistant.helpers.service import extract_entity_ids from homeassistant.helpers.service import extract_entity_ids
from homeassistant.loader import get_component from homeassistant.loader import get_component
from homeassistant.const import ( from homeassistant.const import (
@ -35,7 +34,7 @@ def is_on(hass, entity_id=None):
entity_ids = hass.states.entity_ids() entity_ids = hass.states.entity_ids()
for entity_id in entity_ids: for entity_id in entity_ids:
domain = split_entity_id(entity_id)[0] domain = ha.split_entity_id(entity_id)[0]
module = get_component(domain) module = get_component(domain)
@ -95,7 +94,7 @@ def setup(hass, config):
# Group entity_ids by domain. groupby requires sorted data. # Group entity_ids by domain. groupby requires sorted data.
by_domain = it.groupby(sorted(entity_ids), by_domain = it.groupby(sorted(entity_ids),
lambda item: split_entity_id(item)[0]) lambda item: ha.split_entity_id(item)[0])
for domain, ent_ids in by_domain: for domain, ent_ids in by_domain:
# We want to block for all calls and only return when all calls # We want to block for all calls and only return when all calls

View file

@ -14,8 +14,7 @@ from homeassistant.const import (
ATTR_ENTITY_ID, CONF_ICON, CONF_NAME, STATE_CLOSED, STATE_HOME, ATTR_ENTITY_ID, CONF_ICON, CONF_NAME, STATE_CLOSED, STATE_HOME,
STATE_NOT_HOME, STATE_OFF, STATE_ON, STATE_OPEN, STATE_LOCKED, STATE_NOT_HOME, STATE_OFF, STATE_ON, STATE_OPEN, STATE_LOCKED,
STATE_UNLOCKED, STATE_UNKNOWN, ATTR_ASSUMED_STATE) STATE_UNLOCKED, STATE_UNKNOWN, ATTR_ASSUMED_STATE)
from homeassistant.helpers.entity import ( from homeassistant.helpers.entity import Entity, generate_entity_id
Entity, generate_entity_id, split_entity_id)
from homeassistant.helpers.event import track_state_change from homeassistant.helpers.event import track_state_change
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -101,7 +100,7 @@ def expand_entity_ids(hass, entity_ids):
try: try:
# If entity_id points at a group, expand it # If entity_id points at a group, expand it
domain, _ = split_entity_id(entity_id) domain, _ = ha.split_entity_id(entity_id)
if domain == DOMAIN: if domain == DOMAIN:
found_ids.extend( found_ids.extend(

View file

@ -20,7 +20,7 @@ from homeassistant.const import (
HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
HTTP_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, ALLOWED_CORS_HEADERS, HTTP_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, ALLOWED_CORS_HEADERS,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_START) EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_START)
from homeassistant.helpers.entity import split_entity_id from homeassistant.core import split_entity_id
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv

View file

@ -18,10 +18,8 @@ from homeassistant.components.http import HomeAssistantView
from homeassistant.const import (EVENT_HOMEASSISTANT_START, from homeassistant.const import (EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED, EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED,
STATE_NOT_HOME, STATE_OFF, STATE_ON) STATE_NOT_HOME, STATE_OFF, STATE_ON)
from homeassistant.core import DOMAIN as HA_DOMAIN from homeassistant.core import State, split_entity_id, DOMAIN as HA_DOMAIN
from homeassistant.core import State
from homeassistant.helpers import template from homeassistant.helpers import template
from homeassistant.helpers.entity import split_entity_id
DOMAIN = "logbook" DOMAIN = "logbook"
DEPENDENCIES = ['recorder', 'frontend'] DEPENDENCIES = ['recorder', 'frontend']

View file

@ -9,9 +9,8 @@ from sqlalchemy import (Boolean, Column, DateTime, ForeignKey, Index, Integer,
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.core import Event, EventOrigin, State from homeassistant.core import Event, EventOrigin, State, split_entity_id
from homeassistant.remote import JSONEncoder from homeassistant.remote import JSONEncoder
from homeassistant.helpers.entity import split_entity_id
# SQLAlchemy Schema # SQLAlchemy Schema
# pylint: disable=invalid-name # pylint: disable=invalid-name

View file

@ -14,7 +14,8 @@ import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON,
SERVICE_TOGGLE, STATE_ON, CONF_ALIAS) SERVICE_TOGGLE, STATE_ON, CONF_ALIAS)
from homeassistant.helpers.entity import ToggleEntity, split_entity_id from homeassistant.core import split_entity_id
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv

View file

@ -14,11 +14,12 @@ from homeassistant.const import (
CONF_TIME_ZONE, CONF_CUSTOMIZE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC, CONF_TIME_ZONE, CONF_CUSTOMIZE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS, CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
__version__) __version__)
from homeassistant.core import valid_entity_id
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.util.yaml import load_yaml from homeassistant.util.yaml import load_yaml
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.unit_system import (IMPERIAL_SYSTEM, METRIC_SYSTEM) from homeassistant.helpers.unit_system import (IMPERIAL_SYSTEM, METRIC_SYSTEM)
from homeassistant.helpers.entity import valid_entity_id, set_customize from homeassistant.helpers.entity import set_customize
from homeassistant.util import dt as date_util, location as loc_util from homeassistant.util import dt as date_util, location as loc_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View file

@ -9,22 +9,17 @@ import enum
import functools as ft import functools as ft
import logging import logging
import os import os
import re
import signal import signal
import threading import threading
import time import time
from types import MappingProxyType from types import MappingProxyType
# pylint: disable=unused-import # pylint: disable=unused-import
from typing import Optional, Any, Callable # NOQA from typing import Optional, Any, Callable, List # NOQA
import voluptuous as vol import voluptuous as vol
from homeassistant.helpers.typing import UnitSystemType # NOQA
import homeassistant.util as util
import homeassistant.util.dt as dt_util
import homeassistant.util.location as location
from homeassistant.config import get_default_config_dir
from homeassistant.const import ( from homeassistant.const import (
ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, ATTR_SERVICE, ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, ATTR_SERVICE,
ATTR_SERVICE_CALL_ID, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE, ATTR_SERVICE_CALL_ID, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE,
@ -34,10 +29,11 @@ from homeassistant.const import (
SERVICE_HOMEASSISTANT_RESTART, SERVICE_HOMEASSISTANT_STOP, __version__) SERVICE_HOMEASSISTANT_RESTART, SERVICE_HOMEASSISTANT_STOP, __version__)
from homeassistant.exceptions import ( from homeassistant.exceptions import (
HomeAssistantError, InvalidEntityFormatError) HomeAssistantError, InvalidEntityFormatError)
from homeassistant.helpers.entity import split_entity_id, valid_entity_id from homeassistant.helpers.typing import UnitSystemType # NOQA
from homeassistant.helpers.unit_system import ( from homeassistant.helpers.unit_system import METRIC_SYSTEM
METRIC_SYSTEM, import homeassistant.util as util
) import homeassistant.util.dt as dt_util
import homeassistant.util.location as location
DOMAIN = "homeassistant" DOMAIN = "homeassistant"
@ -52,9 +48,22 @@ SERVICE_CALL_LIMIT = 10 # seconds
# will be added for each component that polls devices. # will be added for each component that polls devices.
MIN_WORKER_THREAD = 2 MIN_WORKER_THREAD = 2
# Pattern for validating entity IDs (format: <domain>.<entity>)
ENTITY_ID_PATTERN = re.compile(r"^(\w+)\.(\w+)$")
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
def split_entity_id(entity_id: str) -> List[str]:
"""Split a state entity_id into domain, object_id."""
return entity_id.split(".", 1)
def valid_entity_id(entity_id: str) -> bool:
"""Test if an entity ID is a valid format."""
return ENTITY_ID_PATTERN.match(entity_id) is not None
class CoreState(enum.Enum): class CoreState(enum.Enum):
"""Represent the current state of Home Assistant.""" """Represent the current state of Home Assistant."""
@ -734,7 +743,7 @@ class Config(object):
self.api = None self.api = None
# Directory that holds the configuration # Directory that holds the configuration
self.config_dir = get_default_config_dir() self.config_dir = None
def distance(self: object, lat: float, lon: float) -> float: def distance(self: object, lat: float, lon: float) -> float:
"""Calculate distance from Home Assistant.""" """Calculate distance from Home Assistant."""
@ -743,6 +752,8 @@ class Config(object):
def path(self, *path): def path(self, *path):
"""Generate path to the file within the config dir.""" """Generate path to the file within the config dir."""
if self.config_dir is None:
raise HomeAssistantError("config_dir is not set")
return os.path.join(self.config_dir, *path) return os.path.join(self.config_dir, *path)
def as_dict(self): def as_dict(self):

View file

@ -12,7 +12,7 @@ from homeassistant.const import (
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS, CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, SUN_EVENT_SUNSET, CONF_CONDITION, CONF_BELOW, CONF_ABOVE, SUN_EVENT_SUNSET,
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC) SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC)
from homeassistant.helpers.entity import valid_entity_id from homeassistant.core import valid_entity_id
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.util import slugify from homeassistant.util import slugify

View file

@ -1,6 +1,5 @@
"""An abstract class for entities.""" """An abstract class for entities."""
import logging import logging
import re
from typing import Any, Optional, List, Dict from typing import Any, Optional, List, Dict
@ -19,9 +18,6 @@ _OVERWRITE = {} # type: Dict[str, Any]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# Pattern for validating entity IDs (format: <domain>.<entity>)
ENTITY_ID_PATTERN = re.compile(r"^(\w+)\.(\w+)$")
def generate_entity_id(entity_id_format: str, name: Optional[str], def generate_entity_id(entity_id_format: str, name: Optional[str],
current_ids: Optional[List[str]]=None, current_ids: Optional[List[str]]=None,
@ -45,16 +41,6 @@ def set_customize(customize: Dict[str, Any]) -> None:
_OVERWRITE = {key.lower(): val for key, val in customize.items()} _OVERWRITE = {key.lower(): val for key, val in customize.items()}
def split_entity_id(entity_id: str) -> List[str]:
"""Split a state entity_id into domain, object_id."""
return entity_id.split(".", 1)
def valid_entity_id(entity_id: str) -> bool:
"""Test if an entity ID is a valid format."""
return ENTITY_ID_PATTERN.match(entity_id) is not None
class Entity(object): class Entity(object):
"""An abstract class for Home Assistant entities.""" """An abstract class for Home Assistant entities."""

View file

@ -37,11 +37,6 @@ class TestHelpersEntity(unittest.TestCase):
state = self.hass.states.get(self.entity.entity_id) state = self.hass.states.get(self.entity.entity_id)
self.assertTrue(state.attributes.get(ATTR_HIDDEN)) self.assertTrue(state.attributes.get(ATTR_HIDDEN))
def test_split_entity_id(self):
"""Test split_entity_id."""
self.assertEqual(['domain', 'object_id'],
entity.split_entity_id('domain.object_id'))
def test_generate_entity_id_requires_hass_or_ids(self): def test_generate_entity_id_requires_hass_or_ids(self):
"""Ensure we require at least hass or current ids.""" """Ensure we require at least hass or current ids."""
fmt = 'test.{}' fmt = 'test.{}'

View file

@ -25,6 +25,15 @@ from tests.common import get_test_home_assistant
PST = pytz.timezone('America/Los_Angeles') PST = pytz.timezone('America/Los_Angeles')
class TestMethods(unittest.TestCase):
"""Test the Home Assistant helper methods."""
def test_split_entity_id(self):
"""Test split_entity_id."""
self.assertEqual(['domain', 'object_id'],
ha.split_entity_id('domain.object_id'))
class TestHomeAssistant(unittest.TestCase): class TestHomeAssistant(unittest.TestCase):
"""Test the Home Assistant core classes.""" """Test the Home Assistant core classes."""
@ -442,27 +451,18 @@ class TestConfig(unittest.TestCase):
def setUp(self): # pylint: disable=invalid-name def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started.""" """Setup things to be run when tests are started."""
self.config = ha.Config() self.config = ha.Config()
self.assertIsNone(self.config.config_dir)
def test_config_dir_set_correct(self):
"""Test config dir set correct."""
data_dir = os.getenv('APPDATA') if os.name == "nt" \
else os.path.expanduser('~')
self.assertEqual(os.path.join(data_dir, ".homeassistant"),
self.config.config_dir)
def test_path_with_file(self): def test_path_with_file(self):
"""Test get_config_path method.""" """Test get_config_path method."""
data_dir = os.getenv('APPDATA') if os.name == "nt" \ self.config.config_dir = '/tmp/ha-config'
else os.path.expanduser('~') self.assertEqual("/tmp/ha-config/test.conf",
self.assertEqual(os.path.join(data_dir, ".homeassistant", "test.conf"),
self.config.path("test.conf")) self.config.path("test.conf"))
def test_path_with_dir_and_file(self): def test_path_with_dir_and_file(self):
"""Test get_config_path method.""" """Test get_config_path method."""
data_dir = os.getenv('APPDATA') if os.name == "nt" \ self.config.config_dir = '/tmp/ha-config'
else os.path.expanduser('~') self.assertEqual("/tmp/ha-config/dir/test.conf",
self.assertEqual(
os.path.join(data_dir, ".homeassistant", "dir", "test.conf"),
self.config.path("dir", "test.conf")) self.config.path("dir", "test.conf"))
def test_as_dict(self): def test_as_dict(self):

View file

@ -10,7 +10,8 @@ import homeassistant.components.http as http
from homeassistant.const import HTTP_HEADER_HA_AUTH, EVENT_STATE_CHANGED from homeassistant.const import HTTP_HEADER_HA_AUTH, EVENT_STATE_CHANGED
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import get_test_instance_port, get_test_home_assistant from tests.common import (
get_test_instance_port, get_test_home_assistant, get_test_config_dir)
API_PASSWORD = "test1234" API_PASSWORD = "test1234"
MASTER_PORT = get_test_instance_port() MASTER_PORT = get_test_instance_port()
@ -52,6 +53,7 @@ def setUpModule(): # pylint: disable=invalid-name
# Start slave # Start slave
slave = remote.HomeAssistant(master_api) slave = remote.HomeAssistant(master_api)
slave.config.config_dir = get_test_config_dir()
bootstrap.setup_component( bootstrap.setup_component(
slave, http.DOMAIN, slave, http.DOMAIN,
{http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD, {http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD,