New TimeZone handling (#1138)

* Remove function to get TZ from config file

* Readd old timezone handling

* Fix tests
This commit is contained in:
Pascal Vizeli 2019-06-25 17:09:14 +02:00 committed by GitHub
parent 6d6deb8c66
commit 709f034f2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 22 deletions

View File

@ -22,10 +22,11 @@ from .host import HostManager
from .ingress import Ingress from .ingress import Ingress
from .services import ServiceManager from .services import ServiceManager
from .snapshots import SnapshotManager from .snapshots import SnapshotManager
from .supervisor import Supervisor
from .store import StoreManager from .store import StoreManager
from .supervisor import Supervisor
from .tasks import Tasks from .tasks import Tasks
from .updater import Updater from .updater import Updater
from .utils.dt import fetch_timezone
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -66,6 +67,10 @@ async def initialize_coresys():
if MACHINE_ID.exists(): if MACHINE_ID.exists():
coresys.machine_id = MACHINE_ID.read_text().strip() coresys.machine_id = MACHINE_ID.read_text().strip()
# Init TimeZone
if coresys.config.timezone == "UTC":
coresys.config.timezone = await fetch_timezone(coresys.websession)
return coresys return coresys

View File

@ -3,9 +3,6 @@ from datetime import datetime
import logging import logging
import os import os
from pathlib import Path, PurePath from pathlib import Path, PurePath
import re
import pytz
from .const import ( from .const import (
ATTR_ADDONS_CUSTOM_LIST, ATTR_ADDONS_CUSTOM_LIST,
@ -40,8 +37,6 @@ APPARMOR_DATA = PurePath("apparmor")
DEFAULT_BOOT_TIME = datetime.utcfromtimestamp(0).isoformat() DEFAULT_BOOT_TIME = datetime.utcfromtimestamp(0).isoformat()
RE_TIMEZONE = re.compile(r"time_zone: (?P<timezone>[\w/\-+]+)")
class CoreConfig(JsonConfig): class CoreConfig(JsonConfig):
"""Hold all core config data.""" """Hold all core config data."""
@ -53,21 +48,7 @@ class CoreConfig(JsonConfig):
@property @property
def timezone(self): def timezone(self):
"""Return system timezone.""" """Return system timezone."""
config_file = Path(self.path_homeassistant, "configuration.yaml") return self._data[ATTR_TIMEZONE]
try:
assert config_file.exists()
configuration = config_file.read_text()
data = RE_TIMEZONE.search(configuration)
assert data
timezone = data.group("timezone")
pytz.timezone(timezone)
except (pytz.exceptions.UnknownTimeZoneError, OSError, AssertionError):
_LOGGER.debug("Can't parse Home Assistant timezone")
return self._data[ATTR_TIMEZONE]
return timezone
@timezone.setter @timezone.setter
def timezone(self, value): def timezone(self, value):

View File

@ -1,13 +1,17 @@
"""Tools file for Hass.io.""" """Tools file for Hass.io."""
import asyncio
from datetime import datetime, timedelta, timezone, tzinfo from datetime import datetime, timedelta, timezone, tzinfo
import logging import logging
import re import re
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
import aiohttp
import pytz import pytz
UTC = pytz.utc UTC = pytz.utc
GEOIP_URL = "http://ip-api.com/json/"
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -22,6 +26,21 @@ DATETIME_RE = re.compile(
) )
async def fetch_timezone(websession):
"""Read timezone from freegeoip."""
data = {}
try:
async with websession.get(GEOIP_URL, timeout=10) as request:
data = await request.json()
except (aiohttp.ClientError, asyncio.TimeoutError) as err:
_LOGGER.warning("Can't fetch freegeoip data: %s", err)
except ValueError as err:
_LOGGER.warning("Error on parse freegeoip data: %s", err)
return data.get("timezone", "UTC")
# Copyright (c) Django Software Foundation and individual contributors. # Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved. # All rights reserved.
# https://github.com/django/django/blob/master/LICENSE # https://github.com/django/django/blob/master/LICENSE

View File

@ -7,3 +7,20 @@ def load_json_fixture(filename):
"""Load a fixture.""" """Load a fixture."""
path = Path(Path(__file__).parent.joinpath("fixtures"), filename) path = Path(Path(__file__).parent.joinpath("fixtures"), filename)
return json.loads(path.read_text()) return json.loads(path.read_text())
def mock_coro(return_value=None, exception=None):
"""Return a coro that returns a value or raise an exception."""
return mock_coro_func(return_value, exception)()
def mock_coro_func(return_value=None, exception=None):
"""Return a method to create a coro function that returns a value."""
async def coro(*args, **kwargs):
"""Fake coroutine."""
if exception:
raise exception
return return_value
return coro

View File

@ -5,6 +5,8 @@ import pytest
from hassio.bootstrap import initialize_coresys from hassio.bootstrap import initialize_coresys
from tests.common import mock_coro
# pylint: disable=redefined-outer-name # pylint: disable=redefined-outer-name
@ -18,7 +20,10 @@ def docker():
@pytest.fixture @pytest.fixture
async def coresys(loop, docker): async def coresys(loop, docker):
"""Create a CoreSys Mock.""" """Create a CoreSys Mock."""
with patch("hassio.bootstrap.initialize_system_data"): with patch("hassio.bootstrap.initialize_system_data"), patch(
"hassio.bootstrap.fetch_timezone",
return_value=mock_coro(return_value="Europe/Zurich"),
):
coresys_obj = await initialize_coresys() coresys_obj = await initialize_coresys()
coresys_obj.ingress.save_data = MagicMock() coresys_obj.ingress.save_data = MagicMock()