"""This module contains functions to locate and parse SQLTrack config files."""from__future__importannotationsfromtypingimportUnionfromconfigparserimportConfigParserimportgetpassimportitertoolsasitimportosfrompathlibimportPathfrom.utilimportcoalesceCONFIG_NAME="sqltrack.conf"USER=getpass.getuser()DEFAULT_CONFIG={"engine":"postgres","dbpath":"sqltrack.db","user":USER,"dbname":USER,}delUSERdef_path_from_env(env_var,*parts):value=os.getenv(env_var)ifnotvalue:returnNonereturnPath(value).joinpath(parts)
[docs]deffind_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"))ifpathisnotNone:returnPath(path)home=Path.home()forpathin(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,):ifpathisnotNone:path=Path(path)ifpath.exists():returnpath
[docs]defget_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={}fork,vinos.environ.items():ifk.startswith("SQLTRACK_DSN_"):_,_,name=k.partition("SQLTRACK_DSN_")config[name.lower()]=vreturnconfig
[docs]defload_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 defaultsconfig=dict(DEFAULT_CONFIG)# parse config fileparser=ConfigParser()best_path=find_config_file(path,config_name=config_name)ifbest_pathisnotNone:ifnotbest_path.exists():raiseValueError(f"Specified config file '{best_path!s}' does not exist.")else:withopen(best_path,encoding='UTF-8')asfp:parser.read_file(it.chain(("[DEFAULT]",),fp))config.update(dict(parser["DEFAULT"]))# update config with environment overridesconfig.update(get_env_config())# update config with kwargsconfig.update(kwargs)# donereturnconfig