mirror of
https://github.com/home-assistant/core.git
synced 2025-04-27 02:37:50 +00:00
Merge pull request #108 from balloob/chore-improve-config
Refactor config files into separate module
This commit is contained in:
commit
cb7b0d8a4f
@ -15,8 +15,6 @@ import re
|
|||||||
import datetime as dt
|
import datetime as dt
|
||||||
import functools as ft
|
import functools as ft
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||||
SERVICE_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED,
|
SERVICE_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED,
|
||||||
@ -898,41 +896,6 @@ class Config(object):
|
|||||||
# Directory that holds the configuration
|
# Directory that holds the configuration
|
||||||
self.config_dir = os.path.join(os.getcwd(), 'config')
|
self.config_dir = os.path.join(os.getcwd(), 'config')
|
||||||
|
|
||||||
def auto_detect(self):
|
|
||||||
""" Will attempt to detect config of Home Assistant. """
|
|
||||||
# Only detect if location or temp unit missing
|
|
||||||
if None not in (self.latitude, self.longitude, self.temperature_unit):
|
|
||||||
return
|
|
||||||
|
|
||||||
_LOGGER.info('Auto detecting location and temperature unit')
|
|
||||||
|
|
||||||
try:
|
|
||||||
info = requests.get(
|
|
||||||
'https://freegeoip.net/json/', timeout=5).json()
|
|
||||||
except requests.RequestException:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.latitude is None and self.longitude is None:
|
|
||||||
self.latitude = info['latitude']
|
|
||||||
self.longitude = info['longitude']
|
|
||||||
|
|
||||||
if self.temperature_unit is None:
|
|
||||||
# From Wikipedia:
|
|
||||||
# Fahrenheit is used in the Bahamas, Belize, the Cayman Islands,
|
|
||||||
# Palau, and the United States and associated territories of
|
|
||||||
# American Samoa and the U.S. Virgin Islands
|
|
||||||
if info['country_code'] in ('BS', 'BZ', 'KY', 'PW',
|
|
||||||
'US', 'AS', 'VI'):
|
|
||||||
self.temperature_unit = TEMP_FAHRENHEIT
|
|
||||||
else:
|
|
||||||
self.temperature_unit = TEMP_CELCIUS
|
|
||||||
|
|
||||||
if self.location_name is None:
|
|
||||||
self.location_name = info['city']
|
|
||||||
|
|
||||||
if self.time_zone is None:
|
|
||||||
self.time_zone = info['time_zone']
|
|
||||||
|
|
||||||
def path(self, path):
|
def path(self, path):
|
||||||
""" Returns path to the file within the config dir. """
|
""" Returns path to the file within the config dir. """
|
||||||
return os.path.join(self.config_dir, path)
|
return os.path.join(self.config_dir, path)
|
||||||
|
@ -72,24 +72,13 @@ def ensure_config_path(config_dir):
|
|||||||
'directory {} ').format(config_dir))
|
'directory {} ').format(config_dir))
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
# Try to use yaml configuration first
|
import homeassistant.config as config_util
|
||||||
config_path = os.path.join(config_dir, 'configuration.yaml')
|
|
||||||
if not os.path.isfile(config_path):
|
|
||||||
config_path = os.path.join(config_dir, 'home-assistant.conf')
|
|
||||||
|
|
||||||
# Ensure a config file exists to make first time usage easier
|
config_path = config_util.ensure_config_exists(config_dir)
|
||||||
if not os.path.isfile(config_path):
|
|
||||||
config_path = os.path.join(config_dir, 'configuration.yaml')
|
if config_path is None:
|
||||||
try:
|
print('Error getting configuration path')
|
||||||
with open(config_path, 'w') as conf:
|
sys.exit()
|
||||||
conf.write("frontend:\n\n")
|
|
||||||
conf.write("discovery:\n\n")
|
|
||||||
conf.write("history:\n\n")
|
|
||||||
conf.write("logbook:\n\n")
|
|
||||||
except IOError:
|
|
||||||
print(('Fatal Error: No configuration file found and unable '
|
|
||||||
'to write a default one to {}').format(config_path))
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
return config_path
|
return config_path
|
||||||
|
|
||||||
|
@ -10,13 +10,12 @@ start by calling homeassistant.start_home_assistant(bus)
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import configparser
|
|
||||||
import yaml
|
|
||||||
import io
|
|
||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import homeassistant
|
import homeassistant
|
||||||
|
import homeassistant.util as util
|
||||||
|
import homeassistant.config as config_util
|
||||||
import homeassistant.loader as loader
|
import homeassistant.loader as loader
|
||||||
import homeassistant.components as core_components
|
import homeassistant.components as core_components
|
||||||
import homeassistant.components.group as group
|
import homeassistant.components.group as group
|
||||||
@ -148,26 +147,7 @@ def from_config_file(config_path, hass=None):
|
|||||||
# Set config dir to directory holding config file
|
# Set config dir to directory holding config file
|
||||||
hass.config.config_dir = os.path.abspath(os.path.dirname(config_path))
|
hass.config.config_dir = os.path.abspath(os.path.dirname(config_path))
|
||||||
|
|
||||||
config_dict = {}
|
config_dict = config_util.load_config_file(config_path)
|
||||||
# check config file type
|
|
||||||
if os.path.splitext(config_path)[1] == '.yaml':
|
|
||||||
# Read yaml
|
|
||||||
config_dict = yaml.load(io.open(config_path, 'r'))
|
|
||||||
|
|
||||||
# If YAML file was empty
|
|
||||||
if config_dict is None:
|
|
||||||
config_dict = {}
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Read config
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read(config_path)
|
|
||||||
|
|
||||||
for section in config.sections():
|
|
||||||
config_dict[section] = {}
|
|
||||||
|
|
||||||
for key, val in config.items(section):
|
|
||||||
config_dict[section][key] = val
|
|
||||||
|
|
||||||
return from_config_dict(config_dict, hass)
|
return from_config_dict(config_dict, hass)
|
||||||
|
|
||||||
@ -201,12 +181,14 @@ def enable_logging(hass):
|
|||||||
|
|
||||||
def process_ha_core_config(hass, config):
|
def process_ha_core_config(hass, config):
|
||||||
""" Processes the [homeassistant] section from the config. """
|
""" Processes the [homeassistant] section from the config. """
|
||||||
|
hac = hass.config
|
||||||
|
|
||||||
for key, attr in ((CONF_LATITUDE, 'latitude'),
|
for key, attr in ((CONF_LATITUDE, 'latitude'),
|
||||||
(CONF_LONGITUDE, 'longitude'),
|
(CONF_LONGITUDE, 'longitude'),
|
||||||
(CONF_NAME, 'location_name'),
|
(CONF_NAME, 'location_name'),
|
||||||
(CONF_TIME_ZONE, 'time_zone')):
|
(CONF_TIME_ZONE, 'time_zone')):
|
||||||
if key in config:
|
if key in config:
|
||||||
setattr(hass.config, attr, config[key])
|
setattr(hac, attr, config[key])
|
||||||
|
|
||||||
for entity_id, attrs in config.get(CONF_CUSTOMIZE, {}).items():
|
for entity_id, attrs in config.get(CONF_CUSTOMIZE, {}).items():
|
||||||
Entity.overwrite_attribute(entity_id, attrs.keys(), attrs.values())
|
Entity.overwrite_attribute(entity_id, attrs.keys(), attrs.values())
|
||||||
@ -215,11 +197,37 @@ def process_ha_core_config(hass, config):
|
|||||||
unit = config[CONF_TEMPERATURE_UNIT]
|
unit = config[CONF_TEMPERATURE_UNIT]
|
||||||
|
|
||||||
if unit == 'C':
|
if unit == 'C':
|
||||||
hass.config.temperature_unit = TEMP_CELCIUS
|
hac.temperature_unit = TEMP_CELCIUS
|
||||||
elif unit == 'F':
|
elif unit == 'F':
|
||||||
hass.config.temperature_unit = TEMP_FAHRENHEIT
|
hac.temperature_unit = TEMP_FAHRENHEIT
|
||||||
|
|
||||||
hass.config.auto_detect()
|
# If we miss some of the needed values, auto detect them
|
||||||
|
if None not in (hac.latitude, hac.longitude, hac.temperature_unit):
|
||||||
|
return
|
||||||
|
|
||||||
|
_LOGGER.info('Auto detecting location and temperature unit')
|
||||||
|
|
||||||
|
info = util.detect_location_info()
|
||||||
|
|
||||||
|
if info is None:
|
||||||
|
_LOGGER.error('Could not detect location information')
|
||||||
|
return
|
||||||
|
|
||||||
|
if hac.latitude is None and hac.longitude is None:
|
||||||
|
hac.latitude = info.latitude
|
||||||
|
hac.longitude = info.longitude
|
||||||
|
|
||||||
|
if hac.temperature_unit is None:
|
||||||
|
if info.use_fahrenheit:
|
||||||
|
hac.temperature_unit = TEMP_FAHRENHEIT
|
||||||
|
else:
|
||||||
|
hac.temperature_unit = TEMP_CELCIUS
|
||||||
|
|
||||||
|
if hac.location_name is None:
|
||||||
|
hac.location_name = info.city
|
||||||
|
|
||||||
|
if hac.time_zone is None:
|
||||||
|
hac.time_zone = info.time_zone
|
||||||
|
|
||||||
|
|
||||||
def _ensure_loader_prepared(hass):
|
def _ensure_loader_prepared(hass):
|
||||||
|
140
homeassistant/config.py
Normal file
140
homeassistant/config.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
"""
|
||||||
|
homeassistant.config
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Module to help with parsing and generating configuration files.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from homeassistant import HomeAssistantError
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONF_LATITUDE, CONF_LONGITUDE, CONF_TEMPERATURE_UNIT, CONF_NAME,
|
||||||
|
CONF_TIME_ZONE)
|
||||||
|
import homeassistant.util as util
|
||||||
|
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
YAML_CONFIG_FILE = 'configuration.yaml'
|
||||||
|
CONF_CONFIG_FILE = 'home-assistant.conf'
|
||||||
|
DEFAULT_COMPONENTS = [
|
||||||
|
'discovery', 'frontend', 'conversation', 'history', 'logbook']
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_config_exists(config_dir, detect_location=True):
|
||||||
|
""" Ensures a config file exists in given config dir.
|
||||||
|
Creating a default one if needed.
|
||||||
|
Returns path to the config file. """
|
||||||
|
config_path = find_config_file(config_dir)
|
||||||
|
|
||||||
|
if config_path is None:
|
||||||
|
_LOGGER.info("Unable to find configuration. Creating default one")
|
||||||
|
config_path = create_default_config(config_dir, detect_location)
|
||||||
|
|
||||||
|
return config_path
|
||||||
|
|
||||||
|
|
||||||
|
def create_default_config(config_dir, detect_location=True):
|
||||||
|
""" Creates a default configuration file in given config dir.
|
||||||
|
Returns path to new config file if success, None if failed. """
|
||||||
|
config_path = os.path.join(config_dir, YAML_CONFIG_FILE)
|
||||||
|
|
||||||
|
# Writing files with YAML does not create the most human readable results
|
||||||
|
# So we're hard coding a YAML template.
|
||||||
|
try:
|
||||||
|
with open(config_path, 'w') as config_file:
|
||||||
|
location_info = detect_location and util.detect_location_info()
|
||||||
|
|
||||||
|
if location_info:
|
||||||
|
temp_unit = 'F' if location_info.use_fahrenheit else 'C'
|
||||||
|
|
||||||
|
auto_config = {
|
||||||
|
CONF_NAME: 'Home',
|
||||||
|
CONF_LATITUDE: location_info.latitude,
|
||||||
|
CONF_LONGITUDE: location_info.longitude,
|
||||||
|
CONF_TEMPERATURE_UNIT: temp_unit,
|
||||||
|
CONF_TIME_ZONE: location_info.time_zone,
|
||||||
|
}
|
||||||
|
|
||||||
|
config_file.write("homeassistant:\n")
|
||||||
|
|
||||||
|
for key, value in auto_config.items():
|
||||||
|
config_file.write(" {}: {}\n".format(key, value))
|
||||||
|
|
||||||
|
config_file.write("\n")
|
||||||
|
|
||||||
|
for component in DEFAULT_COMPONENTS:
|
||||||
|
config_file.write("{}:\n\n".format(component))
|
||||||
|
|
||||||
|
return config_path
|
||||||
|
|
||||||
|
except IOError:
|
||||||
|
_LOGGER.exception(
|
||||||
|
'Unable to write default configuration file %s', config_path)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def find_config_file(config_dir):
|
||||||
|
""" Looks in given directory for supported config files. """
|
||||||
|
for filename in (YAML_CONFIG_FILE, CONF_CONFIG_FILE):
|
||||||
|
config_path = os.path.join(config_dir, filename)
|
||||||
|
|
||||||
|
if os.path.isfile(config_path):
|
||||||
|
return config_path
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def load_config_file(config_path):
|
||||||
|
""" Loads given config file. """
|
||||||
|
config_ext = os.path.splitext(config_path)[1]
|
||||||
|
|
||||||
|
if config_ext == '.yaml':
|
||||||
|
return load_yaml_config_file(config_path)
|
||||||
|
|
||||||
|
elif config_ext == '.conf':
|
||||||
|
return load_conf_config_file(config_path)
|
||||||
|
|
||||||
|
|
||||||
|
def load_yaml_config_file(config_path):
|
||||||
|
""" Parse a YAML configuration file. """
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_path) as conf_file:
|
||||||
|
# If configuration file is empty YAML returns None
|
||||||
|
# We convert that to an empty dict
|
||||||
|
conf_dict = yaml.load(conf_file) or {}
|
||||||
|
|
||||||
|
except yaml.YAMLError:
|
||||||
|
_LOGGER.exception('Error reading YAML configuration file')
|
||||||
|
raise HomeAssistantError()
|
||||||
|
|
||||||
|
if not isinstance(conf_dict, dict):
|
||||||
|
_LOGGER.error(
|
||||||
|
'The configuration file %s does not contain a dictionary',
|
||||||
|
os.path.basename(config_path))
|
||||||
|
raise HomeAssistantError()
|
||||||
|
|
||||||
|
return conf_dict
|
||||||
|
|
||||||
|
|
||||||
|
def load_conf_config_file(config_path):
|
||||||
|
""" Parse the old style conf configuration. """
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
config_dict = {}
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(config_path)
|
||||||
|
|
||||||
|
for section in config.sections():
|
||||||
|
config_dict[section] = {}
|
||||||
|
|
||||||
|
for key, val in config.items(section):
|
||||||
|
config_dict[section][key] = val
|
||||||
|
|
||||||
|
return config_dict
|
@ -16,6 +16,8 @@ import random
|
|||||||
import string
|
import string
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
RE_SANITIZE_FILENAME = re.compile(r'(~|\.\.|/|\\)')
|
RE_SANITIZE_FILENAME = re.compile(r'(~|\.\.|/|\\)')
|
||||||
RE_SANITIZE_PATH = re.compile(r'(~|\.(\.)+)')
|
RE_SANITIZE_PATH = re.compile(r'(~|\.(\.)+)')
|
||||||
RE_SLUGIFY = re.compile(r'[^A-Za-z0-9_]+')
|
RE_SLUGIFY = re.compile(r'[^A-Za-z0-9_]+')
|
||||||
@ -174,6 +176,32 @@ def get_random_string(length=10):
|
|||||||
return ''.join(generator.choice(source_chars) for _ in range(length))
|
return ''.join(generator.choice(source_chars) for _ in range(length))
|
||||||
|
|
||||||
|
|
||||||
|
LocationInfo = collections.namedtuple(
|
||||||
|
"LocationInfo",
|
||||||
|
['ip', 'country_code', 'country_name', 'region_code', 'region_name',
|
||||||
|
'city', 'zip_code', 'time_zone', 'latitude', 'longitude',
|
||||||
|
'use_fahrenheit'])
|
||||||
|
|
||||||
|
|
||||||
|
def detect_location_info():
|
||||||
|
""" Detect location information. """
|
||||||
|
try:
|
||||||
|
raw_info = requests.get(
|
||||||
|
'https://freegeoip.net/json/', timeout=5).json()
|
||||||
|
except requests.RequestException:
|
||||||
|
return
|
||||||
|
|
||||||
|
data = {key: raw_info.get(key) for key in LocationInfo._fields}
|
||||||
|
|
||||||
|
# From Wikipedia: Fahrenheit is used in the Bahamas, Belize,
|
||||||
|
# the Cayman Islands, Palau, and the United States and associated
|
||||||
|
# territories of American Samoa and the U.S. Virgin Islands
|
||||||
|
data['use_fahrenheit'] = data['country_code'] in (
|
||||||
|
'BS', 'BZ', 'KY', 'PW', 'US', 'AS', 'VI')
|
||||||
|
|
||||||
|
return LocationInfo(**data)
|
||||||
|
|
||||||
|
|
||||||
class OrderedEnum(enum.Enum):
|
class OrderedEnum(enum.Enum):
|
||||||
""" Taken from Python 3.4.0 docs. """
|
""" Taken from Python 3.4.0 docs. """
|
||||||
# pylint: disable=no-init, too-few-public-methods
|
# pylint: disable=no-init, too-few-public-methods
|
||||||
|
@ -11,10 +11,15 @@ from homeassistant.helpers.entity import ToggleEntity
|
|||||||
from homeassistant.const import STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME
|
from homeassistant.const import STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME
|
||||||
|
|
||||||
|
|
||||||
|
def get_test_config_dir():
|
||||||
|
""" Returns a path to a test config dir. """
|
||||||
|
return os.path.join(os.path.dirname(__file__), "config")
|
||||||
|
|
||||||
|
|
||||||
def get_test_home_assistant():
|
def get_test_home_assistant():
|
||||||
""" Returns a Home Assistant object pointing at test config dir. """
|
""" Returns a Home Assistant object pointing at test config dir. """
|
||||||
hass = ha.HomeAssistant()
|
hass = ha.HomeAssistant()
|
||||||
hass.config.config_dir = os.path.join(os.path.dirname(__file__), "config")
|
hass.config.config_dir = get_test_config_dir()
|
||||||
|
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
|
180
tests/test_config.py
Normal file
180
tests/test_config.py
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
"""
|
||||||
|
tests.test_config
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Tests config utils.
|
||||||
|
"""
|
||||||
|
# pylint: disable=too-many-public-methods,protected-access
|
||||||
|
import unittest
|
||||||
|
import unittest.mock as mock
|
||||||
|
import os
|
||||||
|
|
||||||
|
from homeassistant import DOMAIN, HomeAssistantError
|
||||||
|
import homeassistant.util as util
|
||||||
|
import homeassistant.config as config_util
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONF_LATITUDE, CONF_LONGITUDE, CONF_TEMPERATURE_UNIT, CONF_NAME,
|
||||||
|
CONF_TIME_ZONE)
|
||||||
|
|
||||||
|
from helpers import get_test_config_dir
|
||||||
|
|
||||||
|
CONFIG_DIR = get_test_config_dir()
|
||||||
|
YAML_PATH = os.path.join(CONFIG_DIR, config_util.YAML_CONFIG_FILE)
|
||||||
|
CONF_PATH = os.path.join(CONFIG_DIR, config_util.CONF_CONFIG_FILE)
|
||||||
|
|
||||||
|
|
||||||
|
def create_file(path):
|
||||||
|
""" Creates an empty file. """
|
||||||
|
with open(path, 'w'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def mock_detect_location_info():
|
||||||
|
""" Mock implementation of util.detect_location_info. """
|
||||||
|
return util.LocationInfo(
|
||||||
|
ip='1.1.1.1',
|
||||||
|
country_code='US',
|
||||||
|
country_name='United States',
|
||||||
|
region_code='CA',
|
||||||
|
region_name='California',
|
||||||
|
city='San Diego',
|
||||||
|
zip_code='92122',
|
||||||
|
time_zone='America/Los_Angeles',
|
||||||
|
latitude='2.0',
|
||||||
|
longitude='1.0',
|
||||||
|
use_fahrenheit=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfig(unittest.TestCase):
|
||||||
|
""" Test the config utils. """
|
||||||
|
|
||||||
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
|
""" Clean up. """
|
||||||
|
for path in (YAML_PATH, CONF_PATH):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
def test_create_default_config(self):
|
||||||
|
""" Test creationg of default config. """
|
||||||
|
|
||||||
|
config_util.create_default_config(CONFIG_DIR, False)
|
||||||
|
|
||||||
|
self.assertTrue(os.path.isfile(YAML_PATH))
|
||||||
|
|
||||||
|
def test_find_config_file_yaml(self):
|
||||||
|
""" Test if it finds a YAML config file. """
|
||||||
|
|
||||||
|
create_file(YAML_PATH)
|
||||||
|
|
||||||
|
self.assertEqual(YAML_PATH, config_util.find_config_file(CONFIG_DIR))
|
||||||
|
|
||||||
|
def test_find_config_file_conf(self):
|
||||||
|
""" Test if it finds the old CONF config file. """
|
||||||
|
|
||||||
|
create_file(CONF_PATH)
|
||||||
|
|
||||||
|
self.assertEqual(CONF_PATH, config_util.find_config_file(CONFIG_DIR))
|
||||||
|
|
||||||
|
def test_find_config_file_prefers_yaml_over_conf(self):
|
||||||
|
""" Test if find config prefers YAML over CONF if both exist. """
|
||||||
|
|
||||||
|
create_file(YAML_PATH)
|
||||||
|
create_file(CONF_PATH)
|
||||||
|
|
||||||
|
self.assertEqual(YAML_PATH, config_util.find_config_file(CONFIG_DIR))
|
||||||
|
|
||||||
|
def test_ensure_config_exists_creates_config(self):
|
||||||
|
""" Test that calling ensure_config_exists creates a new config file if
|
||||||
|
none exists. """
|
||||||
|
|
||||||
|
config_util.ensure_config_exists(CONFIG_DIR, False)
|
||||||
|
|
||||||
|
self.assertTrue(os.path.isfile(YAML_PATH))
|
||||||
|
|
||||||
|
def test_ensure_config_exists_uses_existing_config(self):
|
||||||
|
""" Test that calling ensure_config_exists uses existing config. """
|
||||||
|
|
||||||
|
create_file(YAML_PATH)
|
||||||
|
config_util.ensure_config_exists(CONFIG_DIR, False)
|
||||||
|
|
||||||
|
with open(YAML_PATH) as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# File created with create_file are empty
|
||||||
|
self.assertEqual('', content)
|
||||||
|
|
||||||
|
def test_load_yaml_config_converts_empty_files_to_dict(self):
|
||||||
|
""" Test that loading an empty file returns an empty dict. """
|
||||||
|
create_file(YAML_PATH)
|
||||||
|
|
||||||
|
self.assertIsInstance(
|
||||||
|
config_util.load_yaml_config_file(YAML_PATH), dict)
|
||||||
|
|
||||||
|
def test_load_yaml_config_raises_error_if_not_dict(self):
|
||||||
|
""" Test error raised when YAML file is not a dict. """
|
||||||
|
with open(YAML_PATH, 'w') as f:
|
||||||
|
f.write('5')
|
||||||
|
|
||||||
|
with self.assertRaises(HomeAssistantError):
|
||||||
|
config_util.load_yaml_config_file(YAML_PATH)
|
||||||
|
|
||||||
|
def test_load_yaml_config_raises_error_if_malformed_yaml(self):
|
||||||
|
""" Test error raised if invalid YAML. """
|
||||||
|
with open(YAML_PATH, 'w') as f:
|
||||||
|
f.write(':')
|
||||||
|
|
||||||
|
with self.assertRaises(HomeAssistantError):
|
||||||
|
config_util.load_yaml_config_file(YAML_PATH)
|
||||||
|
|
||||||
|
def test_load_config_loads_yaml_config(self):
|
||||||
|
""" Test correct YAML config loading. """
|
||||||
|
with open(YAML_PATH, 'w') as f:
|
||||||
|
f.write('hello: world')
|
||||||
|
|
||||||
|
self.assertEqual({'hello': 'world'},
|
||||||
|
config_util.load_config_file(YAML_PATH))
|
||||||
|
|
||||||
|
def test_load_config_loads_conf_config(self):
|
||||||
|
""" Test correct YAML config loading. """
|
||||||
|
create_file(CONF_PATH)
|
||||||
|
|
||||||
|
self.assertEqual({}, config_util.load_config_file(CONF_PATH))
|
||||||
|
|
||||||
|
def test_conf_config_file(self):
|
||||||
|
""" Test correct CONF config loading. """
|
||||||
|
with open(CONF_PATH, 'w') as f:
|
||||||
|
f.write('[ha]\ntime_zone=America/Los_Angeles')
|
||||||
|
|
||||||
|
self.assertEqual({'ha': {'time_zone': 'America/Los_Angeles'}},
|
||||||
|
config_util.load_conf_config_file(CONF_PATH))
|
||||||
|
|
||||||
|
def test_create_default_config_detect_location(self):
|
||||||
|
""" Test that detect location sets the correct config keys. """
|
||||||
|
with mock.patch('homeassistant.util.detect_location_info',
|
||||||
|
mock_detect_location_info):
|
||||||
|
config_util.ensure_config_exists(CONFIG_DIR)
|
||||||
|
|
||||||
|
config = config_util.load_config_file(YAML_PATH)
|
||||||
|
|
||||||
|
self.assertIn(DOMAIN, config)
|
||||||
|
|
||||||
|
ha_conf = config[DOMAIN]
|
||||||
|
|
||||||
|
expected_values = {
|
||||||
|
CONF_LATITUDE: 2.0,
|
||||||
|
CONF_LONGITUDE: 1.0,
|
||||||
|
CONF_TEMPERATURE_UNIT: 'F',
|
||||||
|
CONF_NAME: 'Home',
|
||||||
|
CONF_TIME_ZONE: 'America/Los_Angeles'
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(expected_values, ha_conf)
|
||||||
|
|
||||||
|
def test_create_default_config_returns_none_if_write_error(self):
|
||||||
|
"""
|
||||||
|
Test that writing default config to non existing folder returns None.
|
||||||
|
"""
|
||||||
|
self.assertIsNone(
|
||||||
|
config_util.create_default_config(
|
||||||
|
os.path.join(CONFIG_DIR, 'non_existing_dir/'), False))
|
Loading…
x
Reference in New Issue
Block a user