801 lines
29 KiB
Python
801 lines
29 KiB
Python
"""Unit tests for bison.scheme"""
|
|
|
|
import pytest
|
|
|
|
from bison import errors, scheme
|
|
|
|
|
|
def test_base_opt_validate():
|
|
"""Validate the base option, which should fail."""
|
|
opt = scheme._BaseOpt()
|
|
with pytest.raises(NotImplementedError):
|
|
opt.validate('test-data')
|
|
|
|
|
|
def test_base_opt_parse_env():
|
|
"""Parse env from the base option, which should fail."""
|
|
opt = scheme._BaseOpt()
|
|
with pytest.raises(NotImplementedError):
|
|
opt.parse_env()
|
|
|
|
|
|
class TestOption:
|
|
"""Tests for the `Option` class."""
|
|
|
|
def test_init_simple(self):
|
|
"""Initialize an Option."""
|
|
opt = scheme.Option('test-opt')
|
|
|
|
assert opt.name == 'test-opt'
|
|
assert type(opt.default) == scheme.NoDefault
|
|
assert opt.type is None
|
|
assert opt.choices is None
|
|
assert opt.bind_env is None
|
|
|
|
def test_init_full(self):
|
|
"""Initialize an Option."""
|
|
opt = scheme.Option(
|
|
name='test-opt',
|
|
default='foo',
|
|
field_type=str,
|
|
choices=['foo', 'bar'],
|
|
bind_env=True
|
|
)
|
|
|
|
assert opt.name == 'test-opt'
|
|
assert type(opt.default) != scheme.NoDefault
|
|
assert opt.default == 'foo'
|
|
assert opt.type == str
|
|
assert opt.choices == ['foo', 'bar']
|
|
assert opt.bind_env is True
|
|
|
|
@pytest.mark.parametrize(
|
|
'field_type,value', [
|
|
(str, 'test-value'),
|
|
(str, ''),
|
|
(int, 0),
|
|
(int, 1000),
|
|
(int, -1),
|
|
(float, 0.0),
|
|
(float, 1000.999),
|
|
(float, -1.0),
|
|
(bool, True),
|
|
(bool, False),
|
|
(list, []),
|
|
(list, [1, 2, 3]),
|
|
(list, ['a', 'b', 'c']),
|
|
(tuple, tuple()),
|
|
(tuple, (1,)),
|
|
(tuple, ('a', 'b')),
|
|
(dict, {}),
|
|
(dict, {'a': 'b'}),
|
|
(dict, {1: 2})
|
|
]
|
|
)
|
|
def test_validate_type_ok(self, field_type, value):
|
|
"""Validate an Option, where type validation succeeds"""
|
|
opt = scheme.Option('test-option', field_type=field_type)
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'field_type,value', [
|
|
(str, None),
|
|
(str, 1),
|
|
(str, 1.8),
|
|
(str, True),
|
|
(str, ['a', 'b', 'c']),
|
|
|
|
(int, None),
|
|
(int, 'value'),
|
|
(int, 1.8),
|
|
(int, True),
|
|
(int, ['a', 'b', 'c']),
|
|
|
|
(float, None),
|
|
(float, 'value'),
|
|
(float, 1),
|
|
(float, True),
|
|
(float, ['a', 'b', 'c']),
|
|
|
|
(bool, None),
|
|
(bool, 'value'),
|
|
(bool, 1),
|
|
(bool, 1.8),
|
|
(bool, ['a', 'b', 'c']),
|
|
|
|
(list, None),
|
|
(list, 'value'),
|
|
(list, 1),
|
|
(list, 1.8),
|
|
(list, True),
|
|
]
|
|
)
|
|
def test_validate_type_failure(self, field_type, value):
|
|
"""Validate an Option, where type validation fails"""
|
|
opt = scheme.Option('test-option', field_type=field_type)
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'choices,value', [
|
|
(['one', 'two'], 'one'), # choices can be lists
|
|
(('one', 'two'), 'one'), # choices can be tuples
|
|
([1, 2, 3], 1),
|
|
((1, 2, 3), 1),
|
|
([None], None),
|
|
((None,), None),
|
|
([1.21, 1.22, 1.23], 1.23),
|
|
((1.21, 1.22, 1.23), 1.23),
|
|
([True, False], False),
|
|
((True, False), False)
|
|
]
|
|
)
|
|
def test_validate_choices_ok(self, choices, value):
|
|
"""Validate an Option, where choice validation succeeds"""
|
|
opt = scheme.Option('test-option', choices=choices)
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'choices,value', [
|
|
(['one', 'two'], 'three'),
|
|
([1, 2, 3], 0),
|
|
([], None),
|
|
([0.2, 0.3, 0.4], 0.1),
|
|
([False], True)
|
|
]
|
|
)
|
|
def test_validate_choices_failure(self, choices, value):
|
|
"""Validate an Option, where choice validation succeeds"""
|
|
opt = scheme.Option('test-option', choices=choices)
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,value,expected', [
|
|
(scheme.Option('foo'), 'foo', 'foo'),
|
|
(scheme.Option('foo'), 1, 1),
|
|
(scheme.Option('foo'), None, None),
|
|
(scheme.Option('foo'), False, False),
|
|
(scheme.Option('foo', field_type=str), 'foo', 'foo'),
|
|
(scheme.Option('foo', field_type=str), 1, '1'),
|
|
(scheme.Option('foo', field_type=int), '1', 1),
|
|
(scheme.Option('foo', field_type=float), '1', 1.0),
|
|
(scheme.Option('foo', field_type=float), '1.23', 1.23),
|
|
(scheme.Option('foo', field_type=bool), 'false', False),
|
|
(scheme.Option('foo', field_type=bool), 'False', False),
|
|
(scheme.Option('foo', field_type=bool), 'FALSE', False),
|
|
(scheme.Option('foo', field_type=bool), 'true', True),
|
|
(scheme.Option('foo', field_type=bool), 'True', True),
|
|
(scheme.Option('foo', field_type=bool), 'TRUE', True),
|
|
]
|
|
)
|
|
def test_cast(self, option, value, expected):
|
|
"""Cast values to the type set by the Option."""
|
|
actual = option.cast(value)
|
|
assert actual == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,value', [
|
|
(scheme.Option('foo', field_type=int), 'foo'),
|
|
(scheme.Option('foo', field_type=list), 'foo'),
|
|
(scheme.Option('foo', field_type=tuple), 'foo'),
|
|
]
|
|
)
|
|
def test_cast_fail(self, option, value):
|
|
"""Cast values to the type set by the Option."""
|
|
with pytest.raises(errors.BisonError):
|
|
option.cast(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,prefix,auto_env', [
|
|
(scheme.Option('foo'), None, False),
|
|
(scheme.Option('foo', bind_env=False), None, False),
|
|
(scheme.Option('foo', bind_env=True), None, False),
|
|
(scheme.Option('foo', bind_env=True), 'TEST_ENV_', False),
|
|
|
|
(scheme.Option('foo', bind_env='TEST_KEY'), None, False),
|
|
(scheme.Option('foo', bind_env='TEST_KEY'), 'TEST_ENV_', False),
|
|
|
|
(scheme.Option('foo', bind_env=None), 'TEST_ENV_', False),
|
|
(scheme.Option('foo', bind_env=None), 'TEST_ENV_', True),
|
|
(scheme.Option('foo', bind_env=None), None, False),
|
|
(scheme.Option('foo', bind_env=None), None, True),
|
|
]
|
|
)
|
|
def test_parse_env_none(self, option, prefix, auto_env):
|
|
"""Parse environment variables for the Option. All of theses tests
|
|
should result in None being returned because no environment variables
|
|
are actually set.
|
|
"""
|
|
actual = option.parse_env(prefix=prefix, auto_env=auto_env)
|
|
assert actual is None
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,key,prefix,auto_env,expected', [
|
|
(scheme.Option('foo', bind_env=True), 'foo', 'TEST_ENV_', False, 'bar'),
|
|
(scheme.Option('foo', bind_env=True), 'foo', 'TEST_ENV_', True, 'bar'),
|
|
|
|
(scheme.Option('foo', bind_env='TEST_ENV_FOO'), 'foo', 'TEST_ENV_', False, 'bar'),
|
|
(scheme.Option('foo', bind_env='TEST_ENV_FOO'), 'foo', 'TEST_ENV_', True, 'bar'),
|
|
(scheme.Option('foo', bind_env='TEST_ENV_FOO'), 'foo', None, False, 'bar'),
|
|
(scheme.Option('foo', bind_env='TEST_ENV_FOO'), 'foo', None, True, 'bar'),
|
|
|
|
(scheme.Option('foo', bind_env=None), 'foo', 'TEST_ENV_', True, 'bar'),
|
|
(scheme.Option('foo', bind_env=None), 'nested.env.key', 'TEST_ENV_', True, 'test'),
|
|
]
|
|
)
|
|
def test_parse_env_ok(self, option, key, prefix, auto_env, expected, with_env):
|
|
"""Parse environment variables for the Option."""
|
|
actual = option.parse_env(key=key, prefix=prefix, auto_env=auto_env)
|
|
assert actual == expected
|
|
|
|
|
|
class TestDictOption:
|
|
"""Tests for the `DictOption` class."""
|
|
|
|
def test_init_simple(self):
|
|
"""Initialize a DictOption."""
|
|
opt = scheme.DictOption('test-opt', None)
|
|
|
|
assert opt.name == 'test-opt'
|
|
assert type(opt.default) == scheme.NoDefault
|
|
assert opt.scheme is None
|
|
assert opt.bind_env is False
|
|
|
|
def test_init_full(self):
|
|
"""Initialize a DictOption."""
|
|
opt = scheme.DictOption(
|
|
name='test-opt',
|
|
scheme=scheme.Scheme(),
|
|
default='foo',
|
|
bind_env=True
|
|
)
|
|
|
|
assert opt.name == 'test-opt'
|
|
assert type(opt.default) != scheme.NoDefault
|
|
assert opt.default == 'foo'
|
|
assert isinstance(opt.scheme, scheme.Scheme)
|
|
assert opt.bind_env is True
|
|
|
|
@pytest.mark.parametrize(
|
|
'value', [
|
|
'foo',
|
|
1,
|
|
1.234,
|
|
False,
|
|
True,
|
|
None,
|
|
[1, 2, 3],
|
|
['a', 'b', 'c'],
|
|
[{'a': 1}, {'b': 2}],
|
|
('foo', 'bar'),
|
|
{1, 2, 3}
|
|
]
|
|
)
|
|
def test_validate_bad_data(self, value):
|
|
"""Validate a DictOption where the given value is not a dict"""
|
|
opt = scheme.DictOption('test-opt', scheme.Scheme())
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(value)
|
|
|
|
def test_validate_no_scheme(self):
|
|
"""Validate a DictOption with no scheme"""
|
|
opt = scheme.DictOption('test-opt', None)
|
|
opt.validate({'foo': 'bar'})
|
|
|
|
def test_validate_with_scheme(self):
|
|
"""Validate a DictOption with a scheme"""
|
|
opt = scheme.DictOption('test-opt', scheme.Scheme(
|
|
scheme.Option('foo', field_type=str)
|
|
))
|
|
opt.validate({'foo': 'bar'})
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,prefix,auto_env', [
|
|
(scheme.DictOption('foo', scheme=None, bind_env=False), None, False),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=False), None, True),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=False), 'TEST_ENV', False),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=False), 'TEST_ENV', True),
|
|
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), None, False),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), None, True),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'TEST_ENV', False),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'TEST_ENV', True),
|
|
]
|
|
)
|
|
def test_parse_env_none(self, option, prefix, auto_env):
|
|
"""Parse environment variables for the DictOption. All of theses tests
|
|
should result in None being returned because no environment variables
|
|
are actually set.
|
|
"""
|
|
actual = option.parse_env(prefix=prefix, auto_env=auto_env)
|
|
assert actual is None
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,key,prefix,auto_env,expected', [
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'foo', 'TEST_ENV_', False, None),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'foo', 'TEST_ENV_', True, None),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'nested', 'TEST_ENV_', False, {'env': {'key': 'test'}}),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'nested', 'TEST_ENV_', True, {'env': {'key': 'test'}}),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'nested.env', 'TEST_ENV_', False, {'key': 'test'}),
|
|
(scheme.DictOption('foo', scheme=None, bind_env=True), 'nested.env', 'TEST_ENV_', True, {'key': 'test'}),
|
|
]
|
|
)
|
|
def test_parse_env_ok(self, option, key, prefix, auto_env, expected, with_env):
|
|
"""Parse environment variables for the DictOption."""
|
|
actual = option.parse_env(key=key, prefix=prefix, auto_env=auto_env)
|
|
assert actual == expected
|
|
|
|
|
|
class TestListOption:
|
|
"""Tests for the `ListOption` class."""
|
|
|
|
def test_init_simple(self):
|
|
"""Initialize a ListOption."""
|
|
opt = scheme.ListOption('test-opt')
|
|
|
|
assert opt.name == 'test-opt'
|
|
assert type(opt.default) == scheme.NoDefault
|
|
assert opt.member_type is None
|
|
assert opt.member_scheme is None
|
|
assert opt.bind_env is False
|
|
|
|
def test_init_full(self):
|
|
"""Initialize a ListOption."""
|
|
opt = scheme.ListOption(
|
|
name='test-opt',
|
|
default='foo',
|
|
member_type=dict,
|
|
member_scheme=scheme.Scheme(),
|
|
bind_env=True
|
|
)
|
|
|
|
assert opt.name == 'test-opt'
|
|
assert type(opt.default) != scheme.NoDefault
|
|
assert opt.default == 'foo'
|
|
assert opt.member_type == dict
|
|
assert isinstance(opt.member_scheme, scheme.Scheme)
|
|
assert opt.bind_env is True
|
|
|
|
@pytest.mark.parametrize(
|
|
'value', [
|
|
'foo',
|
|
1,
|
|
1.234,
|
|
False,
|
|
True,
|
|
None,
|
|
{'a': 1, 'b': 2},
|
|
('foo', 'bar'),
|
|
{1, 2, 3}
|
|
]
|
|
)
|
|
def test_validate_bad_data(self, value):
|
|
"""Validate when the value is not a list"""
|
|
opt = scheme.ListOption('test-opt')
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(value)
|
|
|
|
def test_validate_member_type_scheme_conflict(self):
|
|
"""Validate the ListOption when both member_type and member_scheme are defined."""
|
|
opt = scheme.ListOption(
|
|
name='test-opt',
|
|
member_type=int,
|
|
member_scheme=scheme.Scheme()
|
|
)
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate([1, 2, 3])
|
|
|
|
@pytest.mark.parametrize(
|
|
'member_type,value', [
|
|
(str, ['a', 'b', 'c']),
|
|
(int, [1, 2, 3]),
|
|
(float, [1.0, 2.0, 3.0]),
|
|
(bool, [False, False, True]),
|
|
(tuple, [(1,), (2,), (3,)]),
|
|
(list, [[1], [2], [3]]),
|
|
(dict, [{'a': 1, 'b': 2}])
|
|
]
|
|
)
|
|
def test_validate_member_type_ok(self, member_type, value):
|
|
"""Validate the ListOption, where member_type validation succeeds."""
|
|
opt = scheme.ListOption('test-opt', member_type=member_type)
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'member_type,value', [
|
|
(str, ['a', 1]),
|
|
(str, [1, 2]),
|
|
(int, [1, 2, '3']),
|
|
(int, ['foo', 'bar']),
|
|
(float, [1.0, '2.0', 3.0]),
|
|
(float, ['foo', 'bar']),
|
|
(bool, ['False', False, True]),
|
|
(bool, ['foo', 'bar']),
|
|
(tuple, [(1,), '(2,)', (3,)]),
|
|
(tuple, ['']),
|
|
(list, [[1], (2,), [3]]),
|
|
(list, ['foo', 'bar']),
|
|
(dict, [{'a': 1}, {1, 2, 3}]),
|
|
(dict, ['foo', 'bar'])
|
|
]
|
|
)
|
|
def test_validate_member_type_failure(self, member_type, value):
|
|
"""Validate the ListOption, where member_type validation fails."""
|
|
opt = scheme.ListOption('test-opt', member_type=member_type)
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'member_scheme,value', [
|
|
# an empty scheme will validate every dict as correct
|
|
(scheme.Scheme(), [{'foo': 'bar'}]),
|
|
(scheme.Scheme(), [{1: 3}]),
|
|
(scheme.Scheme(), [{1.23: 2.31}]),
|
|
(scheme.Scheme(), [{False: True}]),
|
|
(scheme.Scheme(), [{None: None}]),
|
|
(scheme.Scheme(), [{(1, 2): (2, 1)}]),
|
|
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 'bar'}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 'baz'}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 'baz'}, {'foo': 'bar'}])
|
|
]
|
|
)
|
|
def test_validate_member_scheme_ok(self, member_scheme, value):
|
|
"""Validate the ListOption, where member_scheme validation succeeds."""
|
|
opt = scheme.ListOption('test-opt', member_scheme=member_scheme)
|
|
opt.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'member_scheme,value', [
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 1}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': 1.23}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': False}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': True}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': None}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': (1, 2)}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': ['a', 'b']}]),
|
|
(scheme.Scheme(scheme.Option('foo', field_type=str)), [{'foo': {'a', 'b'}}]),
|
|
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': 'foo'}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': 1.23}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': False}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': True}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': None}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': (1, 2)}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': ['a', 'b']}]),
|
|
(scheme.Scheme(scheme.Option('bar', field_type=int)), [{'bar': {'a', 'b'}}])
|
|
]
|
|
)
|
|
def test_validate_member_scheme_fail(self, member_scheme, value):
|
|
"""Validate the ListOption, where member_scheme validation fails."""
|
|
opt = scheme.ListOption('test-opt', member_scheme=member_scheme)
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(value)
|
|
|
|
def test_validate_member_scheme_not_a_scheme(self):
|
|
"""Validate the ListOption, where the member_scheme is not a Scheme."""
|
|
opt = scheme.ListOption('test-opt', member_scheme='not-none-or-scheme')
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
opt.validate(['a', 'b', 'c'])
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,prefix,auto_env', [
|
|
(scheme.ListOption('foo', bind_env=False), None, False),
|
|
(scheme.ListOption('foo', bind_env=False), None, True),
|
|
(scheme.ListOption('foo', bind_env=False), 'TEST_ENV', False),
|
|
(scheme.ListOption('foo', bind_env=False), 'TEST_ENV', True),
|
|
|
|
(scheme.ListOption('foo', bind_env=True), None, False),
|
|
(scheme.ListOption('foo', bind_env=True), None, True),
|
|
(scheme.ListOption('foo', bind_env=True), 'TEST_ENV', False),
|
|
(scheme.ListOption('foo', bind_env=True), 'TEST_ENV', True),
|
|
]
|
|
)
|
|
def test_parse_env_none(self, option, prefix, auto_env):
|
|
"""Parse environment variables for the ListOption. All of theses tests
|
|
should result in None being returned because no environment variables
|
|
are actually set.
|
|
"""
|
|
actual = option.parse_env(prefix=prefix, auto_env=auto_env)
|
|
assert actual is None
|
|
|
|
@pytest.mark.parametrize(
|
|
'option,key,prefix,auto_env,expected', [
|
|
(scheme.ListOption('foo', bind_env=True), 'foo', 'TEST_ENV_', False, ['bar']),
|
|
(scheme.ListOption('foo', bind_env=True), 'foo', 'TEST_ENV_', True, ['bar']),
|
|
(scheme.ListOption('foo', bind_env=True), 'bar.list', 'TEST_ENV_', False, ['a', 'b', 'c']),
|
|
(scheme.ListOption('foo', bind_env=True), 'bar.list', 'TEST_ENV_', True, ['a', 'b', 'c']),
|
|
]
|
|
)
|
|
def test_parse_env_ok(self, option, key, prefix, auto_env, expected, with_env):
|
|
"""Parse environment variables for the ListOption."""
|
|
actual = option.parse_env(key=key, prefix=prefix, auto_env=auto_env)
|
|
assert actual == expected
|
|
|
|
|
|
class TestScheme:
|
|
"""Tests for the `Scheme` class."""
|
|
|
|
def test_empty_init(self):
|
|
"""Initialize a Scheme with no arguments."""
|
|
sch = scheme.Scheme()
|
|
|
|
assert len(sch.args) == 0
|
|
assert sch._flat is None
|
|
|
|
def test_single_arg_init(self):
|
|
"""Initialize a Scheme with one argument."""
|
|
sch = scheme.Scheme(
|
|
'item'
|
|
)
|
|
|
|
assert len(sch.args) == 1
|
|
assert sch._flat is None
|
|
|
|
def test_multi_arg_init(self):
|
|
"""Initialize a Scheme with multiple arguments."""
|
|
sch = scheme.Scheme(
|
|
'item-1',
|
|
'item-2',
|
|
'item-3'
|
|
)
|
|
|
|
assert len(sch.args) == 3
|
|
assert sch._flat is None
|
|
|
|
@pytest.mark.parametrize(
|
|
'args,expected', [
|
|
(
|
|
# args
|
|
(scheme.Option('foo', default='bar'),),
|
|
# expected
|
|
{'foo': 'bar'}
|
|
),
|
|
(
|
|
# args
|
|
(
|
|
scheme.Option('foo'),
|
|
scheme.Option('bar', default='baz'),
|
|
scheme.ListOption('list', default=['a', 'b'])
|
|
),
|
|
# expected
|
|
{
|
|
'bar': 'baz',
|
|
'list': ['a', 'b']
|
|
}
|
|
),
|
|
(
|
|
# args
|
|
(
|
|
scheme.Option('foo', default='bar'),
|
|
scheme.DictOption('bar', scheme=None)
|
|
),
|
|
# expected
|
|
{
|
|
'foo': 'bar'
|
|
}
|
|
),
|
|
(
|
|
# args
|
|
(
|
|
scheme.DictOption('foo', scheme=scheme.Scheme(), default={}),
|
|
scheme.DictOption('bar', scheme=scheme.Scheme(
|
|
scheme.Option('test', default=True),
|
|
scheme.Option('data', default=None),
|
|
scheme.Option('value', default=20),
|
|
scheme.Option('float', default=10.1010),
|
|
scheme.Option('no_default'),
|
|
scheme.DictOption('dct', scheme=scheme.Scheme(
|
|
scheme.Option('nested', default='here')
|
|
))
|
|
))
|
|
),
|
|
# expected
|
|
{
|
|
'foo': {},
|
|
'bar': {
|
|
'test': True,
|
|
'data': None,
|
|
'value': 20,
|
|
'float': 10.1010,
|
|
'dct': {
|
|
'nested': 'here'
|
|
}
|
|
}
|
|
}
|
|
),
|
|
]
|
|
)
|
|
def test_build_defaults(self, args, expected):
|
|
"""Build a defaults dict from a Scheme."""
|
|
sch = scheme.Scheme(*args)
|
|
defaults = sch.build_defaults()
|
|
|
|
assert defaults == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
'args', [
|
|
('a', 'b'), # not an instance of _BaseOpt
|
|
]
|
|
)
|
|
def test_build_defaults_failure(self, args):
|
|
"""Build a defaults dict from a Scheme with bad data."""
|
|
sch = scheme.Scheme(*args)
|
|
with pytest.raises(errors.InvalidSchemeError):
|
|
sch.build_defaults()
|
|
|
|
@pytest.mark.parametrize(
|
|
'args,expected', [
|
|
(
|
|
(scheme.Option('foo'),),
|
|
['foo']
|
|
),
|
|
(
|
|
(scheme.Option('foo'), scheme.Option('bar')),
|
|
['foo', 'bar']
|
|
),
|
|
(
|
|
(scheme.Option('foo'), scheme.DictOption('bar', scheme=None)),
|
|
['foo', 'bar']
|
|
),
|
|
(
|
|
(
|
|
scheme.Option('foo'),
|
|
scheme.DictOption('bar', scheme=scheme.Scheme(
|
|
scheme.Option('test'),
|
|
scheme.DictOption('dct', scheme=scheme.Scheme(
|
|
scheme.Option('nested')
|
|
)),
|
|
scheme.ListOption('list')
|
|
))
|
|
),
|
|
['foo', 'bar', 'bar.test', 'bar.dct', 'bar.list', 'bar.dct.nested']
|
|
)
|
|
]
|
|
)
|
|
def test_flatten(self, args, expected):
|
|
"""Flatten a Scheme."""
|
|
sch = scheme.Scheme(*args)
|
|
flattened = sch.flatten()
|
|
|
|
assert len(flattened) == len(expected)
|
|
for key in expected:
|
|
assert key in flattened
|
|
|
|
@pytest.mark.parametrize(
|
|
'args,value', [
|
|
(
|
|
# option exists in config
|
|
(scheme.Option('foo', default='bar', field_type=str),),
|
|
{'foo': 'baz'}
|
|
),
|
|
(
|
|
# option does not exist in config and has default, but is not required
|
|
(scheme.Option('foo', default='bar', required=False, field_type=str),),
|
|
{}
|
|
),
|
|
(
|
|
# multiple args
|
|
(
|
|
scheme.Option('foo', field_type=str),
|
|
scheme.Option('bar', field_type=int),
|
|
scheme.Option('baz', choices=['test'])
|
|
),
|
|
{'foo': 'a', 'bar': 1, 'baz': 'test'}
|
|
),
|
|
(
|
|
# optional parent option not specified, required child option
|
|
# not specified
|
|
(
|
|
scheme.DictOption('foo', required=False, scheme=scheme.Scheme(
|
|
scheme.Option('bar', field_type=str),
|
|
scheme.Option('baz', field_type=str),
|
|
)),
|
|
),
|
|
{}
|
|
)
|
|
]
|
|
)
|
|
def test_validate_ok(self, args, value):
|
|
"""Validate a Scheme successfully."""
|
|
sch = scheme.Scheme(*args)
|
|
sch.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'args,value', [
|
|
(
|
|
# option does not exist in config, no default
|
|
(scheme.Option('foo', field_type=str),),
|
|
{}
|
|
),
|
|
(
|
|
# option exists in config, fails validation
|
|
(scheme.Option('foo', default='bar', field_type=str),),
|
|
{'foo': 1}
|
|
),
|
|
(
|
|
# multiple args, one fails validation
|
|
(
|
|
scheme.Option('foo', field_type=str),
|
|
scheme.Option('bar', field_type=int),
|
|
scheme.Option('baz', choices=['test'])
|
|
),
|
|
{'foo': 'a', 'bar': 1, 'baz': 'something'}
|
|
),
|
|
(
|
|
# optional parent option specified, required child option
|
|
# not specified
|
|
(
|
|
scheme.DictOption('foo', required=True, scheme=scheme.Scheme(
|
|
scheme.Option('bar', field_type=str),
|
|
scheme.Option('baz', field_type=str),
|
|
)),
|
|
),
|
|
{'foo': {'baz': 2}}
|
|
)
|
|
]
|
|
)
|
|
def test_validate_failure(self, args, value):
|
|
"""Validate a Scheme unsuccessfully."""
|
|
sch = scheme.Scheme(*args)
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
sch.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'value', [
|
|
'foo',
|
|
1,
|
|
1.23,
|
|
['a', 'b', 'c'],
|
|
{'a', 'b', 'c'},
|
|
('a', 'b', 'c'),
|
|
None,
|
|
False,
|
|
True
|
|
]
|
|
)
|
|
def test_validate_failure_bad_config(self, value):
|
|
"""Validate a Scheme where the given config is not a dict."""
|
|
sch = scheme.Scheme()
|
|
with pytest.raises(errors.SchemeValidationError):
|
|
sch.validate(value)
|
|
|
|
@pytest.mark.parametrize(
|
|
'args,value', [
|
|
(
|
|
# option does not exist in config, has default, not required
|
|
(scheme.Option('foo', default='bar'),),
|
|
{}
|
|
),
|
|
(
|
|
# option does not exist in config, has default, not required
|
|
(
|
|
scheme.DictOption('foo', scheme=scheme.Scheme(
|
|
scheme.Option('bar', default=1),
|
|
scheme.Option('baz'),
|
|
)),
|
|
),
|
|
{'foo': {'baz': 2}}
|
|
),
|
|
(
|
|
# option does not exist in config, has default, not required
|
|
(
|
|
scheme.ListOption('foo', member_scheme=scheme.Scheme(
|
|
scheme.Option('bar', default=1),
|
|
scheme.Option('baz'),
|
|
)),
|
|
),
|
|
{'foo': [{'baz': 2}, {'bar': 3, 'baz': 2}]}
|
|
),
|
|
]
|
|
)
|
|
def test_validate_has_default(self, args, value):
|
|
"""Validate a Scheme where a default value is set, and the required field
|
|
may or may not be set.
|
|
|
|
If a default value is provided, it should be assumed to not be required.
|
|
"""
|
|
sch = scheme.Scheme(*args)
|
|
sch.validate(value)
|