Skip to content

Commit

Permalink
Improve boolean validator (home-assistant#24294)
Browse files Browse the repository at this point in the history
* Improve boolean validator

* Remove extra throw

* Remove None test as discussed

* Fix for tests depending on None == False
  • Loading branch information
Swamp-Ig authored and alandtse committed Aug 6, 2019
1 parent 7c2774b commit 11f4bf4
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 9 deletions.
10 changes: 7 additions & 3 deletions homeassistant/helpers/config_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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
Expand Down Expand Up @@ -81,14 +82,17 @@ def validate(obj: Dict) -> Dict:

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
raise vol.Invalid('invalid boolean value {}'.format(value))
return bool(value)
elif isinstance(value, Number):
return value != 0
raise vol.Invalid('invalid boolean value {}'.format(value))


def isdevice(value):
Expand Down
6 changes: 4 additions & 2 deletions tests/components/demo/test_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ def test_set_away_mode_bad_attr(self):
"""Test setting the away mode without required attribute."""
state = self.hass.states.get(ENTITY_CLIMATE)
assert 'on' == state.attributes.get('away_mode')
common.set_away_mode(self.hass, None, ENTITY_CLIMATE)
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')

Expand Down Expand Up @@ -246,7 +247,8 @@ def test_set_aux_heat_bad_attr(self):
"""Test setting the auxiliary heater without required attribute."""
state = self.hass.states.get(ENTITY_CLIMATE)
assert 'off' == state.attributes.get('aux_heat')
common.set_aux_heat(self.hass, None, ENTITY_CLIMATE)
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')

Expand Down
3 changes: 2 additions & 1 deletion tests/components/demo/test_media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ def test_volume_services(self):

assert False is state.attributes.get('is_volume_muted')

common.mute_volume(self.hass, None, entity_id)
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)
assert False is state.attributes.get('is_volume_muted')
Expand Down
3 changes: 2 additions & 1 deletion tests/components/demo/test_water_heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ def test_set_away_mode_bad_attr(self):
"""Test setting the away mode without required attribute."""
state = self.hass.states.get(ENTITY_WATER_HEATER)
assert 'off' == state.attributes.get('away_mode')
common.set_away_mode(self.hass, None, ENTITY_WATER_HEATER)
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')

Expand Down
7 changes: 5 additions & 2 deletions tests/helpers/test_config_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down

0 comments on commit 11f4bf4

Please sign in to comment.