Skip to content
Snippets Groups Projects
Select Git revision
  • 2cc34496ecb7b8e72def39410dca9a4fadd88ff3
  • master default protected
  • config
3 results

config.py

Blame
  • config.py 4.81 KiB
    #!/usr/bin/env python 
    #-*- coding: utf-8 -*-
    
    import os
    import toml
    from pathlib import Path
    
    
    def this_or_else(this: str, other: str) -> str:
        """
        Return this if this is a non-empty string
        otherwise return other
        """
        if this is None or this.strip() == "":
            return other
        else:
            return this
    
    
    def get_home() -> str:
        """
        Get the home directory from the environment variable
        """
        return os.environ.get("HOME")
    
    
    def get_dirs(application_name):
        """
        Get the XDG dirs for data and config
        """
        dirs = {}
    
        # Get home directory
        home = get_home()
    
        # Set defaults for xdg directories
        default_data_home = "{}/.local/share/{}".format(home, application_name)
        default_config_home = "{}/.config/{}".format(home, application_name)
    
        # Set dict value to environment variable or (if none set) to default value
        dirs["data"]   = this_or_else(os.environ.get("XDG_DATA_HOME"), default_data_home)
        dirs["config"] = this_or_else(os.environ.get("XDG_CONFIG_HOME"), default_config_home)
    
        # Override this directory from Environment variable
        key = "{}_DATA_DIR".format(application_name.upper())
        if os.getenv(key) is not None:
            dirs["data"] = os.getenv(key)
    
        # Override this directory from Environment variable
        key = "{}_CONFIG_DIR".format(application_name.upper())
        if os.getenv(key) is not None:
            dirs["config"] = os.getenv(key)
    
        return dirs
    
    
    def initialize_config(application_name: str, default_config: str, app) -> dict:
        """
        Initialize a configuration. If none exists, create a default one
        """
        # Get XDG dirs
        dirs = get_dirs(application_name)
    
        # Convert the default config to a dict
        default_strconfig = default_config
        default_config = toml.loads(default_config)
    
        # Generate a environment variable name from the application name
        # E.g. "foo bar" becomes "FOO_BAR_CONFIG_PATH"
        config_path_environment_variable = "{}_CONFIG_PATH".format(application_name.upper().replace(" ", "_").replace("-", "_"))
    
        # If the environment variable is set, use that as a config path, otherwise use the default one
        config_dir = this_or_else(os.environ.get(config_path_environment_variable), dirs["config"])
        config_path = "{}/config.toml".format(config_dir.rstrip("/"))
    
        # Create the config_dir if it doesn't exist
        if not Path.is_dir(Path(config_dir)):
            Path(config_dir).mkdir(parents=True, exist_ok=True)
            app.logger.info("Config directory didn't exist, created directory: {}".format(config_dir))
    
        # Create a default config if it does exist
        if not Path.is_file(Path(config_path)):
            write_config(config_path, default_config)
            app.logger.info("Created new default config.toml at:\n{}".format(config_path))
            config = default_config
        else:
            config = read_config(config_path)
            if config_has_missing_keys(config, default_config, default_strconfig, app):
                app.logger.error("Error: there are keys missing in the config. Delete to let {} create a new one, or add the missing keys manually".format(application_name))
                exit(1)
            app.logger.info("Read config from: {}".format(config_path))
    
            # Log info about environment variable if not set
            if os.environ.get(config_path_environment_variable) is None:
                app.logger.info("Override config path by setting the Environment variable {}=".format(config_path_environment_variable))
    
        return config
    
    def config_has_missing_keys(config, default_config, default_strconfig, app) -> bool:
        """
        Returns True if any of the keys from the default config are missing
        Prints those missing keys and the default config, if this is the case 
        """
        missing = []
        for default_key in default_config.keys():
            if not default_key in config.keys():
                app.logger.error("Your config.toml is missing the [{}] section!".format(default_key))
                missing.append(True)
            else:
                for sub_key in default_config[default_key].keys():
                    if not sub_key in config[default_key].keys():
                        app.logger.error("Your config.toml is missing the key \"{}\" in the [{}] section!".format(sub_key, default_key))
                        missing.append(True)
    
        if any(missing):
            app.logger.error("The default config looks like this:")
            app.logger.error(default_strconfig)
            return True
        else:
            return False
    
    
    
    def write_config(config_path: str, config: dict):
        """
        Write a dict as toml to a given path
        """
        with open(config_path, "w", encoding="utf-8") as f:
            toml.dump(config, f)
    
    
    def read_config(config_path: str) -> dict:
        """
        Read a config.toml from the given path,
        return a dict containing the config
        """
        with open(config_path, "r", encoding="utf-8") as f:
            config = toml.load(f)
        return config