From 5f44d0f8f9db03371164ff596f7b09615a5f6efe Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 17 May 2022 18:45:57 +0200 Subject: [PATCH] Clean up accessing storage.Store helper via hass (#72009) --- homeassistant/auth/auth_store.py | 7 ++--- homeassistant/auth/mfa_modules/notify.py | 9 ++++--- homeassistant/auth/mfa_modules/totp.py | 9 ++++--- homeassistant/auth/providers/homeassistant.py | 12 ++++++--- homeassistant/components/alexa/auth.py | 3 ++- .../components/ambiclimate/climate.py | 3 ++- .../components/ambiclimate/config_flow.py | 3 ++- .../components/analytics/analytics.py | 2 +- homeassistant/components/camera/prefs.py | 7 +++-- homeassistant/components/cloud/prefs.py | 3 ++- homeassistant/components/evohome/__init__.py | 3 ++- homeassistant/components/freebox/router.py | 3 ++- homeassistant/components/frontend/__init__.py | 8 +++--- homeassistant/components/frontend/storage.py | 6 +++-- homeassistant/components/hassio/__init__.py | 3 ++- homeassistant/components/http/auth.py | 5 ++-- homeassistant/components/icloud/__init__.py | 3 ++- .../components/icloud/config_flow.py | 9 +++---- .../components/mobile_app/__init__.py | 7 +++-- homeassistant/components/network/network.py | 5 ++-- .../components/smartthings/smartapp.py | 7 ++--- homeassistant/components/unifi/__init__.py | 3 ++- homeassistant/components/zha/core/store.py | 3 ++- homeassistant/core.py | 26 +++++++++++++++---- homeassistant/helpers/area_registry.py | 7 +++-- 25 files changed, 101 insertions(+), 55 deletions(-) diff --git a/homeassistant/auth/auth_store.py b/homeassistant/auth/auth_store.py index d2c3db79726..baf5a8bf3b3 100644 --- a/homeassistant/auth/auth_store.py +++ b/homeassistant/auth/auth_store.py @@ -10,6 +10,7 @@ from typing import Any from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.helpers.storage import Store from homeassistant.util import dt as dt_util from . import models @@ -45,8 +46,8 @@ class AuthStore: self._users: dict[str, models.User] | None = None self._groups: dict[str, models.Group] | None = None self._perm_lookup: PermissionLookup | None = None - self._store = hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True + self._store = Store( + hass, STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True ) self._lock = asyncio.Lock() @@ -315,7 +316,7 @@ class AuthStore: self._perm_lookup = perm_lookup = PermissionLookup(ent_reg, dev_reg) - if data is None: + if data is None or not isinstance(data, dict): self._set_defaults() return diff --git a/homeassistant/auth/mfa_modules/notify.py b/homeassistant/auth/mfa_modules/notify.py index 37b35a5087d..3872257a205 100644 --- a/homeassistant/auth/mfa_modules/notify.py +++ b/homeassistant/auth/mfa_modules/notify.py @@ -17,6 +17,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import ServiceNotFound from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.storage import Store from . import ( MULTI_FACTOR_AUTH_MODULE_SCHEMA, @@ -99,8 +100,8 @@ class NotifyAuthModule(MultiFactorAuthModule): """Initialize the user data store.""" super().__init__(hass, config) self._user_settings: _UsersDict | None = None - self._user_store = hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True + self._user_store = Store( + hass, STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True ) self._include = config.get(CONF_INCLUDE, []) self._exclude = config.get(CONF_EXCLUDE, []) @@ -118,7 +119,9 @@ class NotifyAuthModule(MultiFactorAuthModule): if self._user_settings is not None: return - if (data := await self._user_store.async_load()) is None: + if (data := await self._user_store.async_load()) is None or not isinstance( + data, dict + ): data = {STORAGE_USERS: {}} self._user_settings = { diff --git a/homeassistant/auth/mfa_modules/totp.py b/homeassistant/auth/mfa_modules/totp.py index bb5fc47469f..e503198f08b 100644 --- a/homeassistant/auth/mfa_modules/totp.py +++ b/homeassistant/auth/mfa_modules/totp.py @@ -10,6 +10,7 @@ import voluptuous as vol from homeassistant.auth.models import User from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResult +from homeassistant.helpers.storage import Store from . import ( MULTI_FACTOR_AUTH_MODULE_SCHEMA, @@ -76,8 +77,8 @@ class TotpAuthModule(MultiFactorAuthModule): """Initialize the user data store.""" super().__init__(hass, config) self._users: dict[str, str] | None = None - self._user_store = hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True + self._user_store = Store( + hass, STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True ) self._init_lock = asyncio.Lock() @@ -92,7 +93,9 @@ class TotpAuthModule(MultiFactorAuthModule): if self._users is not None: return - if (data := await self._user_store.async_load()) is None: + if (data := await self._user_store.async_load()) is None or not isinstance( + data, dict + ): data = {STORAGE_USERS: {}} self._users = data.get(STORAGE_USERS, {}) diff --git a/homeassistant/auth/providers/homeassistant.py b/homeassistant/auth/providers/homeassistant.py index 3971cb43080..cb95907c9b2 100644 --- a/homeassistant/auth/providers/homeassistant.py +++ b/homeassistant/auth/providers/homeassistant.py @@ -14,6 +14,7 @@ from homeassistant.const import CONF_ID from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.storage import Store from . import AUTH_PROVIDER_SCHEMA, AUTH_PROVIDERS, AuthProvider, LoginFlow from ..models import Credentials, UserMeta @@ -60,8 +61,8 @@ class Data: def __init__(self, hass: HomeAssistant) -> None: """Initialize the user data store.""" self.hass = hass - self._store = hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True + self._store = Store( + hass, STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True ) self._data: dict[str, Any] | None = None # Legacy mode will allow usernames to start/end with whitespace @@ -79,7 +80,9 @@ class Data: async def async_load(self) -> None: """Load stored data.""" - if (data := await self._store.async_load()) is None: + if (data := await self._store.async_load()) is None or not isinstance( + data, dict + ): data = {"users": []} seen: set[str] = set() @@ -203,7 +206,8 @@ class Data: async def async_save(self) -> None: """Save data.""" - await self._store.async_save(self._data) + if self._data is not None: + await self._store.async_save(self._data) @AUTH_PROVIDERS.register("homeassistant") diff --git a/homeassistant/components/alexa/auth.py b/homeassistant/components/alexa/auth.py index d888b91a39e..1ce20d154bd 100644 --- a/homeassistant/components/alexa/auth.py +++ b/homeassistant/components/alexa/auth.py @@ -11,6 +11,7 @@ import async_timeout from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET from homeassistant.core import callback from homeassistant.helpers import aiohttp_client +from homeassistant.helpers.storage import Store from homeassistant.util import dt _LOGGER = logging.getLogger(__name__) @@ -37,7 +38,7 @@ class Auth: self.client_secret = client_secret self._prefs = None - self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) self._get_token_lock = asyncio.Lock() diff --git a/homeassistant/components/ambiclimate/climate.py b/homeassistant/components/ambiclimate/climate.py index 0bf4ec35526..93d9348655f 100644 --- a/homeassistant/components/ambiclimate/climate.py +++ b/homeassistant/components/ambiclimate/climate.py @@ -23,6 +23,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from .const import ( @@ -63,7 +64,7 @@ async def async_setup_entry( """Set up the Ambiclimate device from config entry.""" config = entry.data websession = async_get_clientsession(hass) - store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + store = Store(hass, STORAGE_VERSION, STORAGE_KEY) token_info = await store.async_load() oauth = ambiclimate.AmbiclimateOAuth( diff --git a/homeassistant/components/ambiclimate/config_flow.py b/homeassistant/components/ambiclimate/config_flow.py index e93c21ce5ba..bde5e41e392 100644 --- a/homeassistant/components/ambiclimate/config_flow.py +++ b/homeassistant/components/ambiclimate/config_flow.py @@ -10,6 +10,7 @@ from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET from homeassistant.core import callback from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.network import get_url +from homeassistant.helpers.storage import Store from .const import ( AUTH_CALLBACK_NAME, @@ -102,7 +103,7 @@ class AmbiclimateFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): _LOGGER.error("Failed to get access token", exc_info=True) return None - store = self.hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + store = Store(self.hass, STORAGE_VERSION, STORAGE_KEY) await store.async_save(token_info) return token_info diff --git a/homeassistant/components/analytics/analytics.py b/homeassistant/components/analytics/analytics.py index 39c813b2696..802aa33585a 100644 --- a/homeassistant/components/analytics/analytics.py +++ b/homeassistant/components/analytics/analytics.py @@ -71,7 +71,7 @@ class Analytics: ATTR_ONBOARDED: False, ATTR_UUID: None, } - self._store: Store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) @property def preferences(self) -> dict: diff --git a/homeassistant/components/camera/prefs.py b/homeassistant/components/camera/prefs.py index 53a149ff7d8..3d54c10d09a 100644 --- a/homeassistant/components/camera/prefs.py +++ b/homeassistant/components/camera/prefs.py @@ -4,6 +4,7 @@ from __future__ import annotations from typing import Final from homeassistant.core import HomeAssistant +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import UNDEFINED, UndefinedType from .const import DOMAIN, PREF_PRELOAD_STREAM @@ -35,12 +36,14 @@ class CameraPreferences: def __init__(self, hass: HomeAssistant) -> None: """Initialize camera prefs.""" self._hass = hass - self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) self._prefs: dict[str, dict[str, bool]] | None = None async def async_initialize(self) -> None: """Finish initializing the preferences.""" - if (prefs := await self._store.async_load()) is None: + if (prefs := await self._store.async_load()) is None or not isinstance( + prefs, dict + ): prefs = {} self._prefs = prefs diff --git a/homeassistant/components/cloud/prefs.py b/homeassistant/components/cloud/prefs.py index e6747c42c45..275c2a56326 100644 --- a/homeassistant/components/cloud/prefs.py +++ b/homeassistant/components/cloud/prefs.py @@ -5,6 +5,7 @@ from homeassistant.auth.const import GROUP_ID_ADMIN from homeassistant.auth.models import User from homeassistant.components import webhook from homeassistant.core import callback +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import UNDEFINED from homeassistant.util.logging import async_create_catching_coro @@ -46,7 +47,7 @@ class CloudPreferences: def __init__(self, hass): """Initialize cloud prefs.""" self._hass = hass - self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) self._prefs = None self._listeners = [] diff --git a/homeassistant/components/evohome/__init__.py b/homeassistant/components/evohome/__init__.py index 0085eb701d0..aa09bb666f4 100644 --- a/homeassistant/components/evohome/__init__.py +++ b/homeassistant/components/evohome/__init__.py @@ -35,6 +35,7 @@ from homeassistant.helpers.dispatcher import ( from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import async_call_later from homeassistant.helpers.service import verify_domain_control +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType import homeassistant.util.dt as dt_util @@ -198,7 +199,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: user_data = tokens.pop(USER_DATA, None) return (tokens, user_data) - store = hass.helpers.storage.Store(STORAGE_VER, STORAGE_KEY) + store = Store(hass, STORAGE_VER, STORAGE_KEY) tokens, user_data = await load_auth_tokens(store) client_v2 = evohomeasync2.EvohomeClient( diff --git a/homeassistant/components/freebox/router.py b/homeassistant/components/freebox/router.py index 0d20545fdcd..70fc7b86a40 100644 --- a/homeassistant/components/freebox/router.py +++ b/homeassistant/components/freebox/router.py @@ -18,6 +18,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.storage import Store from homeassistant.util import slugify from .const import ( @@ -32,7 +33,7 @@ from .const import ( async def get_api(hass: HomeAssistant, host: str) -> Freepybox: """Get the Freebox API.""" - freebox_path = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY).path + freebox_path = Store(hass, STORAGE_VERSION, STORAGE_KEY).path if not os.path.exists(freebox_path): await hass.async_add_executor_job(os.makedirs, freebox_path) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 91b9c9a126f..c1deb02fc6a 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -22,6 +22,7 @@ from homeassistant.const import CONF_MODE, CONF_NAME, EVENT_THEMES_UPDATED from homeassistant.core import HomeAssistant, ServiceCall, callback from homeassistant.helpers import service import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.storage import Store from homeassistant.helpers.translation import async_get_translations from homeassistant.helpers.typing import ConfigType from homeassistant.loader import async_get_integration, bind_hass @@ -389,11 +390,12 @@ async def _async_setup_themes( """Set up themes data and services.""" hass.data[DATA_THEMES] = themes or {} - store = hass.data[DATA_THEMES_STORE] = hass.helpers.storage.Store( - THEMES_STORAGE_VERSION, THEMES_STORAGE_KEY + store = hass.data[DATA_THEMES_STORE] = Store( + hass, THEMES_STORAGE_VERSION, THEMES_STORAGE_KEY ) - theme_data = await store.async_load() or {} + if not (theme_data := await store.async_load()) or not isinstance(theme_data, dict): + theme_data = {} theme_name = theme_data.get(DATA_DEFAULT_THEME, DEFAULT_THEME) dark_theme_name = theme_data.get(DATA_DEFAULT_DARK_THEME) diff --git a/homeassistant/components/frontend/storage.py b/homeassistant/components/frontend/storage.py index e5100ca3ab2..bfda566de55 100644 --- a/homeassistant/components/frontend/storage.py +++ b/homeassistant/components/frontend/storage.py @@ -35,8 +35,10 @@ def with_store(orig_func: Callable) -> Callable: user_id = connection.user.id if (store := stores.get(user_id)) is None: - store = stores[user_id] = hass.helpers.storage.Store( - STORAGE_VERSION_USER_DATA, f"frontend.user_data_{connection.user.id}" + store = stores[user_id] = Store( + hass, + STORAGE_VERSION_USER_DATA, + f"frontend.user_data_{connection.user.id}", ) if user_id not in data: diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index a3689f61746..34773987014 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -41,6 +41,7 @@ from homeassistant.helpers.device_registry import ( async_get_registry, ) from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.loader import bind_hass @@ -519,7 +520,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: if not await hassio.is_connected(): _LOGGER.warning("Not connected with the supervisor / system too busy!") - store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + store = Store(hass, STORAGE_VERSION, STORAGE_KEY) if (data := await store.async_load()) is None: data = {} diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py index 4788680a6fa..dab6abede4c 100644 --- a/homeassistant/components/http/auth.py +++ b/homeassistant/components/http/auth.py @@ -17,6 +17,7 @@ from homeassistant.auth.const import GROUP_ID_READ_ONLY from homeassistant.auth.models import User from homeassistant.components import websocket_api from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.storage import Store from homeassistant.util import dt as dt_util from homeassistant.util.network import is_local @@ -108,8 +109,8 @@ def async_user_not_allowed_do_auth( async def async_setup_auth(hass: HomeAssistant, app: Application) -> None: """Create auth middleware for the app.""" - store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) - if (data := await store.async_load()) is None: + store = Store(hass, STORAGE_VERSION, STORAGE_KEY) + if (data := await store.async_load()) is None or not isinstance(data, dict): data = {} refresh_token = None diff --git a/homeassistant/components/icloud/__init__.py b/homeassistant/components/icloud/__init__.py index 17cc15b195a..8175cf43f27 100644 --- a/homeassistant/components/icloud/__init__.py +++ b/homeassistant/components/icloud/__init__.py @@ -5,6 +5,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant, ServiceCall import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.storage import Store from homeassistant.util import slugify from .account import IcloudAccount @@ -81,7 +82,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: if entry.unique_id is None: hass.config_entries.async_update_entry(entry, unique_id=username) - icloud_dir = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + icloud_dir = Store(hass, STORAGE_VERSION, STORAGE_KEY) account = IcloudAccount( hass, diff --git a/homeassistant/components/icloud/config_flow.py b/homeassistant/components/icloud/config_flow.py index f3630abfdaa..a4c29acff75 100644 --- a/homeassistant/components/icloud/config_flow.py +++ b/homeassistant/components/icloud/config_flow.py @@ -13,6 +13,7 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.helpers.storage import Store from .const import ( CONF_GPS_ACCURACY_THRESHOLD, @@ -113,7 +114,7 @@ class IcloudFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): PyiCloudService, self._username, self._password, - self.hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY).path, + Store(self.hass, STORAGE_VERSION, STORAGE_KEY).path, True, None, self._with_family, @@ -162,7 +163,7 @@ class IcloudFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Handle a flow initiated by the user.""" errors = {} - icloud_dir = self.hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + icloud_dir = Store(self.hass, STORAGE_VERSION, STORAGE_KEY) if not os.path.exists(icloud_dir.path): await self.hass.async_add_executor_job(os.makedirs, icloud_dir.path) @@ -276,9 +277,7 @@ class IcloudFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): PyiCloudService, self._username, self._password, - self.hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY - ).path, + Store(self.hass, STORAGE_VERSION, STORAGE_KEY).path, True, None, self._with_family, diff --git a/homeassistant/components/mobile_app/__init__.py b/homeassistant/components/mobile_app/__init__.py index 9f92285625b..1b308705624 100644 --- a/homeassistant/components/mobile_app/__init__.py +++ b/homeassistant/components/mobile_app/__init__.py @@ -10,6 +10,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_DEVICE_ID, CONF_WEBHOOK_ID, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, discovery +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType from . import websocket_api @@ -37,8 +38,10 @@ PLATFORMS = [Platform.SENSOR, Platform.BINARY_SENSOR, Platform.DEVICE_TRACKER] async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the mobile app component.""" - store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) - if (app_config := await store.async_load()) is None: + store = Store(hass, STORAGE_VERSION, STORAGE_KEY) + if (app_config := await store.async_load()) is None or not isinstance( + app_config, dict + ): app_config = { DATA_CONFIG_ENTRIES: {}, DATA_DELETED_IDS: [], diff --git a/homeassistant/components/network/network.py b/homeassistant/components/network/network.py index 6ec9941da3c..b2caf6438bd 100644 --- a/homeassistant/components/network/network.py +++ b/homeassistant/components/network/network.py @@ -6,6 +6,7 @@ from typing import Any, cast from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.singleton import singleton +from homeassistant.helpers.storage import Store from .const import ( ATTR_CONFIGURED_ADAPTERS, @@ -37,9 +38,7 @@ class Network: def __init__(self, hass: HomeAssistant) -> None: """Initialize the Network class.""" - self._store = hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY, atomic_writes=True - ) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY, atomic_writes=True) self._data: dict[str, Any] = {} self.adapters: list[Adapter] = [] diff --git a/homeassistant/components/smartthings/smartapp.py b/homeassistant/components/smartthings/smartapp.py index a6d35c40335..28b60b57447 100644 --- a/homeassistant/components/smartthings/smartapp.py +++ b/homeassistant/components/smartthings/smartapp.py @@ -32,6 +32,7 @@ from homeassistant.helpers.dispatcher import ( async_dispatcher_send, ) from homeassistant.helpers.network import NoURLAvailableError, get_url +from homeassistant.helpers.storage import Store from .const import ( APP_NAME_PREFIX, @@ -210,8 +211,8 @@ async def setup_smartapp_endpoint(hass: HomeAssistant): return # Get/create config to store a unique id for this hass instance. - store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) - if not (config := await store.async_load()): + store = Store(hass, STORAGE_VERSION, STORAGE_KEY) + if not (config := await store.async_load()) or not isinstance(config, dict): # Create config config = { CONF_INSTANCE_ID: str(uuid4()), @@ -282,7 +283,7 @@ async def unload_smartapp_endpoint(hass: HomeAssistant): if cloudhook_url and cloud.async_is_logged_in(hass): await cloud.async_delete_cloudhook(hass, hass.data[DOMAIN][CONF_WEBHOOK_ID]) # Remove cloudhook from storage - store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + store = Store(hass, STORAGE_VERSION, STORAGE_KEY) await store.async_save( { CONF_INSTANCE_ID: hass.data[DOMAIN][CONF_INSTANCE_ID], diff --git a/homeassistant/components/unifi/__init__.py b/homeassistant/components/unifi/__init__.py index a396f8ce38f..7a874aff993 100644 --- a/homeassistant/components/unifi/__init__.py +++ b/homeassistant/components/unifi/__init__.py @@ -4,6 +4,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import device_registry as dr from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType from .const import ( @@ -106,7 +107,7 @@ class UnifiWirelessClients: """Set up client storage.""" self.hass = hass self.data = {} - self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) async def async_load(self): """Load data from file.""" diff --git a/homeassistant/components/zha/core/store.py b/homeassistant/components/zha/core/store.py index 5d33375ace2..28983bdb427 100644 --- a/homeassistant/components/zha/core/store.py +++ b/homeassistant/components/zha/core/store.py @@ -10,6 +10,7 @@ from typing import cast import attr from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.storage import Store from homeassistant.loader import bind_hass from .typing import ZhaDeviceType @@ -38,7 +39,7 @@ class ZhaStorage: """Initialize the zha device storage.""" self.hass: HomeAssistant = hass self.devices: MutableMapping[str, ZhaDeviceEntry] = {} - self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) @callback def async_create_device(self, device: ZhaDeviceType) -> ZhaDeviceEntry: diff --git a/homeassistant/core.py b/homeassistant/core.py index 973a940ffbc..7fcf07d9c66 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1895,11 +1895,19 @@ class Config: async def async_load(self) -> None: """Load [homeassistant] core config.""" - store = self.hass.helpers.storage.Store( - CORE_STORAGE_VERSION, CORE_STORAGE_KEY, private=True, atomic_writes=True + # Circular dep + # pylint: disable=import-outside-toplevel + from .helpers.storage import Store + + store = Store( + self.hass, + CORE_STORAGE_VERSION, + CORE_STORAGE_KEY, + private=True, + atomic_writes=True, ) - if not (data := await store.async_load()): + if not (data := await store.async_load()) or not isinstance(data, dict): return # In 2021.9 we fixed validation to disallow a path (because that's never correct) @@ -1931,6 +1939,10 @@ class Config: async def async_store(self) -> None: """Store [homeassistant] core config.""" + # Circular dep + # pylint: disable=import-outside-toplevel + from .helpers.storage import Store + data = { "latitude": self.latitude, "longitude": self.longitude, @@ -1943,7 +1955,11 @@ class Config: "currency": self.currency, } - store = self.hass.helpers.storage.Store( - CORE_STORAGE_VERSION, CORE_STORAGE_KEY, private=True, atomic_writes=True + store = Store( + self.hass, + CORE_STORAGE_VERSION, + CORE_STORAGE_KEY, + private=True, + atomic_writes=True, ) await store.async_save(data) diff --git a/homeassistant/helpers/area_registry.py b/homeassistant/helpers/area_registry.py index 660c433d8c7..ad4930825c8 100644 --- a/homeassistant/helpers/area_registry.py +++ b/homeassistant/helpers/area_registry.py @@ -12,6 +12,7 @@ from homeassistant.loader import bind_hass from homeassistant.util import slugify from . import device_registry as dr, entity_registry as er +from .storage import Store from .typing import UNDEFINED, UndefinedType DATA_REGISTRY = "area_registry" @@ -47,9 +48,7 @@ class AreaRegistry: """Initialize the area registry.""" self.hass = hass self.areas: MutableMapping[str, AreaEntry] = {} - self._store = hass.helpers.storage.Store( - STORAGE_VERSION, STORAGE_KEY, atomic_writes=True - ) + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY, atomic_writes=True) self._normalized_name_area_idx: dict[str, str] = {} @callback @@ -176,7 +175,7 @@ class AreaRegistry: areas: MutableMapping[str, AreaEntry] = OrderedDict() - if data is not None: + if isinstance(data, dict): for area in data["areas"]: normalized_name = normalize_area_name(area["name"]) areas[area["id"]] = AreaEntry(