def test_must_not_allow_item_or_section_names_with_str_path_separator_in_them(
):
    with pytest.raises(ValueError):
        Config({
            'a.b': True,
        })

    Config({'a.b': True}, str_path_separator='/')

    with pytest.raises(ValueError):
        Config({'a/b': True}, str_path_separator='/')

    # Sections

    with pytest.raises(ValueError):
        Config({'a.b': Section()})

    with pytest.raises(ValueError):
        Config({'a/b': Section()}, str_path_separator='/')

    config = Config({'a/b': Section()}, str_path_separator='.')

    assert config['a/b'].is_section

    config = Config({'a.b': Section()}, str_path_separator='/')

    assert config['a.b'].is_section
Exemple #2
0
def test_dynamic_override_of_envvar_name(monkeypatch):
    config = Section({'uploads': {'threads': 1}})

    assert config.uploads.threads.envvar_name is None

    @config.item_attribute
    def envvar_name(item=None, **kwargs):
        return 'TEST_{}'.format('_'.join(item.get_path()).upper())

    assert config.uploads.threads.envvar_name == 'TEST_UPLOADS_THREADS'

    assert config.uploads.threads.value == 1

    # This has no immediate effect because envvar is still None
    monkeypatch.setenv('TEST_UPLOADS_THREADS', '23')
    assert config.uploads.threads.value == 1

    # This changes everything
    config.uploads.threads.envvar = True
    assert config.uploads.threads.value == 23

    # But, if envvar is set to a name, envvar_name doesn't matter again
    config.uploads.threads.envvar = 'OTHER_UPLOADS_THREADS'
    assert config.uploads.threads.value == 1

    monkeypatch.setenv('OTHER_UPLOADS_THREADS', '42')
    assert config.uploads.threads.value == 42
Exemple #3
0
def test_envvar_attribute_enables_value_override_via_envvars(monkeypatch):
    config = Section({'uploads': {'threads': 1}})

    assert config.uploads.threads.envvar is None
    assert config.uploads.threads.envvar_name is None
    assert config.uploads.threads.value == 1

    config.uploads.threads.envvar = True
    assert config.uploads.threads.value == 1

    monkeypatch.setenv('UPLOADS_THREADS', '23')
    assert config.uploads.threads.value == 23

    config.uploads.threads.envvar_name = 'OTHER_UPLOADS_THREADS'
    assert config.uploads.threads.value == 1

    monkeypatch.setenv('OTHER_UPLOADS_THREADS', '42')
    assert config.uploads.threads.value == 42

    config.uploads.threads.envvar = False
    assert config.uploads.threads.value == 1

    config.uploads.threads.envvar = 'UPLOADS_THREADS'
    assert config.uploads.threads.value == 23

    config.uploads.threads.envvar = 'OTHER_UPLOADS_THREADS'
    assert config.uploads.threads.value == 42

    config.uploads.threads.envvar = 'SOMETHING_NONEXISTENT'
    assert config.uploads.threads.value == 1
Exemple #4
0
class AuthenticationBackend(ABC):
    config_section = 'authentication'
    config_schema = Section(section='authentication')
    config = None

    @abstractmethod
    def authenticate(self, username, password) -> dict or False:
        raise NotImplemented
Exemple #5
0
class StaticAuth(AuthenticationBackend):
    config_section = 'static_auth'
    config_schema = {'users': Section()}

    def authenticate(self, username, password):
        users = {
            u.lower(): p
            for u, p in self.config.static_auth.users.get().items()
        }
        if username.lower() in users and users[username] == password:
            return {'username': username.lower(), 'email': ''}
def test_get_item_and_get_section_for_rich_config():
    config = Config({'uploads': Section({'db': Section({'user': '******'})})})

    assert config.get_section('uploads').is_section
    assert config.get_section('uploads', 'db').is_section
    assert config.uploads.get_section('db').is_section

    assert config.get_item('uploads', 'db', 'user').is_item
    assert config.uploads.db.get_item('user').is_item

    with pytest.raises(NotFound):
        config.get_item('downloads')

    with pytest.raises(NotFound):
        config.get_section('downloads')

    with pytest.raises(NotFound):
        config.get_item('uploads', 'tmp_dir')

    with pytest.raises(NotFound):
        config.get_section('uploads', 'tmp_dir')
def test_nested_section_settings_are_the_settings_of_the_nearest_manager_in_tree(
):
    c = Config({
        'main':
        Config({
            'a1':
            Section({
                'a2': Config({
                    'a3': Section({'a4': Section()}),
                }),
            }),
            'b1':
            Section({
                'b2':
                Section({
                    'b3': Section({
                        'b4': Config({'b5': Section()}),
                    }),
                }),
            }),
        }),
    })

    assert c.settings
    assert c.main.settings
    assert c.settings is not c.main.settings
    assert c.main.a1.settings is c.main.settings
    assert c.main.a1.a2.settings is not c.main.settings
    assert c.main.a1.a2.a3.settings is c.main.a1.a2.settings
    assert c.main.a1.a2.a3.a4.settings is c.main.a1.a2.settings

    assert c.main.b1.settings is c.main.settings
    assert c.main.b1.b2.settings is c.main.settings
    assert c.main.b1.b2.b3.settings is c.main.settings
    assert c.main.b1.b2.b3.b4.settings is not c.main.settings
    assert c.main.b1.b2.b3.b4.b5.settings is c.main.b1.b2.b3.b4.settings
Exemple #8
0
def test_not_found_hook():
    calls = []

    config = Config({'uploads': Section()})

    @config.hooks.not_found
    def first_hook(*args, **kwargs):
        calls.append(('first', args, sub_dict(kwargs, ('section', 'name'))))

    @config.hooks.not_found
    def second_hook(*args, **kwargs):
        calls.append(('second', args, sub_dict(kwargs, ('section', 'name'))))

    assert len(calls) == 0

    with pytest.raises(NotFound):
        _ = config.db

    assert len(calls) == 2
    assert calls[0] == ('first', (), {'section': config, 'name': 'db'})
    assert calls[1] == ('second', (), {'section': config, 'name': 'db'})

    with pytest.raises(NotFound):
        _ = config.uploads.threads

    assert len(calls) == 4
    assert calls[2] == ('first', (), {
        'section': config.uploads,
        'name': 'threads'
    })
    assert calls[3] == ('second', (), {
        'section': config.uploads,
        'name': 'threads'
    })

    # A hook that creates the missing item so further calls won't trigger
    # the hook handlers again, including any subsequent hook handlers as part of current event.
    @config.hooks.not_found
    def third_hook(*args, **kwargs):
        calls.append(('third', args, sub_dict(kwargs, ('section', 'name'))))

        assert kwargs['section']
        assert kwargs['name']

        item = kwargs['section'].create_item(name=kwargs['name'])
        kwargs['section'].add_item(item.name, item)
        return item

    # Fourth hook will never be called because the third hook already resolves the missing name
    @config.hooks.not_found
    def fourth_hook(*args, **kwargs):
        calls.append(('fourth', args, sub_dict(kwargs, ('section', 'name'))))

    assert len(calls) == 4

    assert config.uploads.threads

    assert len(calls) == 7

    assert calls[4] == ('first', (), {
        'section': config.uploads,
        'name': 'threads'
    })
    assert calls[5] == ('second', (), {
        'section': config.uploads,
        'name': 'threads'
    })
    assert calls[6] == ('third', (), {
        'section': config.uploads,
        'name': 'threads'
    })

    assert config.uploads.threads

    assert len(calls) == 7