Source code for sqltrack.config

"""
This module contains functions to locate and parse SQLTrack config files.
"""
from __future__ import annotations

from typing import Union

from configparser import ConfigParser
import getpass
import itertools as it
import os
from pathlib import Path

from .util import coalesce


CONFIG_NAME = "sqltrack.conf"
USER = getpass.getuser()
DEFAULT_CONFIG = {
    "engine": "postgres",
    "dbpath": "sqltrack.db",
    "user": USER,
    "dbname": USER,
}
del USER


def _path_from_env(env_var, *parts):
    value = os.getenv(env_var)
    if not value:
        return None
    return Path(value).joinpath(parts)


[docs]def find_config_file(path: Union[Path | str | None] = None, config_name=CONFIG_NAME): """ If either ``path`` argument or ``SQLTRACK_CONFIG_PATH`` environment variable is not ``None``. The ``path`` argument takes precedence if both are defined. Otherwise, if no explicit path is given, these default location are checked, in this order: 1. ``./sqltrack.conf`` 2. ``$XDG_CONFIG_HOME/sqltrack/sqltrack.conf`` 3. ``%APPDATA%/sqltrack/sqltrack.conf`` 4. ``$HOME/.config/sqltrack/sqltrack.conf`` 5. ``$HOME/sqltrack.conf`` The first path that exists is returned, or ``None`` if none can be found. """ path = coalesce(path, os.getenv("SQLTRACK_CONFIG_PATH")) if path is not None: return Path(path) home = Path.home() for path in ( config_name, _path_from_env("XDG_CONFIG_HOME", "sqltrack", config_name), _path_from_env("APPDATA", "sqltrack", config_name), home / ".config" / "sqltrack", config_name, home / CONFIG_NAME, ): if path is not None: path = Path(path) if path.exists(): return path
[docs]def get_env_config() -> dict: """ Load config from environment variables. Variables names need to match ``SQLTRACK_DSN_<PARAM>``, where ``<PARAM>`` is converted to lowercase in the returned dictionary. """ config = {} for k, v in os.environ.items(): if k.startswith("SQLTRACK_DSN_"): _, _, name = k.partition("SQLTRACK_DSN_") config[name.lower()] = v return config
[docs]def load_config( path: Union[Path | str | None] = None, config_name=CONFIG_NAME, **kwargs ) -> dict: """ Locates and parses config files, as well as other sources which can add or override parameters. :py:func:`find_config_file` with the given ``path`` argument is used to determine which config file to load. ``ValueError`` is raised if an explicitly specified config file (by either the ``path`` argument or the ``SQLTRACK_CONFIG_PATH`` environment variable) does not exist. The final config is assembled as follows, starting with the the default config:: DEFAULT_CONFIG = { "engine": "postgres", "dbpath": "sqltrack.db", "user": getpass.getuser(), "dbname": getpass.getuser(), } Parameters are added or overridden in this order: 1. Parsed from config file, if any. 2. From ``SQLTRACK_DSN_<PARAM>`` environment variables. (see :py:func:`get_env_config` for details). 3. ``kwargs`` given to this function. """ # start with the defaults config = dict(DEFAULT_CONFIG) # parse config file parser = ConfigParser() best_path = find_config_file(path, config_name=config_name) if best_path is not None: if not best_path.exists(): raise ValueError( f"Specified config file '{best_path!s}' does not exist." ) else: with open(best_path, encoding='UTF-8') as fp: parser.read_file(it.chain(("[DEFAULT]",), fp)) config.update(dict(parser["DEFAULT"])) # update config with environment overrides config.update(get_env_config()) # update config with kwargs config.update(kwargs) # done return config