You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
5.2 KiB

# pylint: disable=redefined-outer-name
from copy import deepcopy
import pytest
import preserve
from configspec import *
@pytest.fixture
def example_spec():
confspec = ConfigSpecification()
confspec.add_spec("bool_a", BoolSpec(helptext="Bool A"))
confspec.add_spec("boollist_a", ListSpec(BoolSpec(), helptext="Bool List A"))
confspec.add_spec("int_a", IntSpec(-4, 4, helptext="Int A"))
confspec.add_spec("intlist_a", ListSpec(IntSpec(-4, 4, "Int A")))
confspec.add_spec("float_a", FloatSpec(-4, 4, helptext="Float A"))
confspec.add_spec("floatlist_a", ListSpec(FloatSpec(-4, 4, "Float A")))
confspec.add_spec("string_a", StringSpec(helptext="String A"))
confspec.add_spec("string_a_blank", StringSpec(allowempty=True, helptext="String A Blank"))
confspec.add_spec("stringlist_a", ListSpec(StringSpec(), helptext="String List A"))
confdictspec = confspec.add_spec("dict_a", DictSpec(helptext="Dict A"))
confdictspec.add_spec("bool_b", BoolSpec(helptext="Bool B"))
confdictspec.add_spec("int_b", IntSpec(helptext="Int B"))
confdictspec.add_spec("float_b", FloatSpec(helptext="Float B"))
confdictspec.add_spec("string_b", StringSpec(helptext="String B"))
confdictlist = confspec.add_spec("dictlist_a", ListSpec(
DictSpec(), helptext="List of Dicts B"))
confdictlist.add_specs({"bool_c": BoolSpec(helptext="Bool C"),
"int_c": IntSpec(helptext="Int C"),
"float_c": FloatSpec(helptext="Float C"),
"string_c": StringSpec(helptext="String C")})
return confspec
@pytest.fixture
def example_values():
vals = {'bool_a': True,
'boollist_a': [False, True],
'int_a': 1,
'intlist_a': [1, 2, 3, 4],
'float_a': 1.5,
'floatlist_a': [1.2, 2.1, 3.7, 2.8],
'string_a': 'sometext',
'string_a_blank': '',
'stringlist_a': ['somemoretext', 'yetmoretext'],
'dict_a': {
'bool_b': False,
'int_b': 0,
'float_b': 0.5,
'string_b': 'texttesttext'},
'dictlist_a': [{'bool_c': False,
'int_c': 3,
'float_c': 3.4,
'string_c': 'string1'},
{'bool_c': True,
'int_c': 0,
'float_c': 0.4,
'string_c': 'string2'}]}
return vals
def test_addspec(example_spec):
# Most of the test is really just forming the fixture without exception
assert isinstance(example_spec, ConfigSpecification)
def test_preserveable(example_spec):
assert isinstance(preserve.preserve(example_spec), dict)
def test_config_validate(example_spec, example_values):
example_spec.validate(example_values)
def test_invalid_bool():
spec = BoolSpec()
with pytest.raises(InvalidConfigError, match="value must be a boolean"):
spec.validate("false")
with pytest.raises(InvalidConfigError, match="value must be a boolean"):
spec.validate(None)
def test_invalid_int():
spec = IntSpec(minval=-4, maxval=4)
with pytest.raises(InvalidConfigError, match="value must be >="):
spec.validate(-5)
with pytest.raises(InvalidConfigError, match="value must be <="):
spec.validate(5)
with pytest.raises(InvalidConfigError, match="value must be an integer"):
spec.validate("5")
with pytest.raises(InvalidConfigError, match="value must be an integer"):
spec.validate(None)
def test_invalid_string():
spec = StringSpec()
# TODO add regex check
with pytest.raises(InvalidConfigError, match="value must be a string"):
spec.validate(1)
with pytest.raises(InvalidConfigError, match="value must be a string"):
spec.validate(None)
with pytest.raises(InvalidConfigError, match="value cannot be a blank string"):
spec.validate("")
def test_dict_optional():
spec = DictSpec()
spec.add_spec("int1", IntSpec())
spec.add_spec("int2", IntSpec(), optional=True)
spec.add_spec("int3", IntSpec(), optional=True, default=1)
with pytest.raises(InvalidConfigError, match="must contain key 'int1'"):
spec.validate({})
with pytest.raises(InvalidConfigError, match="contains unknown key"):
spec.validate({"int1": 1, "int5": 0})
d = {"int1": 1, "int2": 2, "int3": 3}
spec.validate(d)
assert d == {"int1": 1, "int2": 2, "int3": 3}
d = {"int1": 1}
spec.validate(d)
assert d == {"int1": 1, "int2": None, "int3": 1}
def test_man(example_spec, example_values):
confman = ConfigManager()
confman.add_confspec("test_bundle", example_spec)
confman.load({"test_bundle": example_values})
assert confman.get_config_bundle("test_bundle") == example_values
confman.freeze_value("test_bundle", "int_a")
newvals = deepcopy(example_values)
newvals["int_a"] = 4
confman.load({"test_bundle": newvals})
assert confman.get_config_bundle("test_bundle") == example_values
confman.load_overlay({"test_bundle": {"string_a": "new text"}})
assert confman.get_config_bundle("test_bundle")["string_a"] == "new text"