Improve boolean validator (#24294)

* Improve boolean validator

* Remove extra throw

* Remove None test as discussed

* Fix for tests depending on None == False
This commit is contained in:
Penny Wood 2019-06-08 13:18:02 +08:00 committed by Paulus Schoutsen
parent 233bc1a108
commit b30f4b8fc0
5 changed files with 20 additions and 9 deletions

View file

@ -6,6 +6,7 @@ import re
from datetime import (timedelta, datetime as datetime_sys,
time as time_sys, date as date_sys)
from socket import _GLOBAL_DEFAULT_TIMEOUT
from numbers import Number
from typing import Any, Union, TypeVar, Callable, Sequence, Dict, Optional
from urllib.parse import urlparse
from uuid import UUID
@ -81,14 +82,17 @@ def has_at_most_one_key(*keys: str) -> Callable:
def boolean(value: Any) -> bool:
"""Validate and coerce a boolean value."""
if isinstance(value, bool):
return value
if isinstance(value, str):
value = value.lower()
value = value.lower().strip()
if value in ('1', 'true', 'yes', 'on', 'enable'):
return True
if value in ('0', 'false', 'no', 'off', 'disable'):
return False
elif isinstance(value, Number):
return value != 0
raise vol.Invalid('invalid boolean value {}'.format(value))
return bool(value)
def isdevice(value):

View file

@ -203,6 +203,7 @@ class TestDemoClimate(unittest.TestCase):
"""Test setting the away mode without required attribute."""
state = self.hass.states.get(ENTITY_CLIMATE)
assert 'on' == state.attributes.get('away_mode')
with pytest.raises(vol.Invalid):
common.set_away_mode(self.hass, None, ENTITY_CLIMATE)
self.hass.block_till_done()
assert 'on' == state.attributes.get('away_mode')
@ -246,6 +247,7 @@ class TestDemoClimate(unittest.TestCase):
"""Test setting the auxiliary heater without required attribute."""
state = self.hass.states.get(ENTITY_CLIMATE)
assert 'off' == state.attributes.get('aux_heat')
with pytest.raises(vol.Invalid):
common.set_aux_heat(self.hass, None, ENTITY_CLIMATE)
self.hass.block_till_done()
assert 'off' == state.attributes.get('aux_heat')

View file

@ -90,6 +90,7 @@ class TestDemoMediaPlayer(unittest.TestCase):
assert False is state.attributes.get('is_volume_muted')
with pytest.raises(vol.Invalid):
common.mute_volume(self.hass, None, entity_id)
self.hass.block_till_done()
state = self.hass.states.get(entity_id)

View file

@ -95,6 +95,7 @@ class TestDemowater_heater(unittest.TestCase):
"""Test setting the away mode without required attribute."""
state = self.hass.states.get(ENTITY_WATER_HEATER)
assert 'off' == state.attributes.get('away_mode')
with pytest.raises(vol.Invalid):
common.set_away_mode(self.hass, None, ENTITY_WATER_HEATER)
self.hass.block_till_done()
assert 'off' == state.attributes.get('away_mode')

View file

@ -17,11 +17,14 @@ def test_boolean():
"""Test boolean validation."""
schema = vol.Schema(cv.boolean)
for value in ('T', 'negative', 'lock'):
for value in (
None, 'T', 'negative', 'lock', 'tr ue',
[], [1, 2], {'one': 'two'}, test_boolean):
with pytest.raises(vol.MultipleInvalid):
schema(value)
for value in ('true', 'On', '1', 'YES', 'enable', 1, True):
for value in ('true', 'On', '1', 'YES', ' true ',
'enable', 1, 50, True, 0.1):
assert schema(value)
for value in ('false', 'Off', '0', 'NO', 'disable', 0, False):