Limit dependencies of HA core (#2762)
This commit is contained in:
parent
915b9cb3eb
commit
640a8b5a7f
13 changed files with 53 additions and 62 deletions
|
@ -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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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__)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
||||||
|
|
|
@ -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.{}'
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue