Select Git revision
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