Add OptionsFlow helper class (#82531)
* Add OptionsFlow helper classes * More integrations * Adjust SchemaOptionsFlowHandler * Use single class * Simplify access to options * Reduce PR * Make _options private * Add test
This commit is contained in:
parent
7f90fb1cd1
commit
4c38a5d773
3 changed files with 38 additions and 6 deletions
|
@ -5,6 +5,7 @@ import asyncio
|
|||
from collections import ChainMap
|
||||
from collections.abc import Callable, Coroutine, Generator, Iterable, Mapping
|
||||
from contextvars import ContextVar
|
||||
from copy import deepcopy
|
||||
from enum import Enum
|
||||
import functools
|
||||
import logging
|
||||
|
@ -1672,11 +1673,20 @@ class OptionsFlowManager(data_entry_flow.FlowManager):
|
|||
|
||||
|
||||
class OptionsFlow(data_entry_flow.FlowHandler):
|
||||
"""Base class for config option flows."""
|
||||
"""Base class for config options flows."""
|
||||
|
||||
handler: str
|
||||
|
||||
|
||||
class OptionsFlowWithConfigEntry(OptionsFlow):
|
||||
"""Base class for options flows with config entry and options."""
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Initialize options flow."""
|
||||
self.config_entry = config_entry
|
||||
self._options = deepcopy(dict(config_entry.options))
|
||||
|
||||
|
||||
class EntityRegistryDisabledHandler:
|
||||
"""Handler to handle when entities related to config entries updating disabled_by."""
|
||||
|
||||
|
|
|
@ -75,12 +75,12 @@ class SchemaCommonFlowHandler:
|
|||
self,
|
||||
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
|
||||
flow: dict[str, SchemaFlowFormStep | SchemaFlowMenuStep],
|
||||
config_entry: config_entries.ConfigEntry | None,
|
||||
options: dict[str, Any] | None,
|
||||
) -> None:
|
||||
"""Initialize a common handler."""
|
||||
self._flow = flow
|
||||
self._handler = handler
|
||||
self._options = dict(config_entry.options) if config_entry is not None else {}
|
||||
self._options = options if options is not None else {}
|
||||
|
||||
async def async_step(
|
||||
self, step_id: str, user_input: dict[str, Any] | None = None
|
||||
|
@ -300,7 +300,7 @@ class SchemaConfigFlowHandler(config_entries.ConfigFlow):
|
|||
)
|
||||
|
||||
|
||||
class SchemaOptionsFlowHandler(config_entries.OptionsFlow):
|
||||
class SchemaOptionsFlowHandler(config_entries.OptionsFlowWithConfigEntry):
|
||||
"""Handle a schema based options flow."""
|
||||
|
||||
def __init__(
|
||||
|
@ -310,8 +310,10 @@ class SchemaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
async_options_flow_finished: Callable[[HomeAssistant, Mapping[str, Any]], None],
|
||||
) -> None:
|
||||
"""Initialize options flow."""
|
||||
self._common_handler = SchemaCommonFlowHandler(self, options_flow, config_entry)
|
||||
self.config_entry = config_entry
|
||||
super().__init__(config_entry)
|
||||
self._common_handler = SchemaCommonFlowHandler(
|
||||
self, options_flow, self._options
|
||||
)
|
||||
self._async_options_flow_finished = async_options_flow_finished
|
||||
|
||||
for step in options_flow:
|
||||
|
|
|
@ -3426,3 +3426,23 @@ async def test_async_wait_component_startup(hass: HomeAssistant):
|
|||
|
||||
# The component has been loaded
|
||||
assert "test" in hass.config.components
|
||||
|
||||
|
||||
async def test_options_flow_options_not_mutated() -> None:
|
||||
"""Test that OptionsFlowWithConfigEntry doesn't mutate entry options."""
|
||||
entry = MockConfigEntry(
|
||||
domain="test",
|
||||
data={"first": True},
|
||||
options={"sub_dict": {"1": "one"}, "sub_list": ["one"]},
|
||||
)
|
||||
|
||||
options_flow = config_entries.OptionsFlowWithConfigEntry(entry)
|
||||
|
||||
options_flow._options["sub_dict"]["2"] = "two"
|
||||
options_flow._options["sub_list"].append("two")
|
||||
|
||||
assert options_flow._options == {
|
||||
"sub_dict": {"1": "one", "2": "two"},
|
||||
"sub_list": ["one", "two"],
|
||||
}
|
||||
assert entry.options == {"sub_dict": {"1": "one"}, "sub_list": ["one"]}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue