1
mirror of https://github.com/home-assistant/core synced 2024-09-06 10:29:55 +02:00

Extract instance ID helper from updater (#35043)

This commit is contained in:
Paulus Schoutsen 2020-05-04 11:23:12 -07:00 committed by GitHub
parent b3e637ca7a
commit e54e9279e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 37 deletions

View File

@ -1,9 +1,7 @@
"""Support to check for available updates."""
from datetime import timedelta
from distutils.version import StrictVersion
import json
import logging
import uuid
import async_timeout
from distro import linux_distribution # pylint: disable=import-error
@ -25,7 +23,6 @@ CONF_COMPONENT_REPORTING = "include_used_components"
DOMAIN = "updater"
UPDATER_URL = "https://updater.home-assistant.io/"
UPDATER_UUID_FILE = ".uuid"
CONFIG_SCHEMA = vol.Schema(
{
@ -52,26 +49,6 @@ class Updater:
self.newest_version = newest_version
def _create_uuid(hass, filename=UPDATER_UUID_FILE):
"""Create UUID and save it in a file."""
with open(hass.config.path(filename), "w") as fptr:
_uuid = uuid.uuid4().hex
fptr.write(json.dumps({"uuid": _uuid}))
return _uuid
def _load_uuid(hass, filename=UPDATER_UUID_FILE):
"""Load UUID from a file or return None."""
try:
with open(hass.config.path(filename)) as fptr:
jsonf = json.loads(fptr.read())
return uuid.UUID(jsonf["uuid"], version=4).hex
except (ValueError, AttributeError):
return None
except FileNotFoundError:
return _create_uuid(hass, filename)
async def async_setup(hass, config):
"""Set up the updater component."""
if "dev" in current_version:
@ -80,7 +57,7 @@ async def async_setup(hass, config):
conf = config.get(DOMAIN, {})
if conf.get(CONF_REPORTING):
huuid = await hass.async_add_job(_load_uuid, hass)
huuid = await hass.helpers.instance_id.async_get()
else:
huuid = None

View File

@ -7,7 +7,6 @@ import uuid
import attr
from homeassistant.core import callback
from homeassistant.loader import bind_hass
from .singleton import singleton
from .typing import HomeAssistantType
@ -367,7 +366,6 @@ class DeviceRegistry:
self._async_update_device(dev_id, area_id=None)
@bind_hass
@singleton(DATA_REGISTRY)
async def async_get_registry(hass: HomeAssistantType) -> DeviceRegistry:
"""Create entity registry."""

View File

@ -34,7 +34,6 @@ from homeassistant.const import (
)
from homeassistant.core import Event, callback, split_entity_id, valid_entity_id
from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED
from homeassistant.loader import bind_hass
from homeassistant.util import slugify
from homeassistant.util.yaml import load_yaml
@ -491,7 +490,6 @@ class EntityRegistry:
self.async_remove(entity_id)
@bind_hass
@singleton(DATA_REGISTRY)
async def async_get_registry(hass: HomeAssistantType) -> EntityRegistry:
"""Create entity registry."""

View File

@ -0,0 +1,31 @@
"""Helper to create a unique instance ID."""
from typing import Dict, Optional
import uuid
from homeassistant.core import HomeAssistant
from . import singleton, storage
DATA_KEY = "core.uuid"
DATA_VERSION = 1
LEGACY_UUID_FILE = ".uuid"
@singleton.singleton(DATA_KEY)
async def async_get(hass: HomeAssistant) -> str:
"""Get unique ID for the hass instance."""
store = storage.Store(hass, DATA_VERSION, DATA_KEY, True)
data: Optional[Dict[str, str]] = await storage.async_migrator( # type: ignore
hass, hass.config.path(LEGACY_UUID_FILE), store,
)
if data is not None:
return data["uuid"]
data = {"uuid": uuid.uuid4().hex}
await store.async_save(data)
return data["uuid"]

View File

@ -4,6 +4,7 @@ import functools
from typing import Awaitable, Callable, TypeVar, cast
from homeassistant.core import HomeAssistant
from homeassistant.loader import bind_hass
T = TypeVar("T")
@ -19,6 +20,7 @@ def singleton(data_key: str) -> Callable[[FUNC], FUNC]:
def wrapper(func: FUNC) -> FUNC:
"""Wrap a function with caching logic."""
@bind_hass
@functools.wraps(func)
async def wrapped(hass: HomeAssistant) -> T:
obj_or_evt = hass.data.get(data_key)

View File

@ -20,29 +20,32 @@ _LOGGER = logging.getLogger(__name__)
@bind_hass
async def async_migrator(
hass,
old_path,
store,
*,
old_conf_load_func=json_util.load_json,
old_conf_migrate_func=None,
hass, old_path, store, *, old_conf_load_func=None, old_conf_migrate_func=None,
):
"""Migrate old data to a store and then load data.
async def old_conf_migrate_func(old_data)
"""
store_data = await store.async_load()
# If we already have store data we have already migrated in the past.
if store_data is not None:
return store_data
def load_old_config():
"""Load old config."""
if not os.path.isfile(old_path):
return None
return old_conf_load_func(old_path)
if old_conf_load_func is not None:
return old_conf_load_func(old_path)
return json_util.load_json(old_path)
config = await hass.async_add_executor_job(load_old_config)
if config is None:
return await store.async_load()
return None
if old_conf_migrate_func is not None:
config = await old_conf_migrate_func(config)

View File

@ -37,7 +37,7 @@ def mock_get_newest_version_fixture():
@pytest.fixture(name="mock_get_uuid", autouse=True)
def mock_get_uuid_fixture():
"""Fixture to mock get_uuid."""
with patch("homeassistant.components.updater._load_uuid") as mock:
with patch("homeassistant.helpers.instance_id.async_get") as mock:
yield mock

View File

@ -0,0 +1,26 @@
"""Tests for instance ID helper."""
from tests.async_mock import patch
async def test_get_id_empty(hass, hass_storage):
"""Get unique ID."""
uuid = await hass.helpers.instance_id.async_get()
assert uuid is not None
# Assert it's stored
assert hass_storage["core.uuid"]["data"]["uuid"] == uuid
async def test_get_id_migrate(hass, hass_storage):
"""Migrate existing file."""
with patch(
"homeassistant.util.json.load_json", return_value={"uuid": "1234"}
), patch("os.path.isfile", return_value=True), patch("os.remove") as mock_remove:
uuid = await hass.helpers.instance_id.async_get()
assert uuid == "1234"
# Assert it's stored
assert hass_storage["core.uuid"]["data"]["uuid"] == uuid
# assert old deleted
assert len(mock_remove.mock_calls) == 1