"""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 ##