Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ConfigStore to avoid needing to pass config_dir #114827

Merged
merged 4 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ def __init__(self, config_dir: str) -> None:
self.services = ServiceRegistry(self)
self.states = StateMachine(self.bus, self.loop)
self.config = Config(self, config_dir)
self.config.async_initialize()
self.components = loader.Components(self)
self.helpers = loader.Helpers(self)
self.state: CoreState = CoreState.not_running
Expand Down Expand Up @@ -2582,12 +2583,12 @@ async def _execute_service(
class Config:
"""Configuration settings for Home Assistant."""

_store: Config._ConfigStore

def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
"""Initialize a new config object."""
self.hass = hass

self._store = self._ConfigStore(self.hass, config_dir)

self.latitude: float = 0
self.longitude: float = 0

Expand Down Expand Up @@ -2638,6 +2639,13 @@ def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
# If Home Assistant is running in safe mode
self.safe_mode: bool = False

def async_initialize(self) -> None:
"""Finish initializing a config object.

This must be called before the config object is used.
"""
self._store = self._ConfigStore(self.hass)

def distance(self, lat: float, lon: float) -> float | None:
"""Calculate distance from Home Assistant.

Expand Down Expand Up @@ -2844,7 +2852,6 @@ async def _async_store(self) -> None:
"country": self.country,
"language": self.language,
}

await self._store.async_save(data)

# Circular dependency prevents us from generating the class at top level
Expand All @@ -2854,7 +2861,7 @@ async def _async_store(self) -> None:
class _ConfigStore(Store[dict[str, Any]]):
"""Class to help storing Config data."""

def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize storage class."""
super().__init__(
hass,
Expand All @@ -2863,7 +2870,6 @@ def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
private=True,
atomic_writes=True,
minor_version=CORE_STORAGE_MINOR_VERSION,
config_dir=config_dir,
)
self._original_unit_system: str | None = None # from old store 1.1

Expand Down
13 changes: 5 additions & 8 deletions homeassistant/helpers/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,15 @@ def load_old_config():
return config


def get_internal_store_manager(
hass: HomeAssistant, config_dir: str | None = None
) -> _StoreManager:
def get_internal_store_manager(hass: HomeAssistant) -> _StoreManager:
"""Get the store manager.
This function is not part of the API and should only be
used in the Home Assistant core internals. It is not
guaranteed to be stable.
"""
if STORAGE_MANAGER not in hass.data:
manager = _StoreManager(hass, config_dir or hass.config.config_dir)
manager = _StoreManager(hass)
hass.data[STORAGE_MANAGER] = manager
return hass.data[STORAGE_MANAGER]

Expand All @@ -111,13 +109,13 @@ class _StoreManager:
The store manager is used to cache and manage storage files.
"""

def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize storage manager class."""
self._hass = hass
self._invalidated: set[str] = set()
self._files: set[str] | None = None
self._data_preload: dict[str, json_util.JsonValueType] = {}
self._storage_path: Path = Path(config_dir).joinpath(STORAGE_DIR)
self._storage_path: Path = Path(hass.config.config_dir).joinpath(STORAGE_DIR)
self._cancel_cleanup: asyncio.TimerHandle | None = None

async def async_initialize(self) -> None:
Expand Down Expand Up @@ -246,7 +244,6 @@ def __init__(
encoder: type[JSONEncoder] | None = None,
minor_version: int = 1,
read_only: bool = False,
config_dir: str | None = None,
) -> None:
"""Initialize storage class."""
self.version = version
Expand All @@ -263,7 +260,7 @@ def __init__(
self._atomic_writes = atomic_writes
self._read_only = read_only
self._next_write_time = 0.0
self._manager = get_internal_store_manager(hass, config_dir)
self._manager = get_internal_store_manager(hass)

@cached_property
def path(self):
Expand Down
3 changes: 3 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2288,6 +2288,7 @@ async def test_additional_data_in_core_config(
) -> None:
"""Test that we can handle additional data in core configuration."""
config = ha.Config(hass, "/test/ha-config")
config.async_initialize()
hass_storage[ha.CORE_STORAGE_KEY] = {
"version": 1,
"data": {"location_name": "Test Name", "additional_valid_key": "value"},
Expand All @@ -2301,6 +2302,7 @@ async def test_incorrect_internal_external_url(
) -> None:
"""Test that we warn when detecting invalid internal/external url."""
config = ha.Config(hass, "/test/ha-config")
config.async_initialize()

hass_storage[ha.CORE_STORAGE_KEY] = {
"version": 1,
Expand All @@ -2314,6 +2316,7 @@ async def test_incorrect_internal_external_url(
assert "Invalid internal_url set" not in caplog.text

config = ha.Config(hass, "/test/ha-config")
config.async_initialize()

hass_storage[ha.CORE_STORAGE_KEY] = {
"version": 1,
Expand Down