def test_change_is_a_merge_of_all_changes_in_context():
    config = Config({
        'a': 1,
    })

    config.a.set('2')

    with config.changeset_context() as ctx:
        config.a.set(3)
        config.a.set(4)
        config.a.set('5')

        assert ctx.changes[config.a].old_value == 2
        assert ctx.changes[config.a].old_raw_str_value == '2'
        assert ctx.changes[config.a].new_value == 5
        assert ctx.changes[config.a].new_raw_str_value == '5'

        config.a.set(6)

        assert ctx.changes[config.a].old_value == 2
        assert ctx.changes[config.a].old_raw_str_value == '2'
        assert ctx.changes[config.a].new_value == 6
        assert ctx.changes[config.a].new_raw_str_value is not_set

        ctx.reset()

        assert config.a not in ctx.changes
Esempio n. 2
0
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'
    }
Esempio n. 3
0
def test_config_of_configs():
    uploads = Config({
        'threads': 1,
        'enabled': True,
        'api': {
            'port': 8000,
        }
    })

    downloads = Config({
        'tmp_dir': '/tmp',
        'db': {
            'user': '******',
        }
    })

    config = Config({
        'uploads': uploads,
        'downloads': downloads,
        'messages': {
            'greeting': 'Hello',
        }
    })

    assert config.uploads.threads.is_item
    assert config.uploads.api.port.is_item
    assert config.downloads.db.user.is_item
    assert config.messages.greeting.is_item
def cx():
    return Config([
        ('with_', Item(name='with')),
        ('for', Config([
            ('continue_', Item(name='continue')),
        ])),
    ])
def test_dict_with_all_keys_prefixed_with_at_symbol_is_treated_as_item_meta():
    config = Config({
        'enabled': {
            '@default': False,
        },
        'db': {
            'user': '******',
            'name': {
                '@help': 'Name of the database'
            },
            '@help': 'db configuration',  # This should be ignored for now
        },
    })

    paths = set(path for path, _ in config.iter_items(recursive=True, key='str_path'))
    assert 'enabled' in paths
    assert 'enabled.@default' not in paths
    assert 'db' not in paths
    assert 'db.@help' not in paths
    assert 'db.user' in paths
    assert 'db.name' in paths
    assert 'db.name.@help' not in paths

    assert config.enabled.default is False
    assert config.db.name.help == 'Name of the database'

    # Make sure it still behaves like a bool
    config.enabled.value = 'yes'
    assert config.enabled.value is True

    # Name is excluded because it has no value
    assert config.db.dump_values() == {'user': '******'}

    config.db.name.value = 'testdb'
    assert config.db.dump_values() == {'user': '******', 'name': 'testdb'}
def test_resets_single_item_changes():
    config = Config({'a': 'aaa', 'b': 'bbb', 'c': 'ccc'})

    config.c.value = 'CCC'

    assert config.a.raw_str_value is not_set
    assert config.c.raw_str_value == 'CCC'

    with config.changeset_context() as ctx:

        config.a.value = 'AAA'
        config.b.value = 'BBB'
        config.c.value = 'seeseesee'
        assert config.c.raw_str_value == 'seeseesee'

        assert len(ctx.values) == 3

        ctx.reset(config.a)

        assert len(ctx.values) == 2
        assert ctx.values[config.b] == 'BBB'
        assert ctx.values[config.c] == 'seeseesee'

        assert config.a.value == 'aaa'
        assert config.b.value == 'BBB'
        assert config.c.value == 'seeseesee'

        ctx.reset(config.c)

        assert config.a.value == 'aaa'
        assert config.b.value == 'BBB'
        assert config.c.value == 'CCC'

    assert config.a.raw_str_value is not_set
    assert config.c.raw_str_value == 'CCC'
def test_config_of_configs():
    config = Config({
        'uploads': Config({
            'a': 1,
            'b': True,
            'c': 'ccc',
        }),
        'downloads': Config({
            'd': {
                'e': 'eee',
            },
            'f': 'fff',
        }),
    })

    with config.changeset_context() as ctx:
        config.uploads.a.value = 2
        config.downloads.d.e.value = 'EEE'
        config.downloads.f.value = 'FFF'

    assert len(ctx.values) == 3
    assert ctx.values[config.uploads.a] == 2
    assert ctx.values[config.downloads.d.e] == 'EEE'
    assert ctx.values[config.downloads.f] == 'FFF'

    assert not config.is_default
    assert config.uploads.a.value == 2
    assert config.downloads.d.e.value == 'EEE'
    assert config.downloads.f.value == 'FFF'

    ctx.reset()
    assert config.is_default
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)
Esempio n. 9
0
def test_section_knows_its_alias():
    config = Config()
    config.uploads = Config({'enabled': True})
    assert config.uploads.alias == 'uploads'

    config.uploads.db = Config({'connection': {'user': '******'}})
    assert config.uploads.db.alias == 'db'
    assert config.uploads.db.connection.alias == 'connection'
Esempio n. 10
0
def mixed_app_config(raw_logging_config, raw_db_config):
    """
     A config that contains a previously existing config
     as well as one generated on initialisation.
    """
    return Config({
        'logging': Config(raw_logging_config),
        'db': raw_db_config,
    })
Esempio n. 11
0
def initialize_db_process(config_values):
    from aleph.web import app
    from configmanager import Config
    from aleph.config import get_defaults
    config = Config(schema=get_defaults())
    app['config'] = config
    config.load_values(config_values)

    filestore.init_store(config)
Esempio n. 12
0
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
Esempio n. 13
0
def test_tracking_with_no_default_and_no_custom_value():
    config = Config({'a': {'@type': 'int'}})

    with config.changeset_context() as ctx:
        config.a.value = 55

    assert ctx.values[config.a] == 55
    assert len(ctx.values) == 1

    ctx.reset()
    assert len(ctx.values) == 0
Esempio n. 14
0
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')
Esempio n. 15
0
def config():
    return Config(schema={
        'uploads': {
            'enabled': False,
            'threads': 1,
            'db': Config({
                'user': '******',
                'password': '******',
            }),
        },
        'greeting': 'Hello',
    })
Esempio n. 16
0
def test_can_use__setitem__to_create_new_deep_paths():
    config = Config()
    config['uploads'] = Config({'enabled': True})

    with pytest.raises(TypeError):
        config['uploads', 'threads'] = 5

    config['uploads', 'threads'] = Item(value=5)
    assert config.uploads.threads.type == Types.int

    config['uploads', 'db'] = Config({'user': '******'})
    assert config.uploads.db
Esempio n. 17
0
def test_hooks_work_across_nested_configs():
    config = Config({
        'a':
        Config({
            'aa': Config({
                'aaa': 'aaa-default',
            }),
            'ab': {
                'aba': 'aba-default',
            },
            'ac': 'ac-default',
        }),
        'b': {
            'ba': Config({
                'baa': 'baa-default',
            }),
            'bb': {
                'bba': 'bba-default',
            },
            'bc': 'bc-default',
        },
        'c':
        'c-default',
    })

    calls = []

    @config.hooks.item_value_changed
    def item_value_changed(item):
        calls.append(('root', '.'.join(item.get_path())))

    assert len(calls) == 0

    config.c.value = 'c-1'
    assert len(calls) == 1

    config.a.ac.value = 'ac-1'
    assert len(calls) == 2

    config.a.aa.aaa.value = 'aaa-1'
    assert len(calls) == 3

    config.a.ab.aba.value = 'aba-1'
    assert len(calls) == 4

    config.b.bc.value = 'bc-1'
    assert len(calls) == 5

    config.b.ba.baa.value = 'baa-1'
    assert len(calls) == 6

    config.b.bb.bba.value = 'bba-1'
    assert len(calls) == 7
Esempio n. 18
0
def test_item_reset_is_tracked():
    config = Config({'a': 'aaa'})
    config.a.value = 'bbb'

    with config.changeset_context() as ctx:
        config.a.value = 'ccc'
        assert len(ctx.values) == 1

        config.reset()
        assert len(ctx.values) == 1

    assert ctx.values[config.a] is not_set
Esempio n. 19
0
def test_json_reads_and_writes_strings():
    c = Config({'greeting': 'Hello'})
    assert c.json.dumps() == '{}'
    assert c.json.dumps(with_defaults=True) == '{\n  "greeting": "Hello"\n}'

    c.json.loads('{"something_nonexistent": 1}')
    assert c.dump_values() == {'greeting': 'Hello'}

    c.json.loads('{"something_nonexistent": 1}', as_defaults=True)
    assert c.dump_values() == {'greeting': 'Hello', 'something_nonexistent': 1}

    c.json.loads('{"greeting": "Hello, world!"}')
    assert c.dump_values() == {'greeting': 'Hello, world!', 'something_nonexistent': 1}
Esempio n. 20
0
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'
Esempio n. 21
0
def c4():
    return Config([
        ('greeting', 'Hello!'),
        ('uploads',
         Config([
             ('enabled', True),
             ('db', Config([('host', 'localhost'), ('user', 'root')])),
         ])),
        ('downloads', Config([
            ('enabled', True),
            ('threads', 5),
        ])),
    ])
Esempio n. 22
0
 def load_config(self, airgapped=False):
     print("Loading Config")
     if exists(self.config_file):
         self.config = Config(
             schema=CONFIG_SCHEMA,
             load_sources=[self.config_file],
             auto_load=True,
         )
         self.config.json.load(self.config_file)
     elif airgapped:
         self.get_config(CONFIG_SCHEMA)
     else:
         self.login()
     return self.config
Esempio n. 23
0
def test_not_found_raised_by_iterators_on_first_not_found_name_in_path():
    config = Config({'uploads': {'db': {'user': '******'}}})

    with pytest.raises(NotFound) as exc1:
        list(config.iter_all(recursive=True, path=('downloads', )))
    assert exc1.value.name == 'downloads'

    with pytest.raises(NotFound) as exc2:
        _ = config['uploads', 'enabled']
    assert exc2.value.name == 'enabled'

    with pytest.raises(NotFound) as exc3:
        _ = config['uploads', 'something', 'deep']
    assert exc3.value.name == 'something'
Esempio n. 24
0
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_accepts_configmanager_settings_which_are_passed_to_all_subsections():
    configmanager_settings = {
        'message': 'everyone should know this',
    }
    config1 = Config(configmanager_settings=configmanager_settings)
    assert config1.settings.message == 'everyone should know this'

    config2 = Config({'greeting': 'Hello'}, configmanager_settings=configmanager_settings)
    assert config2.settings.message == 'everyone should know this'

    config3 = Config({'db': {'user': '******'}}, configmanager_settings=configmanager_settings)
    assert config3.settings.message == 'everyone should know this'
    assert config3.db.settings.message == 'everyone should know this'

    assert config3.db.settings is config3.settings
Esempio n. 26
0
def test_hooks_arent_handled_if_hooks_enabled_setting_is_set_to_falsey_value():
    config = Config({'uploads': {'db': {'user': '******'}}})

    calls = []

    @config.hooks.item_value_changed
    def item_value_changed(**kwargs):
        calls.append(1)

    config.uploads.db.user.value = 'admin1'
    assert len(calls) == 1

    config.uploads.db.user.value = 'admin2'
    assert len(calls) == 2

    config.settings.hooks_enabled = False
    config.uploads.db.user.value = 'admin3'
    assert len(calls) == 2

    config.settings.hooks_enabled = None
    config.uploads.db.user.value = 'admin4'
    assert len(calls) == 2

    config.settings.hooks_enabled = True
    config.uploads.db.user.value = 'admin5'
    assert len(calls) == 3
def test_read_as_defaults_treats_all_values_as_schemas(tmpdir):
    path = tmpdir.join('conf.ini').strpath
    with open(path, 'w') as f:
        f.write('[uploads]\nthreads = 5\nenabled = no\n')
        f.write('[messages]\ngreeting = Hello, home!\n')

    m = Config()
    m.configparser.load(path, as_defaults=True)

    assert m.uploads
    assert m.uploads.threads.value == '5'
    assert m.uploads.enabled.value == 'no'
    with pytest.raises(NotFound):
        assert m.uploads.something_else
    assert m.messages.greeting.value == 'Hello, home!'

    # Reading again with as_defaults=True should not change the values, only the defaults
    m.uploads.threads.value = '55'
    m.configparser.load(path, as_defaults=True)
    assert m.uploads.threads.value == '55'
    assert m.uploads.threads.default == '5'

    # But reading with as_defaults=False should change the value
    m.configparser.load(path)
    assert m.uploads.threads.value == '5'
    assert m.uploads.threads.default == '5'
Esempio n. 28
0
def test_adding_new_attributes_to_item():
    # This demonstrates two ways of adding new attributes:
    # 1) by declaring ItemAttribute, 2) by creating them in initialiser

    class CustomItem(Item):
        help = ItemAttribute(name='help', default='No help available!')

        def __init__(self, *args, **kwargs):
            description = kwargs.pop('description', None)
            super(CustomItem, self).__init__(*args, **kwargs)
            self.description = description

    config = Config({
        'a': {
            'b': 1,
            'c': True,
        },
        'd': 'efg',
    },
                    item_factory=CustomItem)

    assert config.a.b.help
    assert config.a.b.description is None

    assert config.d.help
    assert config.d.description is None
Esempio n. 29
0
def test_configparser_integration(tmpdir):
    defaults_ini = tmpdir.join('defaults.ini')
    defaults_ini.write('')
    defaults_ini_path = defaults_ini.strpath

    custom_ini = tmpdir.join('custom.ini')
    custom_ini.write('')
    custom_ini_path = custom_ini.strpath

    # Config sections expose ConfigParser adapter as configparser property:
    config = Config()

    # assuming that defaults.ini exists, this would initialise Config
    # with all values mentioned in defaults.ini set as defaults.
    # Just like with ConfigParser, this won't fail if the file does not exist.
    config.configparser.load(defaults_ini_path, as_defaults=True)

    # if you have already declared defaults, you can load custom
    # configuration without specifying as_defaults=True:
    config.configparser.load(custom_ini_path)

    # when you are done setting config values, you can write them to a file.
    config.configparser.dump(custom_ini_path)

    # Note that default values won't be written unless you explicitly request it
    # by passing with_defaults=True
    config.configparser.dump(custom_ini_path, with_defaults=True)
Esempio n. 30
0
def test_load_sources_setting(config, tmpdir):
    json1 = tmpdir.join('config1.json').strpath
    json2 = tmpdir.join('config2.json').strpath
    json3 = tmpdir.join('config3.json').strpath

    config.uploads.db.settings.load_sources.append(json1)
    config.settings.load_sources.append(json2)

    # None of the files exist, shouldn't fail
    config.load()

    assert config.dump_values(with_defaults=False) == {}

    with open(json1, 'w') as f:
        json.dump({'user': '******', 'password': '******'}, f)

    config.load()

    assert config.dump_values(with_defaults=False) == {
        'uploads': {'db': {'user': '******', 'password': '******'}}
    }

    assert config.uploads.enabled.value is False
    assert config.uploads.db.user.value == 'Administrator'

    with open(json2, 'w') as f:
        json.dump({'uploads': {'db': {'user': '******'}, 'enabled': True}}, f)

    config.load()

    assert config.uploads.enabled.value is True
    assert config.uploads.db.user.value == 'admin'  # should override "Administrator"
    assert config.uploads.db.password.value == 'SECRET'

    with open(json3, 'w') as f:
        json.dump({'main': {'greeting': 'Hey!'}}, f)

    wrapper = Config({
        'main': config
    })
    wrapper.settings.load_sources.append(json3)

    wrapper.load()

    assert wrapper.main.uploads.db.user.value == 'admin'
    assert wrapper.main.uploads.db.password.value == 'SECRET'
    assert wrapper.main.greeting.value == 'Hey!'