Compare commits

...

13 Commits

Author SHA1 Message Date
G Johansson
747faef053 Fix test 2024-11-24 22:23:01 +00:00
G Johansson
6986e12c4d Only default if multiple 2024-11-24 22:21:30 +00:00
G Johansson
073ba775b2 default is optional 2024-11-24 22:12:49 +00:00
G Johansson
b68b350230 More explicit typing 2024-11-24 22:03:03 +00:00
G Johansson
1e6f04f7f9 Fix data entry flow test 2024-11-24 22:01:28 +00:00
G Johansson
6f500be6e2 Put back defaults 2024-11-24 21:59:47 +00:00
G Johansson
48f44ab883 Fix defaults 2024-11-24 21:40:54 +00:00
G Johansson
1a2c59ffeb Fix kitchen sink 2024-11-24 19:19:21 +00:00
G Johansson
bbba064acf Fix multiple None 2024-11-24 19:18:56 +00:00
G Johansson
885749cd91 Change multiple and default to inclusive with no defaults 2024-11-24 19:06:03 +00:00
G Johansson
c7741a0885 Reset kitchen sink section 1 2024-11-24 18:52:27 +00:00
G Johansson
71d881f0ed Mod kitchen_sink 2024-11-24 18:49:04 +00:00
G Johansson
ff51d924b4 Allow multiple sections 2024-11-24 18:49:04 +00:00
6 changed files with 109 additions and 9 deletions

View File

@@ -70,6 +70,7 @@ class OptionsFlowHandler(OptionsFlow):
if user_input is not None:
return self.async_create_entry(data=self.config_entry.options | user_input)
section_1 = self.config_entry.options.get("section_1", {})
return self.async_show_form(
step_id="options_1",
data_schema=vol.Schema(
@@ -79,17 +80,36 @@ class OptionsFlowHandler(OptionsFlow):
{
vol.Optional(
CONF_BOOLEAN,
default=self.config_entry.options.get(
CONF_BOOLEAN, False
),
default=section_1.get(CONF_BOOLEAN, False),
): bool,
vol.Optional(
CONF_INT,
default=self.config_entry.options.get(CONF_INT, 10),
default=section_1.get(CONF_INT, 10),
): int,
}
),
{"collapsed": False},
{
"collapsed": False,
},
),
vol.Required("section_2"): data_entry_flow.section(
vol.Schema(
{
vol.Optional(
"a",
default=2,
): int,
vol.Optional(
"b",
default=4,
): int,
}
),
{
"collapsed": False,
"multiple": True,
"default": self.config_entry.options.get("section_2", []),
},
),
}
),

View File

@@ -23,6 +23,14 @@
},
"description": "This section allows input of some extra data",
"name": "Collapsible section"
},
"section_2": {
"data": {
"a": "A",
"b": "B"
},
"description": "Some datapoints",
"name": "Data point"
}
},
"submit": "Save!"

View File

@@ -908,6 +908,8 @@ class SectionConfig(TypedDict, total=False):
"""Class to represent a section config."""
collapsed: bool
multiple: bool
default: list[dict[str, Any]]
class section:
@@ -916,6 +918,8 @@ class section:
CONFIG_SCHEMA = vol.Schema(
{
vol.Optional("collapsed", default=False): bool,
vol.Optional("multiple", default=False): bool,
vol.Optional("default"): list[dict[str, Any]],
},
)
@@ -928,7 +932,11 @@ class section:
def __call__(self, value: Any) -> Any:
"""Validate input."""
return self.schema(value)
if not self.options.get("multiple"):
return self.schema(value)
if not isinstance(value, list):
raise vol.Invalid("Value should be a list")
return [vol.Schema(dict)(val) for val in value]
# These can be removed if no deprecated constant are in this module anymore

View File

@@ -1136,7 +1136,7 @@ def _custom_serializer(schema: Any, *, allow_section: bool) -> Any:
if isinstance(schema, data_entry_flow.section):
if not allow_section:
raise ValueError("Nesting expandable sections is not supported")
return {
section_schema = {
"type": "expandable",
"schema": voluptuous_serialize.convert(
schema.schema,
@@ -1145,7 +1145,11 @@ def _custom_serializer(schema: Any, *, allow_section: bool) -> Any:
),
),
"expanded": not schema.options["collapsed"],
"multiple": schema.options["multiple"],
}
if schema.options["multiple"]:
section_schema["default"] = schema.options["default"]
return section_schema
if isinstance(schema, multi_select):
return {"type": "multi_select", "options": schema.options}

View File

@@ -98,9 +98,39 @@ async def test_options_flow(hass: HomeAssistant) -> None:
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={"section_1": {"bool": True, "int": 15}},
user_input={
"section_1": {
"bool": True,
"int": 15,
},
"section_2": [
{
"a": 2,
"b": 4,
},
{
"a": 5,
"b": 7,
},
],
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert config_entry.options == {"section_1": {"bool": True, "int": 15}}
assert config_entry.options == {
"section_1": {
"bool": True,
"int": 15,
},
"section_2": [
{
"a": 2,
"b": 4,
},
{
"a": 5,
"b": 7,
},
],
}
await hass.async_block_till_done()

View File

@@ -1020,6 +1020,36 @@ def test_section_in_serializer() -> None:
{"name": "option_2", "required": True, "type": "integer"},
],
"type": "expandable",
"multiple": False,
}
def test_section_multiple_in_serializer() -> None:
"""Test section with multiple with custom_serializer."""
assert cv.custom_serializer(
data_entry_flow.section(
vol.Schema(
{
vol.Optional("option_1", default=False): bool,
vol.Required("option_2"): int,
}
),
{"collapsed": False, "multiple": True, "default": [{True, 10}]},
)
) == {
"expanded": True,
"schema": [
{"default": False, "name": "option_1", "optional": True, "type": "boolean"},
{"name": "option_2", "required": True, "type": "integer"},
],
"type": "expandable",
"multiple": True,
"default": [
{
True,
10,
},
],
}