aboutsummaryrefslogtreecommitdiffstats
path: root/tagit/config/loader.py
blob: 47a51fab7f27d025610ced3049bb2875ed7948a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
"""High-level config loading.

Part of the tagit module.
A copy of the license is provided with the project.
Author: Matthias Baumgartner, 2022
"""
# standard imports
import logging
import os
import shutil
import typing

# inner-module imports
from .settings import Settings

# constants

TAGITRC = '.tagitrc'

DEFAULT_USER_CONFIG = os.path.join(os.path.dirname(__file__), 'user-defaults.yaml')

SETTINGS_PATH = [
    # user home
    os.path.expanduser(os.path.join('~', TAGITRC)),
    # installation directory
    '/usr/share/tagit/settings',
    '/usr/share/tagit/keybindings',
    # module defaults
    os.path.join(os.path.dirname(__file__), 'settings.yaml'),
    ]

# exports
__all__: typing.Sequence[str] = (
    'load_settings',
    )


## code ##

logger = logging.getLogger(__name__)

def load_settings(path=None, verbose=0):
    """Load application settings.
    The settings are loaded from the specified *path* and from all default
    search paths (see *SETTINGS_PATH*). More specific locations overwrite
    less specific ones. Every config key comes with a default value that
    applies if it is not specified in the config files.
    """
    verbose = max(0, verbose)

    # build searchpaths
    searchpaths = []
    searchpaths += [path] if path is not None else []
    searchpaths += SETTINGS_PATH

    # create default user config on first start
    user_config = os.path.expanduser(os.path.join('~', TAGITRC))
    if os.path.exists(DEFAULT_USER_CONFIG) and not os.path.exists(user_config):
        shutil.copy(DEFAULT_USER_CONFIG, user_config)

    # scan searchpaths
    cfg = Settings()
    for path in searchpaths[::-1]:
        if verbose > 0 or cfg('session', 'verbose') > 0:
            print(f'Loading settings from {path}')

        if path is not None and os.path.exists(path):
            try:
                cfg.update(Settings.Open(path, clear_defaults=False))

            except TypeError as e: # schema violation
                logger.critical(f'Encountered a config error while loading {path}: {e}')
                raise e

    # update verbosity from argument
    cfg.set(('session', 'verbose'), max(cfg('session', 'verbose'), verbose))
    return cfg

## EOF ##