Merge system options into pref properties (#51347)
* Make system options future proof * Update tests * Add types
This commit is contained in:
parent
9e3ee73b8b
commit
ee2c950716
27 changed files with 188 additions and 245 deletions
|
@ -1,4 +1,6 @@
|
|||
"""Http views to control the config manager."""
|
||||
from __future__ import annotations
|
||||
|
||||
import aiohttp.web_exceptions
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -7,7 +9,7 @@ from homeassistant.auth.permissions.const import CAT_CONFIG_ENTRIES, POLICY_EDIT
|
|||
from homeassistant.components import websocket_api
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
from homeassistant.const import HTTP_FORBIDDEN, HTTP_NOT_FOUND
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import Unauthorized
|
||||
from homeassistant.helpers.data_entry_flow import (
|
||||
FlowManagerIndexView,
|
||||
|
@ -31,7 +33,6 @@ async def async_setup(hass):
|
|||
hass.components.websocket_api.async_register_command(config_entry_disable)
|
||||
hass.components.websocket_api.async_register_command(config_entry_update)
|
||||
hass.components.websocket_api.async_register_command(config_entries_progress)
|
||||
hass.components.websocket_api.async_register_command(system_options_update)
|
||||
hass.components.websocket_api.async_register_command(ignore_config_flow)
|
||||
|
||||
return True
|
||||
|
@ -230,14 +231,21 @@ def config_entries_progress(hass, connection, msg):
|
|||
)
|
||||
|
||||
|
||||
def send_entry_not_found(connection, msg_id):
|
||||
def send_entry_not_found(
|
||||
connection: websocket_api.ActiveConnection, msg_id: int
|
||||
) -> None:
|
||||
"""Send Config entry not found error."""
|
||||
connection.send_error(
|
||||
msg_id, websocket_api.const.ERR_NOT_FOUND, "Config entry not found"
|
||||
)
|
||||
|
||||
|
||||
def get_entry(hass, connection, entry_id, msg_id):
|
||||
def get_entry(
|
||||
hass: HomeAssistant,
|
||||
connection: websocket_api.ActiveConnection,
|
||||
entry_id: str,
|
||||
msg_id: int,
|
||||
) -> config_entries.ConfigEntry | None:
|
||||
"""Get entry, send error message if it doesn't exist."""
|
||||
entry = hass.config_entries.async_get_entry(entry_id)
|
||||
if entry is None:
|
||||
|
@ -249,49 +257,13 @@ def get_entry(hass, connection, entry_id, msg_id):
|
|||
@websocket_api.async_response
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
"type": "config_entries/system_options/update",
|
||||
"type": "config_entries/update",
|
||||
"entry_id": str,
|
||||
vol.Optional("disable_new_entities"): bool,
|
||||
vol.Optional("disable_polling"): bool,
|
||||
vol.Optional("title"): str,
|
||||
vol.Optional("pref_disable_new_entities"): bool,
|
||||
vol.Optional("pref_disable_polling"): bool,
|
||||
}
|
||||
)
|
||||
async def system_options_update(hass, connection, msg):
|
||||
"""Update config entry system options."""
|
||||
changes = dict(msg)
|
||||
changes.pop("id")
|
||||
changes.pop("type")
|
||||
changes.pop("entry_id")
|
||||
|
||||
entry = get_entry(hass, connection, msg["entry_id"], msg["id"])
|
||||
if entry is None:
|
||||
return
|
||||
|
||||
old_disable_polling = entry.system_options.disable_polling
|
||||
|
||||
hass.config_entries.async_update_entry(entry, system_options=changes)
|
||||
|
||||
result = {
|
||||
"system_options": entry.system_options.as_dict(),
|
||||
"require_restart": False,
|
||||
}
|
||||
|
||||
if (
|
||||
old_disable_polling != entry.system_options.disable_polling
|
||||
and entry.state is config_entries.ConfigEntryState.LOADED
|
||||
):
|
||||
if not await hass.config_entries.async_reload(entry.entry_id):
|
||||
result["require_restart"] = (
|
||||
entry.state is config_entries.ConfigEntryState.FAILED_UNLOAD
|
||||
)
|
||||
|
||||
connection.send_result(msg["id"], result)
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
@websocket_api.websocket_command(
|
||||
{"type": "config_entries/update", "entry_id": str, vol.Optional("title"): str}
|
||||
)
|
||||
async def config_entry_update(hass, connection, msg):
|
||||
"""Update config entry."""
|
||||
changes = dict(msg)
|
||||
|
@ -303,8 +275,25 @@ async def config_entry_update(hass, connection, msg):
|
|||
if entry is None:
|
||||
return
|
||||
|
||||
old_disable_polling = entry.pref_disable_polling
|
||||
|
||||
hass.config_entries.async_update_entry(entry, **changes)
|
||||
connection.send_result(msg["id"], entry_json(entry))
|
||||
|
||||
result = {
|
||||
"config_entry": entry_json(entry),
|
||||
"require_restart": False,
|
||||
}
|
||||
|
||||
if (
|
||||
old_disable_polling != entry.pref_disable_polling
|
||||
and entry.state is config_entries.ConfigEntryState.LOADED
|
||||
):
|
||||
if not await hass.config_entries.async_reload(entry.entry_id):
|
||||
result["require_restart"] = (
|
||||
entry.state is config_entries.ConfigEntryState.FAILED_UNLOAD
|
||||
)
|
||||
|
||||
connection.send_result(msg["id"], result)
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
|
@ -391,7 +380,8 @@ def entry_json(entry: config_entries.ConfigEntry) -> dict:
|
|||
"state": entry.state.value,
|
||||
"supports_options": supports_options,
|
||||
"supports_unload": entry.supports_unload,
|
||||
"system_options": entry.system_options.as_dict(),
|
||||
"pref_disable_new_entities": entry.pref_disable_new_entities,
|
||||
"pref_disable_polling": entry.pref_disable_polling,
|
||||
"disabled_by": entry.disabled_by,
|
||||
"reason": entry.reason,
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ from types import MappingProxyType, MethodType
|
|||
from typing import Any, Callable, Optional, cast
|
||||
import weakref
|
||||
|
||||
import attr
|
||||
|
||||
from homeassistant import data_entry_flow, loader
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback
|
||||
|
@ -152,7 +150,8 @@ class ConfigEntry:
|
|||
"options",
|
||||
"unique_id",
|
||||
"supports_unload",
|
||||
"system_options",
|
||||
"pref_disable_new_entities",
|
||||
"pref_disable_polling",
|
||||
"source",
|
||||
"state",
|
||||
"disabled_by",
|
||||
|
@ -170,7 +169,8 @@ class ConfigEntry:
|
|||
title: str,
|
||||
data: Mapping[str, Any],
|
||||
source: str,
|
||||
system_options: dict,
|
||||
pref_disable_new_entities: bool | None = None,
|
||||
pref_disable_polling: bool | None = None,
|
||||
options: Mapping[str, Any] | None = None,
|
||||
unique_id: str | None = None,
|
||||
entry_id: str | None = None,
|
||||
|
@ -197,7 +197,15 @@ class ConfigEntry:
|
|||
self.options = MappingProxyType(options or {})
|
||||
|
||||
# Entry system options
|
||||
self.system_options = SystemOptions(**system_options)
|
||||
if pref_disable_new_entities is None:
|
||||
pref_disable_new_entities = False
|
||||
|
||||
self.pref_disable_new_entities = pref_disable_new_entities
|
||||
|
||||
if pref_disable_polling is None:
|
||||
pref_disable_polling = False
|
||||
|
||||
self.pref_disable_polling = pref_disable_polling
|
||||
|
||||
# Source of the configuration (user, discovery, cloud)
|
||||
self.source = source
|
||||
|
@ -535,7 +543,8 @@ class ConfigEntry:
|
|||
"title": self.title,
|
||||
"data": dict(self.data),
|
||||
"options": dict(self.options),
|
||||
"system_options": self.system_options.as_dict(),
|
||||
"pref_disable_new_entities": self.pref_disable_new_entities,
|
||||
"pref_disable_polling": self.pref_disable_polling,
|
||||
"source": self.source,
|
||||
"unique_id": self.unique_id,
|
||||
"disabled_by": self.disabled_by,
|
||||
|
@ -652,7 +661,6 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager):
|
|||
title=result["title"],
|
||||
data=result["data"],
|
||||
options=result["options"],
|
||||
system_options={},
|
||||
source=flow.context["source"],
|
||||
unique_id=flow.unique_id,
|
||||
)
|
||||
|
@ -845,8 +853,18 @@ class ConfigEntries:
|
|||
self._entries = {}
|
||||
return
|
||||
|
||||
self._entries = {
|
||||
entry["entry_id"]: ConfigEntry(
|
||||
entries = {}
|
||||
|
||||
for entry in config["entries"]:
|
||||
pref_disable_new_entities = entry.get("pref_disable_new_entities")
|
||||
|
||||
# Between 0.98 and 2021.6 we stored 'disable_new_entities' in a system options dictionary
|
||||
if pref_disable_new_entities is None and "system_options" in entry:
|
||||
pref_disable_new_entities = entry.get("system_options", {}).get(
|
||||
"disable_new_entities"
|
||||
)
|
||||
|
||||
entries[entry["entry_id"]] = ConfigEntry(
|
||||
version=entry["version"],
|
||||
domain=entry["domain"],
|
||||
entry_id=entry["entry_id"],
|
||||
|
@ -855,15 +873,16 @@ class ConfigEntries:
|
|||
title=entry["title"],
|
||||
# New in 0.89
|
||||
options=entry.get("options"),
|
||||
# New in 0.98
|
||||
system_options=entry.get("system_options", {}),
|
||||
# New in 0.104
|
||||
unique_id=entry.get("unique_id"),
|
||||
# New in 2021.3
|
||||
disabled_by=entry.get("disabled_by"),
|
||||
# New in 2021.6
|
||||
pref_disable_new_entities=pref_disable_new_entities,
|
||||
pref_disable_polling=entry.get("pref_disable_polling"),
|
||||
)
|
||||
for entry in config["entries"]
|
||||
}
|
||||
|
||||
self._entries = entries
|
||||
|
||||
async def async_setup(self, entry_id: str) -> bool:
|
||||
"""Set up a config entry.
|
||||
|
@ -962,11 +981,12 @@ class ConfigEntries:
|
|||
self,
|
||||
entry: ConfigEntry,
|
||||
*,
|
||||
unique_id: str | dict | None | UndefinedType = UNDEFINED,
|
||||
title: str | dict | UndefinedType = UNDEFINED,
|
||||
unique_id: str | None | UndefinedType = UNDEFINED,
|
||||
title: str | UndefinedType = UNDEFINED,
|
||||
data: dict | UndefinedType = UNDEFINED,
|
||||
options: Mapping[str, Any] | UndefinedType = UNDEFINED,
|
||||
system_options: dict | UndefinedType = UNDEFINED,
|
||||
pref_disable_new_entities: bool | UndefinedType = UNDEFINED,
|
||||
pref_disable_polling: bool | UndefinedType = UNDEFINED,
|
||||
) -> bool:
|
||||
"""Update a config entry.
|
||||
|
||||
|
@ -978,13 +998,17 @@ class ConfigEntries:
|
|||
"""
|
||||
changed = False
|
||||
|
||||
if unique_id is not UNDEFINED and entry.unique_id != unique_id:
|
||||
changed = True
|
||||
entry.unique_id = cast(Optional[str], unique_id)
|
||||
for attr, value in (
|
||||
("unique_id", unique_id),
|
||||
("title", title),
|
||||
("pref_disable_new_entities", pref_disable_new_entities),
|
||||
("pref_disable_polling", pref_disable_polling),
|
||||
):
|
||||
if value == UNDEFINED or getattr(entry, attr) == value:
|
||||
continue
|
||||
|
||||
if title is not UNDEFINED and entry.title != title:
|
||||
setattr(entry, attr, value)
|
||||
changed = True
|
||||
entry.title = cast(str, title)
|
||||
|
||||
if data is not UNDEFINED and entry.data != data: # type: ignore
|
||||
changed = True
|
||||
|
@ -994,11 +1018,6 @@ class ConfigEntries:
|
|||
changed = True
|
||||
entry.options = MappingProxyType(options)
|
||||
|
||||
if system_options is not UNDEFINED:
|
||||
old_system_options = entry.system_options.as_dict()
|
||||
entry.system_options.update(**system_options)
|
||||
changed = entry.system_options.as_dict() != old_system_options
|
||||
|
||||
if not changed:
|
||||
return False
|
||||
|
||||
|
@ -1401,34 +1420,6 @@ class OptionsFlow(data_entry_flow.FlowHandler):
|
|||
handler: str
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
class SystemOptions:
|
||||
"""Config entry system options."""
|
||||
|
||||
disable_new_entities: bool = attr.ib(default=False)
|
||||
disable_polling: bool = attr.ib(default=False)
|
||||
|
||||
def update(
|
||||
self,
|
||||
*,
|
||||
disable_new_entities: bool | UndefinedType = UNDEFINED,
|
||||
disable_polling: bool | UndefinedType = UNDEFINED,
|
||||
) -> None:
|
||||
"""Update properties."""
|
||||
if disable_new_entities is not UNDEFINED:
|
||||
self.disable_new_entities = disable_new_entities
|
||||
|
||||
if disable_polling is not UNDEFINED:
|
||||
self.disable_polling = disable_polling
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
"""Return dictionary version of this config entries system options."""
|
||||
return {
|
||||
"disable_new_entities": self.disable_new_entities,
|
||||
"disable_polling": self.disable_polling,
|
||||
}
|
||||
|
||||
|
||||
class EntityRegistryDisabledHandler:
|
||||
"""Handler to handle when entities related to config entries updating disabled_by."""
|
||||
|
||||
|
|
|
@ -397,7 +397,7 @@ class EntityPlatform:
|
|||
raise
|
||||
|
||||
if (
|
||||
(self.config_entry and self.config_entry.system_options.disable_polling)
|
||||
(self.config_entry and self.config_entry.pref_disable_polling)
|
||||
or self._async_unsub_polling is not None
|
||||
or not any(entity.should_poll for entity in self.entities.values())
|
||||
):
|
||||
|
|
|
@ -286,7 +286,7 @@ class EntityRegistry:
|
|||
if (
|
||||
disabled_by is None
|
||||
and config_entry
|
||||
and config_entry.system_options.disable_new_entities
|
||||
and config_entry.pref_disable_new_entities
|
||||
):
|
||||
disabled_by = DISABLED_INTEGRATION
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ class DataUpdateCoordinator(Generic[T]):
|
|||
if self.update_interval is None:
|
||||
return
|
||||
|
||||
if self.config_entry and self.config_entry.system_options.disable_polling:
|
||||
if self.config_entry and self.config_entry.pref_disable_polling:
|
||||
return
|
||||
|
||||
if self._unsub_refresh:
|
||||
|
|
|
@ -732,7 +732,8 @@ class MockConfigEntry(config_entries.ConfigEntry):
|
|||
title="Mock Title",
|
||||
state=None,
|
||||
options={},
|
||||
system_options={},
|
||||
pref_disable_new_entities=None,
|
||||
pref_disable_polling=None,
|
||||
unique_id=None,
|
||||
disabled_by=None,
|
||||
reason=None,
|
||||
|
@ -742,7 +743,8 @@ class MockConfigEntry(config_entries.ConfigEntry):
|
|||
"entry_id": entry_id or uuid_util.random_uuid_hex(),
|
||||
"domain": domain,
|
||||
"data": data or {},
|
||||
"system_options": system_options,
|
||||
"pref_disable_new_entities": pref_disable_new_entities,
|
||||
"pref_disable_polling": pref_disable_polling,
|
||||
"options": options,
|
||||
"version": version,
|
||||
"title": title,
|
||||
|
|
|
@ -29,7 +29,6 @@ FIXTURE_CONFIG_ENTRY = {
|
|||
CONF_REGION: FIXTURE_USER_INPUT[CONF_REGION],
|
||||
},
|
||||
"options": {CONF_READ_ONLY: False, CONF_USE_LOCATION: False},
|
||||
"system_options": {"disable_new_entities": False},
|
||||
"source": config_entries.SOURCE_USER,
|
||||
"unique_id": f"{FIXTURE_USER_INPUT[CONF_REGION]}-{FIXTURE_USER_INPUT[CONF_REGION]}",
|
||||
}
|
||||
|
|
|
@ -87,10 +87,8 @@ async def test_get_entries(hass, client):
|
|||
"state": core_ce.ConfigEntryState.NOT_LOADED.value,
|
||||
"supports_options": True,
|
||||
"supports_unload": True,
|
||||
"system_options": {
|
||||
"disable_new_entities": False,
|
||||
"disable_polling": False,
|
||||
},
|
||||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"disabled_by": None,
|
||||
"reason": None,
|
||||
},
|
||||
|
@ -101,10 +99,8 @@ async def test_get_entries(hass, client):
|
|||
"state": core_ce.ConfigEntryState.SETUP_ERROR.value,
|
||||
"supports_options": False,
|
||||
"supports_unload": False,
|
||||
"system_options": {
|
||||
"disable_new_entities": False,
|
||||
"disable_polling": False,
|
||||
},
|
||||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"disabled_by": None,
|
||||
"reason": "Unsupported API",
|
||||
},
|
||||
|
@ -115,10 +111,8 @@ async def test_get_entries(hass, client):
|
|||
"state": core_ce.ConfigEntryState.NOT_LOADED.value,
|
||||
"supports_options": False,
|
||||
"supports_unload": False,
|
||||
"system_options": {
|
||||
"disable_new_entities": False,
|
||||
"disable_polling": False,
|
||||
},
|
||||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"disabled_by": core_ce.DISABLED_USER,
|
||||
"reason": None,
|
||||
},
|
||||
|
@ -340,10 +334,8 @@ async def test_create_account(hass, client, enable_custom_integrations):
|
|||
"state": core_ce.ConfigEntryState.LOADED.value,
|
||||
"supports_options": False,
|
||||
"supports_unload": False,
|
||||
"system_options": {
|
||||
"disable_new_entities": False,
|
||||
"disable_polling": False,
|
||||
},
|
||||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"title": "Test Entry",
|
||||
"reason": None,
|
||||
},
|
||||
|
@ -415,10 +407,8 @@ async def test_two_step_flow(hass, client, enable_custom_integrations):
|
|||
"state": core_ce.ConfigEntryState.LOADED.value,
|
||||
"supports_options": False,
|
||||
"supports_unload": False,
|
||||
"system_options": {
|
||||
"disable_new_entities": False,
|
||||
"disable_polling": False,
|
||||
},
|
||||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"title": "user-title",
|
||||
"reason": None,
|
||||
},
|
||||
|
@ -698,7 +688,7 @@ async def test_two_step_options_flow(hass, client):
|
|||
}
|
||||
|
||||
|
||||
async def test_update_system_options(hass, hass_ws_client):
|
||||
async def test_update_prefrences(hass, hass_ws_client):
|
||||
"""Test that we can update system options."""
|
||||
assert await async_setup_component(hass, "config", {})
|
||||
ws_client = await hass_ws_client(hass)
|
||||
|
@ -706,64 +696,45 @@ async def test_update_system_options(hass, hass_ws_client):
|
|||
entry = MockConfigEntry(domain="demo", state=core_ce.ConfigEntryState.LOADED)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert entry.system_options.disable_new_entities is False
|
||||
assert entry.system_options.disable_polling is False
|
||||
|
||||
await ws_client.send_json(
|
||||
{
|
||||
"id": 5,
|
||||
"type": "config_entries/system_options/update",
|
||||
"entry_id": entry.entry_id,
|
||||
"disable_new_entities": True,
|
||||
}
|
||||
)
|
||||
response = await ws_client.receive_json()
|
||||
|
||||
assert response["success"]
|
||||
assert response["result"] == {
|
||||
"require_restart": False,
|
||||
"system_options": {"disable_new_entities": True, "disable_polling": False},
|
||||
}
|
||||
assert entry.system_options.disable_new_entities is True
|
||||
assert entry.system_options.disable_polling is False
|
||||
assert entry.pref_disable_new_entities is False
|
||||
assert entry.pref_disable_polling is False
|
||||
|
||||
await ws_client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": "config_entries/system_options/update",
|
||||
"type": "config_entries/update",
|
||||
"entry_id": entry.entry_id,
|
||||
"disable_new_entities": False,
|
||||
"disable_polling": True,
|
||||
"pref_disable_new_entities": True,
|
||||
}
|
||||
)
|
||||
response = await ws_client.receive_json()
|
||||
|
||||
assert response["success"]
|
||||
assert response["result"] == {
|
||||
"require_restart": True,
|
||||
"system_options": {"disable_new_entities": False, "disable_polling": True},
|
||||
}
|
||||
assert entry.system_options.disable_new_entities is False
|
||||
assert entry.system_options.disable_polling is True
|
||||
assert response["result"]["require_restart"] is False
|
||||
assert response["result"]["config_entry"]["pref_disable_new_entities"] is True
|
||||
assert response["result"]["config_entry"]["pref_disable_polling"] is False
|
||||
|
||||
|
||||
async def test_update_system_options_nonexisting(hass, hass_ws_client):
|
||||
"""Test that we can update entry."""
|
||||
assert await async_setup_component(hass, "config", {})
|
||||
ws_client = await hass_ws_client(hass)
|
||||
assert entry.pref_disable_new_entities is True
|
||||
assert entry.pref_disable_polling is False
|
||||
|
||||
await ws_client.send_json(
|
||||
{
|
||||
"id": 5,
|
||||
"type": "config_entries/system_options/update",
|
||||
"entry_id": "non_existing",
|
||||
"disable_new_entities": True,
|
||||
"id": 7,
|
||||
"type": "config_entries/update",
|
||||
"entry_id": entry.entry_id,
|
||||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": True,
|
||||
}
|
||||
)
|
||||
response = await ws_client.receive_json()
|
||||
|
||||
assert not response["success"]
|
||||
assert response["error"]["code"] == "not_found"
|
||||
assert response["success"]
|
||||
assert response["result"]["require_restart"] is True
|
||||
assert response["result"]["config_entry"]["pref_disable_new_entities"] is False
|
||||
assert response["result"]["config_entry"]["pref_disable_polling"] is True
|
||||
|
||||
assert entry.pref_disable_new_entities is False
|
||||
assert entry.pref_disable_polling is True
|
||||
|
||||
|
||||
async def test_update_entry(hass, hass_ws_client):
|
||||
|
@ -785,7 +756,7 @@ async def test_update_entry(hass, hass_ws_client):
|
|||
response = await ws_client.receive_json()
|
||||
|
||||
assert response["success"]
|
||||
assert response["result"]["title"] == "Updated Title"
|
||||
assert response["result"]["config_entry"]["title"] == "Updated Title"
|
||||
assert entry.title == "Updated Title"
|
||||
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ def config_entry_fixture():
|
|||
title="",
|
||||
data=data,
|
||||
options={},
|
||||
system_options={},
|
||||
source=SOURCE_USER,
|
||||
entry_id=1,
|
||||
)
|
||||
|
|
|
@ -282,7 +282,6 @@ def config_entry_fixture():
|
|||
title="",
|
||||
data=data,
|
||||
options={CONF_TTS_PAUSE_TIME: 0},
|
||||
system_options={},
|
||||
source=SOURCE_USER,
|
||||
entry_id=1,
|
||||
)
|
||||
|
|
|
@ -35,7 +35,6 @@ def mock_config_entry():
|
|||
},
|
||||
source="test",
|
||||
options={},
|
||||
system_options={"disable_new_entities": False},
|
||||
unique_id=DOMAIN,
|
||||
entry_id="home_plus_control_entry_id",
|
||||
)
|
||||
|
|
|
@ -95,7 +95,6 @@ async def test_storage_is_removed_on_config_entry_removal(hass, utcnow):
|
|||
"TestData",
|
||||
pairing_data,
|
||||
"test",
|
||||
system_options={},
|
||||
)
|
||||
|
||||
assert hkid in hass.data[ENTITY_MAP].storage_data
|
||||
|
|
|
@ -62,7 +62,6 @@ def hmip_config_entry_fixture() -> config_entries.ConfigEntry:
|
|||
unique_id=HAPID,
|
||||
data=entry_data,
|
||||
source=SOURCE_IMPORT,
|
||||
system_options={"disable_new_entities": False},
|
||||
)
|
||||
|
||||
return config_entry
|
||||
|
|
|
@ -127,7 +127,6 @@ async def setup_bridge_for_sensors(hass, mock_bridge, hostname=None):
|
|||
domain=hue.DOMAIN,
|
||||
title="Mock Title",
|
||||
data={"host": hostname},
|
||||
system_options={},
|
||||
)
|
||||
mock_bridge.config_entry = config_entry
|
||||
hass.data[hue.DOMAIN] = {config_entry.entry_id: mock_bridge}
|
||||
|
|
|
@ -181,7 +181,6 @@ async def test_hue_activate_scene(hass, mock_api):
|
|||
"Mock Title",
|
||||
{"host": "mock-host", "username": "mock-username"},
|
||||
"test",
|
||||
system_options={},
|
||||
options={CONF_ALLOW_HUE_GROUPS: True, CONF_ALLOW_UNREACHABLE: False},
|
||||
)
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
|
@ -215,7 +214,6 @@ async def test_hue_activate_scene_transition(hass, mock_api):
|
|||
"Mock Title",
|
||||
{"host": "mock-host", "username": "mock-username"},
|
||||
"test",
|
||||
system_options={},
|
||||
options={CONF_ALLOW_HUE_GROUPS: True, CONF_ALLOW_UNREACHABLE: False},
|
||||
)
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
|
@ -249,7 +247,6 @@ async def test_hue_activate_scene_group_not_found(hass, mock_api):
|
|||
"Mock Title",
|
||||
{"host": "mock-host", "username": "mock-username"},
|
||||
"test",
|
||||
system_options={},
|
||||
options={CONF_ALLOW_HUE_GROUPS: True, CONF_ALLOW_UNREACHABLE: False},
|
||||
)
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
|
@ -278,7 +275,6 @@ async def test_hue_activate_scene_scene_not_found(hass, mock_api):
|
|||
"Mock Title",
|
||||
{"host": "mock-host", "username": "mock-username"},
|
||||
"test",
|
||||
system_options={},
|
||||
options={CONF_ALLOW_HUE_GROUPS: True, CONF_ALLOW_UNREACHABLE: False},
|
||||
)
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
|
|
|
@ -179,7 +179,6 @@ async def setup_bridge(hass, mock_bridge):
|
|||
"Mock Title",
|
||||
{"host": "mock-host"},
|
||||
"test",
|
||||
system_options={},
|
||||
)
|
||||
mock_bridge.config_entry = config_entry
|
||||
hass.data[hue.DOMAIN] = {config_entry.entry_id: mock_bridge}
|
||||
|
|
|
@ -41,7 +41,6 @@ async def test_setup_entry(hass: HomeAssistant):
|
|||
CONF_PASSWORD: "password",
|
||||
},
|
||||
source="test",
|
||||
system_options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
|
@ -81,7 +80,6 @@ async def test_setup_entry_error(hass: HomeAssistant):
|
|||
CONF_PASSWORD: "password",
|
||||
},
|
||||
source="test",
|
||||
system_options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
|
@ -122,7 +120,6 @@ async def test_unload_entry(hass: HomeAssistant):
|
|||
CONF_PASSWORD: "password",
|
||||
},
|
||||
source="test",
|
||||
system_options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ async def test_setup_entry(hass: HomeAssistant):
|
|||
CONF_PASSWORD: "password",
|
||||
},
|
||||
source="test",
|
||||
system_options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
|
@ -90,7 +89,6 @@ async def test_setup_entry_absent_measurement(hass: HomeAssistant):
|
|||
CONF_PASSWORD: "password",
|
||||
},
|
||||
source="test",
|
||||
system_options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
|
|
|
@ -256,7 +256,6 @@ async def test_options_flow(hass):
|
|||
title="Wartenau",
|
||||
data=FIXTURE_CONFIG_ENTRY,
|
||||
source=SOURCE_USER,
|
||||
system_options={"disable_new_entities": False},
|
||||
options=FIXTURE_OPTIONS,
|
||||
unique_id="1234",
|
||||
)
|
||||
|
@ -306,7 +305,6 @@ async def test_options_flow_invalid_auth(hass):
|
|||
title="Wartenau",
|
||||
data=FIXTURE_CONFIG_ENTRY,
|
||||
source=SOURCE_USER,
|
||||
system_options={"disable_new_entities": False},
|
||||
options=FIXTURE_OPTIONS,
|
||||
unique_id="1234",
|
||||
)
|
||||
|
@ -346,7 +344,6 @@ async def test_options_flow_cannot_connect(hass):
|
|||
title="Wartenau",
|
||||
data=FIXTURE_CONFIG_ENTRY,
|
||||
source=SOURCE_USER,
|
||||
system_options={"disable_new_entities": False},
|
||||
options=FIXTURE_OPTIONS,
|
||||
unique_id="1234",
|
||||
)
|
||||
|
|
|
@ -61,7 +61,6 @@ async def setup_platform(hass, platform: str, *, devices=None, scenes=None):
|
|||
"Test",
|
||||
{CONF_INSTALLED_APP_ID: str(uuid4())},
|
||||
SOURCE_USER,
|
||||
system_options={},
|
||||
)
|
||||
broker = DeviceBroker(
|
||||
hass, config_entry, Mock(), Mock(), devices or [], scenes or []
|
||||
|
|
|
@ -943,7 +943,6 @@ async def test_restoring_client(hass, aioclient_mock):
|
|||
title="Mock Title",
|
||||
data=ENTRY_CONFIG,
|
||||
source="test",
|
||||
system_options={},
|
||||
options={},
|
||||
entry_id=1,
|
||||
)
|
||||
|
|
|
@ -793,7 +793,6 @@ async def test_restore_client_succeed(hass, aioclient_mock):
|
|||
title="Mock Title",
|
||||
data=ENTRY_CONFIG,
|
||||
source="test",
|
||||
system_options={},
|
||||
options={},
|
||||
entry_id=1,
|
||||
)
|
||||
|
@ -884,7 +883,6 @@ async def test_restore_client_no_old_state(hass, aioclient_mock):
|
|||
title="Mock Title",
|
||||
data=ENTRY_CONFIG,
|
||||
source="test",
|
||||
system_options={},
|
||||
options={},
|
||||
entry_id=1,
|
||||
)
|
||||
|
|
|
@ -286,7 +286,6 @@ async def setup_ozw(hass, mock_openzwave):
|
|||
"Mock Title",
|
||||
{"usb_path": "mock-path", "network_key": "mock-key"},
|
||||
"test",
|
||||
system_options={},
|
||||
)
|
||||
await hass.config_entries.async_forward_entry_setup(config_entry, "lock")
|
||||
await hass.async_block_till_done()
|
||||
|
|
|
@ -60,9 +60,7 @@ async def test_polling_only_updates_entities_it_should_poll(hass):
|
|||
async def test_polling_disabled_by_config_entry(hass):
|
||||
"""Test the polling of only updated entities."""
|
||||
entity_platform = MockEntityPlatform(hass)
|
||||
entity_platform.config_entry = MockConfigEntry(
|
||||
system_options={"disable_polling": True}
|
||||
)
|
||||
entity_platform.config_entry = MockConfigEntry(pref_disable_polling=True)
|
||||
|
||||
poll_ent = MockEntity(should_poll=True)
|
||||
|
||||
|
|
|
@ -513,12 +513,12 @@ async def test_disabled_by(registry):
|
|||
assert entry2.disabled_by is None
|
||||
|
||||
|
||||
async def test_disabled_by_system_options(registry):
|
||||
"""Test system options setting disabled_by."""
|
||||
async def test_disabled_by_config_entry_pref(registry):
|
||||
"""Test config entry preference setting disabled_by."""
|
||||
mock_config = MockConfigEntry(
|
||||
domain="light",
|
||||
entry_id="mock-id-1",
|
||||
system_options={"disable_new_entities": True},
|
||||
pref_disable_new_entities=True,
|
||||
)
|
||||
entry = registry.async_get_or_create(
|
||||
"light", "hue", "AAAA", config_entry=mock_config
|
||||
|
|
|
@ -376,7 +376,7 @@ async def test_async_config_entry_first_refresh_success(crd, caplog):
|
|||
|
||||
async def test_not_schedule_refresh_if_system_option_disable_polling(hass):
|
||||
"""Test we do not schedule a refresh if disable polling in config entry."""
|
||||
entry = MockConfigEntry(system_options={"disable_polling": True})
|
||||
entry = MockConfigEntry(pref_disable_polling=True)
|
||||
config_entries.current_entry.set(entry)
|
||||
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL)
|
||||
crd.async_add_listener(lambda: None)
|
||||
|
|
|
@ -575,6 +575,13 @@ async def test_saving_and_loading(hass):
|
|||
)
|
||||
|
||||
assert len(hass.config_entries.async_entries()) == 2
|
||||
entry_1 = hass.config_entries.async_entries()[0]
|
||||
|
||||
hass.config_entries.async_update_entry(
|
||||
entry_1,
|
||||
pref_disable_polling=True,
|
||||
pref_disable_new_entities=True,
|
||||
)
|
||||
|
||||
# To trigger the call_later
|
||||
async_fire_time_changed(hass, dt.utcnow() + timedelta(seconds=1))
|
||||
|
@ -597,6 +604,8 @@ async def test_saving_and_loading(hass):
|
|||
assert orig.data == loaded.data
|
||||
assert orig.source == loaded.source
|
||||
assert orig.unique_id == loaded.unique_id
|
||||
assert orig.pref_disable_new_entities == loaded.pref_disable_new_entities
|
||||
assert orig.pref_disable_polling == loaded.pref_disable_polling
|
||||
|
||||
|
||||
async def test_forward_entry_sets_up_component(hass):
|
||||
|
@ -814,14 +823,19 @@ async def test_updating_entry_system_options(manager):
|
|||
domain="test",
|
||||
data={"first": True},
|
||||
state=config_entries.ConfigEntryState.SETUP_ERROR,
|
||||
system_options={"disable_new_entities": True},
|
||||
pref_disable_new_entities=True,
|
||||
)
|
||||
entry.add_to_manager(manager)
|
||||
|
||||
assert entry.system_options.disable_new_entities
|
||||
assert entry.pref_disable_new_entities is True
|
||||
assert entry.pref_disable_polling is False
|
||||
|
||||
entry.system_options.update(disable_new_entities=False)
|
||||
assert not entry.system_options.disable_new_entities
|
||||
manager.async_update_entry(
|
||||
entry, pref_disable_new_entities=False, pref_disable_polling=True
|
||||
)
|
||||
|
||||
assert entry.pref_disable_new_entities is False
|
||||
assert entry.pref_disable_polling is True
|
||||
|
||||
|
||||
async def test_update_entry_options_and_trigger_listener(hass, manager):
|
||||
|
@ -2558,48 +2572,18 @@ async def test_updating_entry_with_and_without_changes(manager):
|
|||
entry.add_to_manager(manager)
|
||||
|
||||
assert manager.async_update_entry(entry) is False
|
||||
assert manager.async_update_entry(entry, data={"second": True}) is True
|
||||
assert manager.async_update_entry(entry, data={"second": True}) is False
|
||||
assert (
|
||||
manager.async_update_entry(entry, data={"second": True, "third": 456}) is True
|
||||
)
|
||||
assert (
|
||||
manager.async_update_entry(entry, data={"second": True, "third": 456}) is False
|
||||
)
|
||||
assert manager.async_update_entry(entry, options={"second": True}) is True
|
||||
assert manager.async_update_entry(entry, options={"second": True}) is False
|
||||
assert (
|
||||
manager.async_update_entry(entry, options={"second": True, "third": "123"})
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
manager.async_update_entry(entry, options={"second": True, "third": "123"})
|
||||
is False
|
||||
)
|
||||
assert (
|
||||
manager.async_update_entry(entry, system_options={"disable_new_entities": True})
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
manager.async_update_entry(entry, system_options={"disable_new_entities": True})
|
||||
is False
|
||||
)
|
||||
assert (
|
||||
manager.async_update_entry(
|
||||
entry, system_options={"disable_new_entities": False}
|
||||
)
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
manager.async_update_entry(
|
||||
entry, system_options={"disable_new_entities": False}
|
||||
)
|
||||
is False
|
||||
)
|
||||
assert manager.async_update_entry(entry, title="thetitle") is False
|
||||
assert manager.async_update_entry(entry, title="newtitle") is True
|
||||
assert manager.async_update_entry(entry, unique_id="abc123") is False
|
||||
assert manager.async_update_entry(entry, unique_id="abc1234") is True
|
||||
|
||||
for change in (
|
||||
{"data": {"second": True, "third": 456}},
|
||||
{"data": {"second": True}},
|
||||
{"options": {"hello": True}},
|
||||
{"pref_disable_new_entities": True},
|
||||
{"pref_disable_polling": True},
|
||||
{"title": "sometitle"},
|
||||
{"unique_id": "abcd1234"},
|
||||
):
|
||||
assert manager.async_update_entry(entry, **change) is True
|
||||
assert manager.async_update_entry(entry, **change) is False
|
||||
|
||||
|
||||
async def test_entry_reload_calls_on_unload_listeners(hass, manager):
|
||||
|
@ -2864,3 +2848,35 @@ async def test__async_abort_entries_match(hass, manager, matchers, reason):
|
|||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == reason
|
||||
|
||||
|
||||
async def test_loading_old_data(hass, hass_storage):
|
||||
"""Test automatically migrating old data."""
|
||||
hass_storage[config_entries.STORAGE_KEY] = {
|
||||
"version": 1,
|
||||
"data": {
|
||||
"entries": [
|
||||
{
|
||||
"version": 5,
|
||||
"domain": "my_domain",
|
||||
"entry_id": "mock-id",
|
||||
"data": {"my": "data"},
|
||||
"source": "user",
|
||||
"title": "Mock title",
|
||||
"system_options": {"disable_new_entities": True},
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
manager = config_entries.ConfigEntries(hass, {})
|
||||
await manager.async_initialize()
|
||||
|
||||
entries = manager.async_entries()
|
||||
assert len(entries) == 1
|
||||
entry = entries[0]
|
||||
assert entry.version == 5
|
||||
assert entry.domain == "my_domain"
|
||||
assert entry.entry_id == "mock-id"
|
||||
assert entry.title == "Mock title"
|
||||
assert entry.data == {"my": "data"}
|
||||
assert entry.pref_disable_new_entities is True
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue