8000 Allow use of Selector in ObjectSelector fields by gjohansson-ST · Pull Request #147929 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Allow use of Selector in ObjectSelector fields #147929

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

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
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
18 changes: 15 additions & 3 deletions homeassistant/helpers/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

from collections.abc import Callable, Mapping, Sequence
from copy import deepcopy
from enum import StrEnum
from functools import cache
import importlib
Expand Down Expand Up @@ -1133,7 +1134,7 @@ class ObjectSelectorField(TypedDict):

label: str
required: bool
selector: dict[str, Any]
selector: Required[Selector | dict[str, Any]]


class ObjectSelectorConfig(BaseSelectorConfig):
Expand All @@ -1142,7 +1143,7 @@ class ObjectSelectorConfig(BaseSelectorConfig):
fields: dict[str, ObjectSelectorField]
multiple: bool
label_field: str
description_field: bool
description_field: str
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugfix (typing)

translation_key: str


Expand All @@ -1156,7 +1157,7 @@ class ObjectSelector(Selector[ObjectSelectorConfig]):
{
vol.Optional("fields"): {
str: {
vol.Required("selector"): dict,
vol.Required("selector"): vol.Any(Selector, dict),
vol.Optional("required"): bool,
vol.Optional("label"): str,
}
Expand All @@ -1172,6 +1173,17 @@ def __init__(self, config: ObjectSelectorConfig | None = None) -> None:
"""Instantiate a selector."""
super().__init__(config)

def serialize(self) -> dict[str, dict[str, ObjectSelectorConfig]]:
"""Serialize ObjectSelector for voluptuous_serialize."""
_config = deepcopy(self.config)
if "fields" in _config:
for items in _config["fields"].values():
if isinstance(items["selector"], Selector):
items["selector"] = {
items["selector"].selector_type: items["selector"].config
}
return {"selector": {self.selector_type: _config}}

def __call__(self, data: Any) -> Any:
"""Validate the passed selection."""
return data
Expand Down
33 changes: 33 additions & 0 deletions tests/helpers/snapshots/test_selector.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# serializer version: 1
# name: test_object_selector_uses_selectors
dict({
'selector': dict({
'object': dict({
'description_field': 'percentage',
'fields': dict({
'name': dict({
'required': True,
'selector': dict({
'text': dict({
'multiline': False,
'multiple': False,
}),
}),
}),
'percentage': dict({
'selector': dict({
'number': dict({
'max': 100.0,
'min': 0.0,
'mode': 'slider',
'step': 1.0,
}),
}),
}),
}),
'label_field': 'name',
'multiple': True,
}),
}),
})
# ---
38 changes: 38 additions & 0 deletions tests/helpers/test_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Any

import pytest
from syrupy.assertion import SnapshotAssertion
import voluptuous as vol

from homeassistant.helpers import selector
Expand Down Expand Up @@ -618,6 +619,43 @@ def test_object_selector_schema(schema, valid_selections, invalid_selections) ->
_test_selector("object", schema, valid_selections, invalid_selections)


def test_object_selector_uses_selectors(snapshot: SnapshotAssertion) -> None:
"""Test ObjectSelector custom serializer for using Selector in ObjectSelectorField."""

selector_type = "object"
schema = {
"fields": {
"name": {
"required": True,
"selector": selector.TextSelector(),
},
"percentage": {
"selector": selector.NumberSelector(
selector.NumberSelectorConfig(min=0, max=100)
),
},
},
"multiple": True,
"label_field": "name",
"description_field": "percentage",
}

# Validate selector configuration
config = {selector_type: schema}
selector.validate_selector(config)
selector_instance = selector.selector(config)

# Serialize selector
selector_instance = selector.selector({selector_type: schema})
assert selector_instance.serialize() != {
"selector": {selector_type: selector_instance.config}
}
assert selector_instance.serialize() == snapshot()

# Test serialized selector can be dumped to YAML
yaml_util.dump(selector_instance.serialize())


@pytest.mark.parametrize(
("schema", "valid_selections", "invalid_selections"),
[
Expand Down
0