diff --git a/homeassistant/components/config/core.py b/homeassistant/components/config/core.py index 7e9008eb115..31abb832f23 100644 --- a/homeassistant/components/config/core.py +++ b/homeassistant/components/config/core.py @@ -5,12 +5,18 @@ import voluptuous as vol from homeassistant.components.http import HomeAssistantView from homeassistant.config import async_check_ha_config_file from homeassistant.components import websocket_api +from homeassistant.const import ( + CONF_UNIT_SYSTEM_METRIC, CONF_UNIT_SYSTEM_IMPERIAL +) +from homeassistant.helpers import config_validation as cv +from homeassistant.util import location async def async_setup(hass): """Set up the Hassbian config.""" hass.http.register_view(CheckConfigView) - hass.components.websocket_api.async_register_command(websocket_core_update) + websocket_api.async_register_command(hass, websocket_update_config) + websocket_api.async_register_command(hass, websocket_detect_config) return True @@ -35,18 +41,57 @@ class CheckConfigView(HomeAssistantView): @websocket_api.require_admin @websocket_api.async_response @websocket_api.websocket_command({ - vol.Required('type'): 'config/core/update', - vol.Optional('latitude'): vol.Coerce(float), - vol.Optional('longitude'): vol.Coerce(float), - vol.Optional('elevation'): vol.Coerce(int), - vol.Optional('unit_system'): vol.Coerce(str), - vol.Optional('location_name'): vol.Coerce(str), - vol.Optional('time_zone'): vol.Coerce(str), + 'type': 'config/core/update', + vol.Optional('latitude'): cv.latitude, + vol.Optional('longitude'): cv.longitude, + vol.Optional('elevation'): int, + vol.Optional('unit_system'): cv.unit_system, + vol.Optional('location_name'): str, + vol.Optional('time_zone'): cv.time_zone, }) -async def websocket_core_update(hass, connection, msg): - """Handle request for account info.""" +async def websocket_update_config(hass, connection, msg): + """Handle update core config command.""" data = dict(msg) data.pop('id') data.pop('type') - await hass.config.update(**data) - connection.send_result(msg['id']) + + try: + await hass.config.update(**data) + connection.send_result(msg['id']) + except ValueError as err: + connection.send_error( + msg['id'], 'invalid_info', str(err) + ) + + +@websocket_api.require_admin +@websocket_api.async_response +@websocket_api.websocket_command({ + 'type': 'config/core/detect', +}) +async def websocket_detect_config(hass, connection, msg): + """Detect core config.""" + session = hass.helpers.aiohttp_client.async_get_clientsession() + location_info = await location.async_detect_location_info(session) + + info = {} + + if location_info is None: + connection.send_result(msg['id'], info) + return + + if location_info.use_metric: + info['unit_system'] = CONF_UNIT_SYSTEM_METRIC + else: + info['unit_system'] = CONF_UNIT_SYSTEM_IMPERIAL + + if location_info.latitude: + info['latitude'] = location_info.latitude + + if location_info.longitude: + info['longitude'] = location_info.longitude + + if location_info.time_zone: + info['time_zone'] = location_info.time_zone + + connection.send_result(msg['id'], info) diff --git a/homeassistant/components/onboarding/__init__.py b/homeassistant/components/onboarding/__init__.py index 55bba8f4efe..f5ed1a9b271 100644 --- a/homeassistant/components/onboarding/__init__.py +++ b/homeassistant/components/onboarding/__init__.py @@ -3,10 +3,11 @@ from homeassistant.core import callback from homeassistant.loader import bind_hass from homeassistant.helpers.storage import Store -from .const import DOMAIN, STEP_USER, STEPS, STEP_INTEGRATION +from .const import ( + DOMAIN, STEP_USER, STEPS, STEP_INTEGRATION, STEP_CORE_CONFIG) STORAGE_KEY = DOMAIN -STORAGE_VERSION = 2 +STORAGE_VERSION = 3 class OnboadingStorage(Store): @@ -15,7 +16,10 @@ class OnboadingStorage(Store): async def _async_migrate_func(self, old_version, old_data): """Migrate to the new version.""" # From version 1 -> 2, we automatically mark the integration step done - old_data['done'].append(STEP_INTEGRATION) + if old_version < 2: + old_data['done'].append(STEP_INTEGRATION) + if old_version < 3: + old_data['done'].append(STEP_CORE_CONFIG) return old_data diff --git a/homeassistant/components/onboarding/const.py b/homeassistant/components/onboarding/const.py index fe1b28fc316..bdc573efcb4 100644 --- a/homeassistant/components/onboarding/const.py +++ b/homeassistant/components/onboarding/const.py @@ -1,10 +1,12 @@ """Constants for the onboarding component.""" DOMAIN = 'onboarding' STEP_USER = 'user' +STEP_CORE_CONFIG = 'core_config' STEP_INTEGRATION = 'integration' STEPS = [ STEP_USER, + STEP_CORE_CONFIG, STEP_INTEGRATION, ] diff --git a/homeassistant/components/onboarding/views.py b/homeassistant/components/onboarding/views.py index a156fe4676f..c8060891fd4 100644 --- a/homeassistant/components/onboarding/views.py +++ b/homeassistant/components/onboarding/views.py @@ -7,13 +7,16 @@ from homeassistant.components.http.data_validator import RequestDataValidator from homeassistant.components.http.view import HomeAssistantView from homeassistant.core import callback -from .const import DOMAIN, STEP_USER, STEPS, DEFAULT_AREAS, STEP_INTEGRATION +from .const import ( + DOMAIN, STEP_USER, STEPS, DEFAULT_AREAS, STEP_INTEGRATION, + STEP_CORE_CONFIG) async def async_setup(hass, data, store): """Set up the onboarding view.""" hass.http.register_view(OnboardingView(data, store)) hass.http.register_view(UserOnboardingView(data, store)) + hass.http.register_view(CoreConfigOnboardingView(data, store)) hass.http.register_view(IntegrationOnboardingView(data, store)) @@ -128,6 +131,26 @@ class UserOnboardingView(_BaseOnboardingView): }) +class CoreConfigOnboardingView(_BaseOnboardingView): + """View to finish core config onboarding step.""" + + url = '/api/onboarding/core_config' + name = 'api:onboarding:core_config' + step = STEP_CORE_CONFIG + + async def post(self, request): + """Handle finishing core config step.""" + hass = request.app['hass'] + + async with self._lock: + if self._async_is_done(): + return self.json_message('Core config step already done', 403) + + await self._async_mark_done(hass) + + return self.json({}) + + class IntegrationOnboardingView(_BaseOnboardingView): """View to finish integration onboarding step.""" @@ -139,7 +162,7 @@ class IntegrationOnboardingView(_BaseOnboardingView): vol.Required('client_id'): str, })) async def post(self, request, data): - """Handle user creation, area creation.""" + """Handle token creation.""" hass = request.app['hass'] user = request['hass_user'] diff --git a/homeassistant/config.py b/homeassistant/config.py index ec83818d903..cffaffd8985 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -18,13 +18,13 @@ from homeassistant.auth import providers as auth_providers,\ from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_HIDDEN, ATTR_ASSUMED_STATE, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_PACKAGES, CONF_UNIT_SYSTEM, - CONF_TIME_ZONE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC, + CONF_TIME_ZONE, CONF_ELEVATION, CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS, __version__, CONF_CUSTOMIZE, CONF_CUSTOMIZE_DOMAIN, CONF_CUSTOMIZE_GLOB, CONF_WHITELIST_EXTERNAL_DIRS, CONF_AUTH_PROVIDERS, CONF_AUTH_MFA_MODULES, CONF_TYPE, CONF_ID) from homeassistant.core import ( - DOMAIN as CONF_CORE, SOURCE_DISCOVERED, SOURCE_YAML, HomeAssistant, + DOMAIN as CONF_CORE, SOURCE_YAML, HomeAssistant, callback) from homeassistant.exceptions import HomeAssistantError from homeassistant.loader import ( @@ -32,7 +32,6 @@ from homeassistant.loader import ( ) from homeassistant.util.yaml import load_yaml, SECRET_YAML import homeassistant.helpers.config_validation as cv -from homeassistant.util import location as loc_util from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM from homeassistant.helpers.entity_values import EntityValues from homeassistant.helpers import config_per_platform, extract_domain_configs @@ -52,22 +51,6 @@ FILE_MIGRATION = ( ('ios.conf', '.ios.conf'), ) -DEFAULT_CORE_CONFIG = ( - # Tuples (attribute, default, auto detect property, description) - (CONF_NAME, 'Home', None, 'Name of the location where Home Assistant is ' - 'running'), - (CONF_LATITUDE, 0, 'latitude', 'Location required to calculate the time' - ' the sun rises and sets'), - (CONF_LONGITUDE, 0, 'longitude', None), - (CONF_ELEVATION, 0, None, 'Impacts weather/sunrise data' - ' (altitude above sea level in meters)'), - (CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_METRIC, None, - '{} for Metric, {} for Imperial'.format(CONF_UNIT_SYSTEM_METRIC, - CONF_UNIT_SYSTEM_IMPERIAL)), - (CONF_TIME_ZONE, 'UTC', 'time_zone', 'Pick yours from here: http://en.wiki' - 'pedia.org/wiki/List_of_tz_database_time_zones'), - (CONF_CUSTOMIZE, '!include customize.yaml', None, 'Customization file'), -) # type: Tuple[Tuple[str, Any, Any, Optional[str]], ...] DEFAULT_CONFIG = """ # Configure a default setup of Home Assistant (frontend, api, etc) default_config: @@ -207,8 +190,7 @@ def get_default_config_dir() -> str: return os.path.join(data_dir, CONFIG_DIR_NAME) # type: ignore -async def async_ensure_config_exists(hass: HomeAssistant, config_dir: str, - detect_location: bool = True)\ +async def async_ensure_config_exists(hass: HomeAssistant, config_dir: str) \ -> Optional[str]: """Ensure a configuration file exists in given configuration directory. @@ -220,49 +202,22 @@ async def async_ensure_config_exists(hass: HomeAssistant, config_dir: str, if config_path is None: print("Unable to find configuration. Creating default one in", config_dir) - config_path = await async_create_default_config( - hass, config_dir, detect_location) + config_path = await async_create_default_config(hass, config_dir) return config_path -async def async_create_default_config( - hass: HomeAssistant, config_dir: str, detect_location: bool = True - ) -> Optional[str]: +async def async_create_default_config(hass: HomeAssistant, config_dir: str) \ + -> Optional[str]: """Create a default configuration file in given configuration directory. Return path to new config file if success, None if failed. This method needs to run in an executor. """ - info = {attr: default for attr, default, _, _ in DEFAULT_CORE_CONFIG} - - if detect_location: - session = hass.helpers.aiohttp_client.async_get_clientsession() - location_info = await loc_util.async_detect_location_info(session) - else: - location_info = None - - if location_info: - if location_info.use_metric: - info[CONF_UNIT_SYSTEM] = CONF_UNIT_SYSTEM_METRIC - else: - info[CONF_UNIT_SYSTEM] = CONF_UNIT_SYSTEM_IMPERIAL - - for attr, default, prop, _ in DEFAULT_CORE_CONFIG: - if prop is None: - continue - info[attr] = getattr(location_info, prop) or default - - if location_info.latitude and location_info.longitude: - info[CONF_ELEVATION] = await loc_util.async_get_elevation( - session, location_info.latitude, location_info.longitude) - - return await hass.async_add_executor_job( - _write_default_config, config_dir, info - ) + return await hass.async_add_executor_job(_write_default_config, config_dir) -def _write_default_config(config_dir: str, info: Dict)\ +def _write_default_config(config_dir: str)\ -> Optional[str]: """Write the default config.""" from homeassistant.components.config.group import ( @@ -271,8 +226,6 @@ def _write_default_config(config_dir: str, info: Dict)\ CONFIG_PATH as AUTOMATION_CONFIG_PATH) from homeassistant.components.config.script import ( CONFIG_PATH as SCRIPT_CONFIG_PATH) - from homeassistant.components.config.customize import ( - CONFIG_PATH as CUSTOMIZE_CONFIG_PATH) config_path = os.path.join(config_dir, YAML_CONFIG_FILE) secret_path = os.path.join(config_dir, SECRET_YAML) @@ -280,21 +233,11 @@ def _write_default_config(config_dir: str, info: Dict)\ group_yaml_path = os.path.join(config_dir, GROUP_CONFIG_PATH) automation_yaml_path = os.path.join(config_dir, AUTOMATION_CONFIG_PATH) script_yaml_path = os.path.join(config_dir, SCRIPT_CONFIG_PATH) - customize_yaml_path = os.path.join(config_dir, CUSTOMIZE_CONFIG_PATH) # 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, 'wt') as config_file: - config_file.write("homeassistant:\n") - - for attr, _, _, description in DEFAULT_CORE_CONFIG: - if info[attr] is None: - continue - elif description: - config_file.write(" # {}\n".format(description)) - config_file.write(" {}: {}\n".format(attr, info[attr])) - config_file.write(DEFAULT_CONFIG) with open(secret_path, 'wt') as secret_file: @@ -312,9 +255,6 @@ def _write_default_config(config_dir: str, info: Dict)\ with open(script_yaml_path, 'wt'): pass - with open(customize_yaml_path, 'wt'): - pass - return config_path except IOError: @@ -576,55 +516,6 @@ async def async_process_ha_core_config( "with '%s: %s'", CONF_TEMPERATURE_UNIT, unit, CONF_UNIT_SYSTEM, hac.units.name) - # Shortcut if no auto-detection necessary - if None not in (hac.latitude, hac.longitude, hac.units, - hac.time_zone, hac.elevation): - return - - discovered = [] # type: List[Tuple[str, Any]] - - # If we miss some of the needed values, auto detect them - if None in (hac.latitude, hac.longitude, hac.units, - hac.time_zone): - hac.config_source = SOURCE_DISCOVERED - info = await loc_util.async_detect_location_info( - hass.helpers.aiohttp_client.async_get_clientsession() - ) - - if info is None: - _LOGGER.error("Could not detect location information") - return - - if hac.latitude is None and hac.longitude is None: - hac.latitude, hac.longitude = (info.latitude, info.longitude) - discovered.append(('latitude', hac.latitude)) - discovered.append(('longitude', hac.longitude)) - - if hac.units is None: - hac.units = METRIC_SYSTEM if info.use_metric else IMPERIAL_SYSTEM - discovered.append((CONF_UNIT_SYSTEM, hac.units.name)) - - if hac.location_name is None: - hac.location_name = info.city - discovered.append(('name', info.city)) - - if hac.time_zone is None: - hac.set_time_zone(info.time_zone) - discovered.append(('time_zone', info.time_zone)) - - if hac.elevation is None and hac.latitude is not None and \ - hac.longitude is not None: - elevation = await loc_util.async_get_elevation( - hass.helpers.aiohttp_client.async_get_clientsession(), - hac.latitude, hac.longitude) - hac.elevation = elevation - discovered.append(('elevation', elevation)) - - if discovered: - _LOGGER.warning( - "Incomplete core configuration. Auto detected %s", - ", ".join('{}: {}'.format(key, val) for key, val in discovered)) - def _log_pkg_error( package: str, component: str, config: Dict, message: str) -> None: diff --git a/homeassistant/core.py b/homeassistant/core.py index 4dd84cc1a46..5941739fcc5 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -57,7 +57,7 @@ CALLABLE_T = TypeVar('CALLABLE_T', bound=Callable) CALLBACK_TYPE = Callable[[], None] # pylint: enable=invalid-name -CORE_STORAGE_KEY = 'homeassistant.core_config' +CORE_STORAGE_KEY = 'core.config' CORE_STORAGE_VERSION = 1 DOMAIN = 'homeassistant' @@ -1181,14 +1181,14 @@ class Config: """Initialize a new config object.""" self.hass = hass - self.latitude = None # type: Optional[float] - self.longitude = None # type: Optional[float] - self.elevation = None # type: Optional[int] - self.location_name = None # type: Optional[str] - self.time_zone = None # type: Optional[datetime.tzinfo] + self.latitude = 0 # type: float + self.longitude = 0 # type: float + self.elevation = 0 # type: int + self.location_name = "Home" # type: str + self.time_zone = dt_util.UTC # type: datetime.tzinfo self.units = METRIC_SYSTEM # type: UnitSystem - self.config_source = None # type: Optional[str] + self.config_source = "default" # type: str # If True, pip install is skipped for requirements on startup self.skip_pip = False # type: bool diff --git a/homeassistant/util/location.py b/homeassistant/util/location.py index 1d13bcf0ce5..bacffa9da42 100644 --- a/homeassistant/util/location.py +++ b/homeassistant/util/location.py @@ -65,30 +65,6 @@ def distance(lat1: Optional[float], lon1: Optional[float], return result * 1000 -async def async_get_elevation(session: aiohttp.ClientSession, latitude: float, - longitude: float) -> int: - """Return elevation for given latitude and longitude.""" - try: - resp = await session.get(ELEVATION_URL, params={ - 'locations': '{},{}'.format(latitude, longitude), - }, timeout=5) - except (aiohttp.ClientError, asyncio.TimeoutError): - return 0 - - if resp.status != 200: - return 0 - - try: - raw_info = await resp.json() - except (aiohttp.ClientError, ValueError): - return 0 - - try: - return int(float(raw_info['results'][0]['elevation'])) - except (ValueError, KeyError, IndexError): - return 0 - - # Author: https://github.com/maurycyp # Source: https://github.com/maurycyp/vincenty # License: https://github.com/maurycyp/vincenty/blob/master/LICENSE diff --git a/tests/components/config/test_core.py b/tests/components/config/test_core.py index 81b3818a815..e58971a4cd8 100644 --- a/tests/components/config/test_core.py +++ b/tests/components/config/test_core.py @@ -1,24 +1,31 @@ """Test hassbian config.""" -import asyncio from unittest.mock import patch +import pytest + from homeassistant.bootstrap import async_setup_component from homeassistant.components import config from homeassistant.components.websocket_api.const import TYPE_RESULT from homeassistant.const import CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_IMPERIAL -import homeassistant.util.dt as dt_util +from homeassistant.util import dt as dt_util, location from tests.common import mock_coro ORIG_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE +@pytest.fixture +async def client(hass, hass_ws_client): + """Fixture that can interact with the config manager API.""" + with patch.object(config, 'SECTIONS', ['core']): + assert await async_setup_component(hass, 'config', {}) + return await hass_ws_client(hass) + + async def test_validate_config_ok(hass, hass_client): """Test checking config.""" with patch.object(config, 'SECTIONS', ['core']): await async_setup_component(hass, 'config', {}) - await asyncio.sleep(0.1, loop=hass.loop) - client = await hass_client() with patch( @@ -42,11 +49,8 @@ async def test_validate_config_ok(hass, hass_client): assert result['errors'] == 'beer' -async def test_websocket_core_update(hass, hass_ws_client): +async def test_websocket_core_update(hass, client): """Test core config update websocket command.""" - with patch.object(config, 'SECTIONS', ['core']): - await async_setup_component(hass, 'config', {}) - assert hass.config.latitude != 60 assert hass.config.longitude != 50 assert hass.config.elevation != 25 @@ -54,7 +58,6 @@ async def test_websocket_core_update(hass, hass_ws_client): assert hass.config.units.name != CONF_UNIT_SYSTEM_IMPERIAL assert hass.config.time_zone.zone != 'America/New_York' - client = await hass_ws_client(hass) await client.send_json({ 'id': 5, 'type': 'config/core/update', @@ -92,7 +95,7 @@ async def test_websocket_core_update_not_admin( await client.send_json({ 'id': 6, 'type': 'config/core/update', - 'latitude': 123, + 'latitude': 23, }) msg = await client.receive_json() @@ -103,16 +106,12 @@ async def test_websocket_core_update_not_admin( assert msg['error']['code'] == 'unauthorized' -async def test_websocket_bad_core_update(hass, hass_ws_client): +async def test_websocket_bad_core_update(hass, client): """Test core config update fails with bad parameters.""" - with patch.object(config, 'SECTIONS', ['core']): - await async_setup_component(hass, 'config', {}) - - client = await hass_ws_client(hass) await client.send_json({ 'id': 7, 'type': 'config/core/update', - 'latituude': 123, + 'latituude': 23, }) msg = await client.receive_json() @@ -121,3 +120,48 @@ async def test_websocket_bad_core_update(hass, hass_ws_client): assert msg['type'] == TYPE_RESULT assert not msg['success'] assert msg['error']['code'] == 'invalid_format' + + +async def test_detect_config(hass, client): + """Test detect config.""" + with patch('homeassistant.util.location.async_detect_location_info', + return_value=mock_coro(None)): + await client.send_json({ + 'id': 1, + 'type': 'config/core/detect', + }) + + msg = await client.receive_json() + + assert msg['success'] is True + assert msg['result'] == {} + + +async def test_detect_config_fail(hass, client): + """Test detect config.""" + with patch('homeassistant.util.location.async_detect_location_info', + return_value=mock_coro(location.LocationInfo( + ip=None, + country_code=None, + country_name=None, + region_code=None, + region_name=None, + city=None, + zip_code=None, + latitude=None, + longitude=None, + use_metric=True, + time_zone='Europe/Amsterdam', + ))): + await client.send_json({ + 'id': 1, + 'type': 'config/core/detect', + }) + + msg = await client.receive_json() + + assert msg['success'] is True + assert msg['result'] == { + 'unit_system': 'metric', + 'time_zone': 'Europe/Amsterdam', + } diff --git a/tests/conftest.py b/tests/conftest.py index fdac037bfa9..83a175656d7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -44,8 +44,6 @@ def check_real(func): # Guard a few functions that would make network connections location.async_detect_location_info = \ check_real(location.async_detect_location_info) -location.async_get_elevation = \ - check_real(location.async_get_elevation) util.get_local_ip = lambda: '127.0.0.1' diff --git a/tests/test_config.py b/tests/test_config.py index 42386cc1f4c..5579679937b 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -12,17 +12,16 @@ import pytest from voluptuous import MultipleInvalid, Invalid import yaml -from homeassistant.core import ( - DOMAIN, SOURCE_STORAGE, Config, HomeAssistantError) +from homeassistant.core import SOURCE_STORAGE, HomeAssistantError import homeassistant.config as config_util from homeassistant.loader import async_get_integration from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_HIDDEN, ATTR_ASSUMED_STATE, CONF_LATITUDE, CONF_LONGITUDE, CONF_UNIT_SYSTEM, CONF_NAME, - CONF_TIME_ZONE, CONF_ELEVATION, CONF_CUSTOMIZE, __version__, + CONF_CUSTOMIZE, __version__, CONF_UNIT_SYSTEM_METRIC, CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, CONF_AUTH_PROVIDERS, CONF_AUTH_MFA_MODULES) -from homeassistant.util import location as location_util, dt as dt_util +from homeassistant.util import dt as dt_util from homeassistant.util.yaml import SECRET_YAML from homeassistant.helpers.entity import Entity from homeassistant.components.config.group import ( @@ -31,12 +30,10 @@ from homeassistant.components.config.automation import ( CONFIG_PATH as AUTOMATIONS_CONFIG_PATH) from homeassistant.components.config.script import ( CONFIG_PATH as SCRIPTS_CONFIG_PATH) -from homeassistant.components.config.customize import ( - CONFIG_PATH as CUSTOMIZE_CONFIG_PATH) import homeassistant.scripts.check_config as check_config from tests.common import ( - get_test_config_dir, patch_yaml_files, mock_coro) + get_test_config_dir, patch_yaml_files) CONFIG_DIR = get_test_config_dir() YAML_PATH = os.path.join(CONFIG_DIR, config_util.YAML_CONFIG_FILE) @@ -45,7 +42,6 @@ VERSION_PATH = os.path.join(CONFIG_DIR, config_util.VERSION_FILE) GROUP_PATH = os.path.join(CONFIG_DIR, GROUP_CONFIG_PATH) AUTOMATIONS_PATH = os.path.join(CONFIG_DIR, AUTOMATIONS_CONFIG_PATH) SCRIPTS_PATH = os.path.join(CONFIG_DIR, SCRIPTS_CONFIG_PATH) -CUSTOMIZE_PATH = os.path.join(CONFIG_DIR, CUSTOMIZE_CONFIG_PATH) ORIG_TIMEZONE = dt_util.DEFAULT_TIME_ZONE @@ -77,20 +73,16 @@ def teardown(): if os.path.isfile(SCRIPTS_PATH): os.remove(SCRIPTS_PATH) - if os.path.isfile(CUSTOMIZE_PATH): - os.remove(CUSTOMIZE_PATH) - async def test_create_default_config(hass): """Test creation of default config.""" - await config_util.async_create_default_config(hass, CONFIG_DIR, False) + await config_util.async_create_default_config(hass, CONFIG_DIR) assert os.path.isfile(YAML_PATH) assert os.path.isfile(SECRET_PATH) assert os.path.isfile(VERSION_PATH) assert os.path.isfile(GROUP_PATH) assert os.path.isfile(AUTOMATIONS_PATH) - assert os.path.isfile(CUSTOMIZE_PATH) def test_find_config_file_yaml(): @@ -106,7 +98,7 @@ async def test_ensure_config_exists_creates_config(hass): If not creates a new config file. """ with mock.patch('builtins.print') as mock_print: - await config_util.async_ensure_config_exists(hass, CONFIG_DIR, False) + await config_util.async_ensure_config_exists(hass, CONFIG_DIR) assert os.path.isfile(YAML_PATH) assert mock_print.called @@ -115,7 +107,7 @@ async def test_ensure_config_exists_creates_config(hass): async def test_ensure_config_exists_uses_existing_config(hass): """Test that calling ensure_config_exists uses existing config.""" create_file(YAML_PATH) - await config_util.async_ensure_config_exists(hass, CONFIG_DIR, False) + await config_util.async_ensure_config_exists(hass, CONFIG_DIR) with open(YAML_PATH) as f: content = f.read() @@ -168,38 +160,6 @@ def test_load_yaml_config_preserves_key_order(): list(config_util.load_yaml_config_file(YAML_PATH).items()) -async def test_create_default_config_detect_location(hass): - """Test that detect location sets the correct config keys.""" - with mock.patch('homeassistant.util.location.async_detect_location_info', - return_value=mock_coro(location_util.LocationInfo( - '0.0.0.0', 'US', 'United States', 'CA', 'California', - 'San Diego', '92122', 'America/Los_Angeles', 32.8594, - -117.2073, True))), \ - mock.patch('homeassistant.util.location.async_get_elevation', - return_value=mock_coro(101)), \ - mock.patch('builtins.print') as mock_print: - await config_util.async_ensure_config_exists(hass, CONFIG_DIR) - - config = config_util.load_yaml_config_file(YAML_PATH) - - assert DOMAIN in config - - ha_conf = config[DOMAIN] - - expected_values = { - CONF_LATITUDE: 32.8594, - CONF_LONGITUDE: -117.2073, - CONF_ELEVATION: 101, - CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC, - CONF_NAME: 'Home', - CONF_TIME_ZONE: 'America/Los_Angeles', - CONF_CUSTOMIZE: OrderedDict(), - } - - assert expected_values == ha_conf - assert mock_print.called - - async def test_create_default_config_returns_none_if_write_error(hass): """Test the writing of a default configuration. @@ -207,7 +167,7 @@ async def test_create_default_config_returns_none_if_write_error(hass): """ with mock.patch('builtins.print') as mock_print: assert await config_util.async_create_default_config( - hass, os.path.join(CONFIG_DIR, 'non_existing_dir/'), False) is None + hass, os.path.join(CONFIG_DIR, 'non_existing_dir/')) is None assert mock_print.called @@ -418,7 +378,7 @@ def test_migrate_no_file_on_upgrade(mock_os, mock_shutil, hass): async def test_loading_configuration_from_storage(hass, hass_storage): """Test loading core config onto hass object.""" - hass_storage["homeassistant.core_config"] = { + hass_storage["core.config"] = { 'data': { 'elevation': 10, 'latitude': 55, @@ -427,7 +387,7 @@ async def test_loading_configuration_from_storage(hass, hass_storage): 'time_zone': 'Europe/Copenhagen', 'unit_system': 'metric' }, - 'key': 'homeassistant.core_config', + 'key': 'core.config', 'version': 1 } await config_util.async_process_ha_core_config( @@ -455,23 +415,23 @@ async def test_updating_configuration(hass, hass_storage): 'time_zone': 'Europe/Copenhagen', 'unit_system': 'metric' }, - 'key': 'homeassistant.core_config', + 'key': 'core.config', 'version': 1 } - hass_storage["homeassistant.core_config"] = dict(core_data) + hass_storage["core.config"] = dict(core_data) await config_util.async_process_ha_core_config( hass, {'whitelist_external_dirs': '/tmp'}) await hass.config.update(latitude=50) new_core_data = copy.deepcopy(core_data) new_core_data['data']['latitude'] = 50 - assert hass_storage["homeassistant.core_config"] == new_core_data + assert hass_storage["core.config"] == new_core_data assert hass.config.latitude == 50 async def test_override_stored_configuration(hass, hass_storage): """Test loading core and YAML config onto hass object.""" - hass_storage["homeassistant.core_config"] = { + hass_storage["core.config"] = { 'data': { 'elevation': 10, 'latitude': 55, @@ -480,7 +440,7 @@ async def test_override_stored_configuration(hass, hass_storage): 'time_zone': 'Europe/Copenhagen', 'unit_system': 'metric' }, - 'key': 'homeassistant.core_config', + 'key': 'core.config', 'version': 1 } await config_util.async_process_ha_core_config(hass, { @@ -571,59 +531,6 @@ async def test_loading_configuration_from_packages(hass): }) -@asynctest.mock.patch( - 'homeassistant.util.location.async_detect_location_info', - autospec=True, return_value=mock_coro(location_util.LocationInfo( - '0.0.0.0', 'US', 'United States', 'CA', - 'California', 'San Diego', '92122', - 'America/Los_Angeles', 32.8594, -117.2073, True))) -@asynctest.mock.patch('homeassistant.util.location.async_get_elevation', - autospec=True, return_value=mock_coro(101)) -async def test_discovering_configuration(mock_detect, mock_elevation, hass): - """Test auto discovery for missing core configs.""" - hass.config.latitude = None - hass.config.longitude = None - hass.config.elevation = None - hass.config.location_name = None - hass.config.time_zone = None - - await config_util.async_process_ha_core_config(hass, {}) - - assert hass.config.latitude == 32.8594 - assert hass.config.longitude == -117.2073 - assert hass.config.elevation == 101 - assert hass.config.location_name == 'San Diego' - assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC - assert hass.config.units.is_metric - assert hass.config.time_zone.zone == 'America/Los_Angeles' - assert hass.config.config_source == config_util.SOURCE_DISCOVERED - - -@asynctest.mock.patch('homeassistant.util.location.async_detect_location_info', - autospec=True, return_value=mock_coro(None)) -@asynctest.mock.patch('homeassistant.util.location.async_get_elevation', - return_value=mock_coro(0)) -async def test_discovering_configuration_auto_detect_fails(mock_detect, - mock_elevation, - hass): - """Test config remains unchanged if discovery fails.""" - hass.config = Config(hass) - hass.config.config_dir = "/test/config" - - await config_util.async_process_ha_core_config(hass, {}) - - blankConfig = Config(hass) - assert hass.config.latitude == blankConfig.latitude - assert hass.config.longitude == blankConfig.longitude - assert hass.config.elevation == blankConfig.elevation - assert hass.config.location_name == blankConfig.location_name - assert hass.config.units == blankConfig.units - assert hass.config.time_zone == blankConfig.time_zone - assert len(hass.config.whitelist_external_dirs) == 1 - assert "/test/config/www" in hass.config.whitelist_external_dirs - assert hass.config.config_source == config_util.SOURCE_DISCOVERED - - @asynctest.mock.patch( 'homeassistant.scripts.check_config.check_ha_config_file') async def test_check_ha_config_file_correct(mock_check, hass): diff --git a/tests/test_core.py b/tests/test_core.py index 101396dd05e..2e9e14ed97a 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -891,17 +891,17 @@ class TestConfig(unittest.TestCase): """Test as dict.""" self.config.config_dir = '/tmp/ha-config' expected = { - 'latitude': None, - 'longitude': None, - 'elevation': None, + 'latitude': 0, + 'longitude': 0, + 'elevation': 0, CONF_UNIT_SYSTEM: METRIC_SYSTEM.as_dict(), - 'location_name': None, + 'location_name': "Home", 'time_zone': 'UTC', 'components': set(), 'config_dir': '/tmp/ha-config', 'whitelist_external_dirs': set(), 'version': __version__, - 'config_source': None, + 'config_source': "default", } assert expected == self.config.as_dict() diff --git a/tests/util/test_location.py b/tests/util/test_location.py index 2db37c46730..3fb7d07c2bb 100644 --- a/tests/util/test_location.py +++ b/tests/util/test_location.py @@ -116,10 +116,8 @@ async def test_detect_location_info_ip_api(aioclient_mock, session): async def test_detect_location_info_both_queries_fail(session): """Ensure we return None if both queries fail.""" - with patch('homeassistant.util.location.async_get_elevation', - return_value=mock_coro(0)), \ - patch('homeassistant.util.location._get_ipapi', - return_value=mock_coro(None)), \ + with patch('homeassistant.util.location._get_ipapi', + return_value=mock_coro(None)), \ patch('homeassistant.util.location._get_ip_api', return_value=mock_coro(None)): info = await location_util.async_detect_location_info( @@ -137,26 +135,3 @@ async def test_ip_api_query_raises(raising_session): """Test ip api query when the request to API fails.""" info = await location_util._get_ip_api(raising_session) assert info is None - - -async def test_elevation_query_raises(raising_session): - """Test elevation when the request to API fails.""" - elevation = await location_util.async_get_elevation( - raising_session, 10, 10, _test_real=True) - assert elevation == 0 - - -async def test_elevation_query_fails(aioclient_mock, session): - """Test elevation when the request to API fails.""" - aioclient_mock.get(location_util.ELEVATION_URL, text='{}', status=401) - elevation = await location_util.async_get_elevation( - session, 10, 10, _test_real=True) - assert elevation == 0 - - -async def test_elevation_query_nonjson(aioclient_mock, session): - """Test if elevation API returns a non JSON value.""" - aioclient_mock.get(location_util.ELEVATION_URL, text='{ I am not JSON }') - elevation = await location_util.async_get_elevation( - session, 10, 10, _test_real=True) - assert elevation == 0