diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index 78dae80ebfb..d69c1425761 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -373,7 +373,7 @@ def icon(value: Any) -> str: raise vol.Invalid('Icons should be specified in the form "prefix:name"') -time_period_dict = vol.All( +time_period_dict_dict = vol.All( dict, vol.Schema( { @@ -385,6 +385,10 @@ time_period_dict = vol.All( } ), has_at_least_one_key("days", "hours", "minutes", "seconds", "milliseconds"), +) + +time_period_dict = vol.All( + time_period_dict_dict, lambda value: timedelta(**value), ) diff --git a/homeassistant/helpers/selector.py b/homeassistant/helpers/selector.py index 3359deb9b09..e529cac096c 100644 --- a/homeassistant/helpers/selector.py +++ b/homeassistant/helpers/selector.py @@ -259,10 +259,12 @@ class TimeSelector(Selector): selector_type = "time" - CONFIG_SCHEMA = vol.Schema({}) + CONFIG_SCHEMA = vol.Schema({vol.Optional("as_str", default=False): bool}) - def __call__(self, data: Any) -> time_sys: + def __call__(self, data: Any) -> str | time_sys: """Validate the passed selection.""" + if self.config["as_str"]: + return str(cv.time(data)) return cv.time(data) @@ -407,10 +409,14 @@ class DurationSelector(Selector): selector_type = "duration" - CONFIG_SCHEMA = vol.Schema({}) + CONFIG_SCHEMA = vol.Schema({vol.Optional("as_dict", default=False): bool}) - def __call__(self, data: Any) -> timedelta: + def __call__(self, data: Any) -> dict[str, float] | timedelta: """Validate the passed selection.""" + if self.config["as_dict"]: + duration_dict: dict[str, float] = cv.time_period_dict_dict(data) + return duration_dict + duration: timedelta = cv.time_period_dict(data) return duration diff --git a/tests/helpers/test_selector.py b/tests/helpers/test_selector.py index 7031f16d249..88820de9eef 100644 --- a/tests/helpers/test_selector.py +++ b/tests/helpers/test_selector.py @@ -248,14 +248,15 @@ def test_boolean_selector_schema(schema, valid_selections, invalid_selections): @pytest.mark.parametrize( - "schema,valid_selections,invalid_selections", - (({}, ("00:00:00",), ("blah", None)),), + "schema,valid_selections,invalid_selections,converter", + ( + ({}, ("00:00:00",), ("blah", None), dt_util.parse_time), + ({"as_str": True}, ("00:00:00",), ("blah", None), None), + ), ) -def test_time_selector_schema(schema, valid_selections, invalid_selections): +def test_time_selector_schema(schema, valid_selections, invalid_selections, converter): """Test time selector.""" - _test_selector( - "time", schema, valid_selections, invalid_selections, dt_util.parse_time - ) + _test_selector("time", schema, valid_selections, invalid_selections, converter) @pytest.mark.parametrize( @@ -382,24 +383,27 @@ def test_attribute_selector_schema(schema, valid_selections, invalid_selections) @pytest.mark.parametrize( - "schema,valid_selections,invalid_selections", + "schema,valid_selections,invalid_selections,converter", ( ( {}, ({"seconds": 10},), (None, {}), + lambda x: timedelta(**x), + ), + ( + {"as_dict": True}, + ({"seconds": 10},), + (None, {}), + None, ), ), ) -def test_duration_selector_schema(schema, valid_selections, invalid_selections): +def test_duration_selector_schema( + schema, valid_selections, invalid_selections, converter +): """Test duration selector.""" - _test_selector( - "duration", - schema, - valid_selections, - invalid_selections, - lambda x: timedelta(**x), - ) + _test_selector("duration", schema, valid_selections, invalid_selections, converter) @pytest.mark.parametrize(