ensure_list validator - Allow None to return an empty list (#5133)

This commit is contained in:
Johann Kellerman 2017-01-05 21:33:22 +02:00 committed by GitHub
parent cb85128304
commit cbda516af9
2 changed files with 62 additions and 36 deletions

View file

@ -85,6 +85,8 @@ def isfile(value: Any) -> str:
def ensure_list(value: Union[T, Sequence[T]]) -> Sequence[T]: def ensure_list(value: Union[T, Sequence[T]]) -> Sequence[T]:
"""Wrap value in list if it is not one.""" """Wrap value in list if it is not one."""
if value is None:
return []
return value if isinstance(value, list) else [value] return value if isinstance(value, list) else [value]

View file

@ -4,10 +4,10 @@ from datetime import timedelta, datetime, date
import enum import enum
import os import os
from socket import _GLOBAL_DEFAULT_TIMEOUT from socket import _GLOBAL_DEFAULT_TIMEOUT
from unittest.mock import Mock, patch
import pytest import pytest
import voluptuous as vol import voluptuous as vol
from unittest.mock import Mock, patch
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -100,20 +100,33 @@ def test_url():
def test_platform_config(): def test_platform_config():
"""Test platform config validation.""" """Test platform config validation."""
for value in ( options = (
{}, {},
{'hello': 'world'}, {'hello': 'world'},
): )
for value in options:
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
cv.PLATFORM_SCHEMA(value) cv.PLATFORM_SCHEMA(value)
for value in ( options = (
{'platform': 'mqtt'}, {'platform': 'mqtt'},
{'platform': 'mqtt', 'beer': 'yes'}, {'platform': 'mqtt', 'beer': 'yes'},
): )
for value in options:
cv.PLATFORM_SCHEMA(value) cv.PLATFORM_SCHEMA(value)
def test_ensure_list():
"""Test ensure_list."""
schema = vol.Schema(cv.ensure_list)
assert [] == schema(None)
assert [1] == schema(1)
assert [1] == schema([1])
assert ['1'] == schema('1')
assert ['1'] == schema(['1'])
assert [{'1': '2'}] == schema({'1': '2'})
def test_entity_id(): def test_entity_id():
"""Test entity ID validation.""" """Test entity ID validation."""
schema = vol.Schema(cv.entity_id) schema = vol.Schema(cv.entity_id)
@ -121,28 +134,30 @@ def test_entity_id():
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
schema('invalid_entity') schema('invalid_entity')
assert 'sensor.light' == schema('sensor.LIGHT') assert schema('sensor.LIGHT') == 'sensor.light'
def test_entity_ids(): def test_entity_ids():
"""Test entity ID validation.""" """Test entity ID validation."""
schema = vol.Schema(cv.entity_ids) schema = vol.Schema(cv.entity_ids)
for value in ( options = (
'invalid_entity', 'invalid_entity',
'sensor.light,sensor_invalid', 'sensor.light,sensor_invalid',
['invalid_entity'], ['invalid_entity'],
['sensor.light', 'sensor_invalid'], ['sensor.light', 'sensor_invalid'],
['sensor.light,sensor_invalid'], ['sensor.light,sensor_invalid'],
): )
for value in options:
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
schema(value) schema(value)
for value in ( options = (
[], [],
['sensor.light'], ['sensor.light'],
'sensor.light' 'sensor.light'
): )
for value in options:
schema(value) schema(value)
assert schema('sensor.LIGHT, light.kitchen ') == [ assert schema('sensor.LIGHT, light.kitchen ') == [
@ -152,7 +167,7 @@ def test_entity_ids():
def test_event_schema(): def test_event_schema():
"""Test event_schema validation.""" """Test event_schema validation."""
for value in ( options = (
{}, None, {}, None,
{ {
'event_data': {}, 'event_data': {},
@ -161,14 +176,16 @@ def test_event_schema():
'event': 'state_changed', 'event': 'state_changed',
'event_data': 1, 'event_data': 1,
}, },
): )
for value in options:
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
cv.EVENT_SCHEMA(value) cv.EVENT_SCHEMA(value)
for value in ( options = (
{'event': 'state_changed'}, {'event': 'state_changed'},
{'event': 'state_changed', 'event_data': {'hello': 'world'}}, {'event': 'state_changed', 'event_data': {'hello': 'world'}},
): )
for value in options:
cv.EVENT_SCHEMA(value) cv.EVENT_SCHEMA(value)
@ -200,16 +217,19 @@ def test_time_period():
"""Test time_period validation.""" """Test time_period validation."""
schema = vol.Schema(cv.time_period) schema = vol.Schema(cv.time_period)
for value in ( options = (
None, '', 'hello:world', '12:', '12:34:56:78', None, '', 'hello:world', '12:', '12:34:56:78',
{}, {'wrong_key': -10} {}, {'wrong_key': -10}
): )
for value in options:
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
schema(value) schema(value)
for value in ( options = (
'8:20', '23:59', '-8:20', '-23:59:59', '-48:00', {'minutes': 5}, 1, '5' '8:20', '23:59', '-8:20', '-23:59:59', '-48:00', {'minutes': 5}, 1, '5'
): )
for value in options:
schema(value) schema(value)
assert timedelta(seconds=180) == schema('180') assert timedelta(seconds=180) == schema('180')
@ -229,7 +249,7 @@ def test_service():
def test_service_schema(): def test_service_schema():
"""Test service_schema validation.""" """Test service_schema validation."""
for value in ( options = (
{}, None, {}, None,
{ {
'service': 'homeassistant.turn_on', 'service': 'homeassistant.turn_on',
@ -248,11 +268,12 @@ def test_service_schema():
'brightness': '{{ no_end' 'brightness': '{{ no_end'
} }
}, },
): )
for value in options:
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
cv.SERVICE_SCHEMA(value) cv.SERVICE_SCHEMA(value)
for value in ( options = (
{'service': 'homeassistant.turn_on'}, {'service': 'homeassistant.turn_on'},
{ {
'service': 'homeassistant.turn_on', 'service': 'homeassistant.turn_on',
@ -262,7 +283,8 @@ def test_service_schema():
'service': 'homeassistant.turn_on', 'service': 'homeassistant.turn_on',
'entity_id': ['light.kitchen', 'light.ceiling'], 'entity_id': ['light.kitchen', 'light.ceiling'],
}, },
): )
for value in options:
cv.SERVICE_SCHEMA(value) cv.SERVICE_SCHEMA(value)
@ -321,11 +343,12 @@ def test_template():
message='{} not considered invalid'.format(value)): message='{} not considered invalid'.format(value)):
schema(value) schema(value)
for value in ( options = (
1, 'Hello', 1, 'Hello',
'{{ beer }}', '{{ beer }}',
'{% if 1 == 1 %}Hello{% else %}World{% endif %}', '{% if 1 == 1 %}Hello{% else %}World{% endif %}',
): )
for value in options:
schema(value) schema(value)
@ -337,13 +360,14 @@ def test_template_complex():
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
schema(value) schema(value)
for value in ( options = (
1, 'Hello', 1, 'Hello',
'{{ beer }}', '{{ beer }}',
'{% if 1 == 1 %}Hello{% else %}World{% endif %}', '{% if 1 == 1 %}Hello{% else %}World{% endif %}',
{'test': 1, 'test2': '{{ beer }}'}, {'test': 1, 'test2': '{{ beer }}'},
['{{ beer }}', 1] ['{{ beer }}', 1]
): )
for value in options:
schema(value) schema(value)
@ -373,16 +397,18 @@ def test_key_dependency():
"""Test key_dependency validator.""" """Test key_dependency validator."""
schema = vol.Schema(cv.key_dependency('beer', 'soda')) schema = vol.Schema(cv.key_dependency('beer', 'soda'))
for value in ( options = (
{'beer': None} {'beer': None}
): )
for value in options:
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
schema(value) schema(value)
for value in ( options = (
{'beer': None, 'soda': None}, {'beer': None, 'soda': None},
{'soda': None}, {} {'soda': None}, {}
): )
for value in options:
schema(value) schema(value)
@ -429,7 +455,7 @@ def test_ordered_dict_key_validator():
schema({1: 'works'}) schema({1: 'works'})
def test_ordered_dict_value_validator(): def test_ordered_dict_value_validator(): # pylint: disable=invalid-name
"""Test ordered_dict validator.""" """Test ordered_dict validator."""
schema = vol.Schema(cv.ordered_dict(cv.string)) schema = vol.Schema(cv.ordered_dict(cv.string))
@ -459,12 +485,10 @@ def test_enum():
with pytest.raises(vol.Invalid): with pytest.raises(vol.Invalid):
schema('value3') schema('value3')
TestEnum['value1']
def test_socket_timeout(): # pylint: disable=invalid-name
def test_socket_timeout():
"""Test socket timeout validator.""" """Test socket timeout validator."""
TEST_CONF_TIMEOUT = 'timeout' TEST_CONF_TIMEOUT = 'timeout' # pylint: disable=invalid-name
schema = vol.Schema( schema = vol.Schema(
{vol.Required(TEST_CONF_TIMEOUT, default=None): cv.socket_timeout}) {vol.Required(TEST_CONF_TIMEOUT, default=None): cv.socket_timeout})
@ -478,4 +502,4 @@ def test_socket_timeout():
assert _GLOBAL_DEFAULT_TIMEOUT == schema({TEST_CONF_TIMEOUT: assert _GLOBAL_DEFAULT_TIMEOUT == schema({TEST_CONF_TIMEOUT:
None})[TEST_CONF_TIMEOUT] None})[TEST_CONF_TIMEOUT]
assert 1.0 == schema({TEST_CONF_TIMEOUT: 1})[TEST_CONF_TIMEOUT] assert schema({TEST_CONF_TIMEOUT: 1})[TEST_CONF_TIMEOUT] == 1.0