def test_can_set_str_value_to_none(): c = Item('a', default='haha') assert c.value == 'haha' assert c.type is Types.str c.value = None assert c.value is None
def cx(): return Config([ ('with_', Item(name='with')), ('for', Config([ ('continue_', Item(name='continue')), ])), ])
def test_item_value_can_be_unicode_str(): c = Item(default=u'Jānis Bērziņš') assert c.str_value == u'Jānis Bērziņš' c.value = u'Pēteris Liepiņš' assert c.str_value == u'Pēteris Liepiņš' assert c.default == u'Jānis Bērziņš'
def test_read_reads_multiple_files_in_order(tmpdir): m = Config({ 'a': { 'x': Item(type=float), 'y': 'aye', }, 'b': { 'm': False, 'n': Item(type=int), } }) path1 = tmpdir.join('config1.ini').strpath path2 = tmpdir.join('config2.ini').strpath path3 = tmpdir.join('config3.ini').strpath # Empty file m.configparser.dump(path1) # Can load from one empty file m.configparser.load(path1) assert m.is_default m.a.x.value = 0.33 m.b.n.value = 42 m.configparser.dump(path2) # Can load from one non-empty file m.reset() m.configparser.load(path2) assert not m.is_default assert m.a.x.value == 0.33 m.reset() m.a.x.value = 0.66 m.b.m.value = 'YES' m.configparser.dump(path3) m.reset() m.configparser.load([path1, path2, path3]) assert m.a.x.value == 0.66 assert m.a.y.is_default assert m.b.m.value is True assert m.b.m.raw_str_value == 'YES' assert m.b.n.value == 42 m.reset() m.configparser.load([path3, path2, path1]) assert m.a.x.value == 0.33 # this is the only difference with the above order assert m.a.y.is_default assert m.b.m.value is True assert m.b.m.raw_str_value == 'YES' assert m.b.n.value == 42 # Make sure multiple paths not supported in non-list syntax. with pytest.raises(TypeError): m.configparser.load(path3, path2, path1)
def test_value_gets_stringified(): c = Item('a', value='23') assert c.value == '23' assert c.value != 23 c.value = 24 assert c.value == '24' assert c.value != 24
def test_item_type_can_be_specified_as_a_string(): i = Item(type='int', default='3') assert i.default == 3 b = Item(type='boolean', default='yes') assert b.default is True f = Item(type='float', default='0.23') assert f.default == 0.23
def test_non_special_default_values_are_converted_to_items_declared_type(): i = Item(type=int, default='3') assert i.default == 3 b = Item(type=bool, default='yes') assert b.default is True f = Item(type=float, default='0.23') assert f.default == 0.23
def test_item_value_is_not_deep_copied_on_value_request(): precious_things = ['a', 'b'] c = Item(default=precious_things) c.value = ['c', 'd'] c.value.append('e') assert c.value == ['c', 'd', 'e'] assert c.default == ['a', 'b']
def test_raw_str_value_is_reset_on_reset(): c = Item('a', type=int, default=25) assert c.str_value == '25' c.value = '23' assert c.str_value == '23' c.reset() assert c.str_value == '25'
def test_item_with_no_value_and_no_default_returns_not_set_as_value(): c = Item('a') assert c.value is not_set c.value = 'hey' assert c.value == 'hey' c.reset() assert c.value is not_set
def test_int_value(): c = Item('a', type=int, default=25) assert c.value == 25 c.value = '23' assert c.value == 23 assert c.value != '23' c.reset() assert c.value == 25
def test_assigning_nameless_item_directly_to_config_should_set_its_name(): config = Config() config.dummy = Config() config.dummy.x = Item(value=5) assert config.dummy.x.name == 'x' config.dummy['y'] = Item(default=True) assert config.dummy.y.name == 'y' assert config.dump_values() == {'dummy': {'x': 5, 'y': True}}
def test_bool_config_preserves_raw_str_value_used_to_set_it(): c = Item('a', type=bool, default=False) assert c.value is False assert not c.value assert c.str_value == 'False' assert c.value is False c.value = 'False' assert not c.value assert c.str_value == 'False' assert c.value is False c.value = 'no' assert not c.value assert c.str_value == 'no' assert c.value is False c.value = '0' assert not c.value assert c.str_value == '0' assert c.value is False c.value = '1' assert c.value assert c.str_value == '1' assert c.value is True c.reset() assert not c.value assert c.value is False c.value = 'yes' assert c.str_value == 'yes' assert c.value is True
def test_different_items_are_unequal_even_when_state_matches(): # This is so that we can have items hashable. # There is no need to compare two items. Compare values or other attributes, but the whole # thing is just an illusion. c = Item('a', type=str, value=None) cc = Item('a', type=str, value=None) assert c != cc d = Item('a', type=int, value=None) assert c != d
def test_item_name_and_alias_must_be_a_string(): config = Config() with pytest.raises(TypeError): config.x = Item(name=5) with pytest.raises(TypeError): config[5] = Item() with pytest.raises(TypeError): config[5] = Item(name='x')
def test_item_is_equal_to_itself(): c = Item('a') assert c == c d = Item('a', value='d') assert d == d e = Item('a', default='e') assert e == e f = Item('a', default='f', value='g') assert f == f
def test_reset_resets_values_to_defaults(): config = Config({'x': Item(type=int), 'y': Item(default='YES')}) config.x.value = 23 config.y.value = 'NO' assert config.x.value == 23 assert config.y.value == 'NO' config.reset() assert config.x.is_default assert config.y.value == 'YES'
def test_item_sets_unrecognised_kwargs_as_attributes(): c = Item(help='This is help', comment='This is comment', default=5, something_random=True) c.value = 5 assert c.is_default assert c.help == 'This is help' assert c.comment == 'This is comment' assert c.something_random with pytest.raises(AttributeError): assert c.something_too_random
def test_type_is_guessed_either_from_default_or_value(): c = Item() assert c.type is Types.str c = Item(value='haha') assert c.type is Types.str c = Item(value=u'hāhā') assert c.type is Types.str assert c.value == u'hāhā' assert c.str_value == u'hāhā' c = Item(default='haha') assert c.type is Types.str c = Item(default=u'haha') assert c.type is Types.str d = Item(default=5) assert d.type is Types.int e = Item(value=5) assert e.type is Types.int f = Item(default=None, value=5) assert f.type is Types.int
def test_to_dict_should_not_include_items_with_no_usable_value(): config = Config() assert config.dump_values() == {} config.a = Item() config.b = Item() config.dummies = Config({'x': Item(), 'y': Item()}) assert config.dump_values() == {} config.dummies.x.value = 'yes' assert config.dump_values() == {'dummies': {'x': 'yes'}} config.b.value = 'no' assert config.dump_values() == {'dummies': {'x': 'yes'}, 'b': 'no'}
def test_read_string(): m = Config({ 'a': { 'x': Item(), 'y': Item(), }, 'b': { 'm': Item(), 'n': Item(), }, }) m.configparser.loads(u'[a]\nx = haha\ny = yaya\n') assert m.a.x.value == 'haha' assert m.a.y.value == 'yaya'
def test_validate_raises_required_value_missing(): config = Config({ 'a': Item(required=True), 'b': Item(), }) with pytest.raises(RequiredValueMissing): config.validate() config.a.set('value') config.validate() config.a.reset() with pytest.raises(RequiredValueMissing): config.validate()
def test_int_type(): number = Item(type=Types.int, default='55') assert number.default == 55 assert number.value == 55 assert number.str_value == '55' number.value = -55 assert number.value == -55 number.value = '-555' assert number.value == -555 assert Types.guess(5) == Types.int assert Types.guess(-5) == Types.int assert Types.guess(0) == Types.int
def test_float_type(): rate = Item(type=Types.float, default='0.23') assert rate.default == 0.23 assert rate.value == 0.23 rate.value = '0.01' assert rate.value == 0.01 rate.value = '-0.23' assert rate.value == -0.23 assert Types.guess(0.23) == Types.float assert Types.guess(-0.23) == Types.float assert Types.guess('-0.23') is not Types.float assert Types.guess('0.23') is not Types.float
def test_can_have_a_dict_as_a_config_value_if_wrapped_inside_item(): # You may want to have a dictionary as a config value if you only # change it all together or you only pass it all in one piece. config = Config({ 'db': { 'user': '******', 'password': '******', }, 'aws': Item(default={ 'access_key': '123', 'secret_key': 'secret', }) }) assert isinstance(config.aws, Item) assert config.aws.name == 'aws' with pytest.raises(AttributeError): assert config.aws.access_key.value == '123' assert config.aws.value['access_key'] == '123' # This should have no effect because it is working on a copy of the default # value, not the real thing. config.aws.value['secret_key'] = 'NEW_SECRET' assert config.dump_values()['aws'] == { 'access_key': '123', 'secret_key': 'secret' }
def test_required_value_missing_includes_item(): item1 = Item(required=True) with pytest.raises(RequiredValueMissing) as exc1: _ = item1.value assert exc1.value.name is not_set assert exc1.value.item is item1 item2 = Item(name='greeting', required=True) with pytest.raises(RequiredValueMissing) as exc2: _ = item2.value assert exc2.value.name == 'greeting' assert exc2.value.item is item2
def test_item_value_changed_hook_not_called_when_resetting_a_not_set(): config = Config({'a': Item()}) @config.hooks.item_value_changed def item_value_changed(item, old_value, new_value): raise AssertionError('This should not have been called') config.reset() config.a.value = not_set
def test_is_default_respects_envvar(monkeypatch): a = Item('a', default=5, envvar=True) assert a.is_default monkeypatch.setenv('A', '5') assert a.is_default monkeypatch.setenv('A', '6') assert not a.is_default
def test_set_sets_value(): a = Item(type=int) assert not a.has_value a.set(5) assert a.has_value assert a.value == 5 b = Item(default=55) b.set(5) assert b.value == 5
def test_item_default_value_is_deep_copied_on_value_request(): precious_things = ['a', 'b'] c = Item(default=precious_things) c.value.append( 'c' ) # This has no effect because the value was created on the fly and no-one stored it. assert c.value == ['a', 'b'] assert c.default == ['a', 'b'] assert precious_things == ['a', 'b']