2018-10-10 22:43:50 +00:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import os.path
|
2018-10-27 00:33:45 +00:00
|
|
|
from collections import ChainMap
|
|
|
|
from configparser import ConfigParser
|
2018-10-10 22:43:50 +00:00
|
|
|
from shutil import copyfile
|
2018-10-27 00:33:45 +00:00
|
|
|
from typing import Optional, Any
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-13 20:01:45 +00:00
|
|
|
from django.conf import settings as dj_settings
|
2018-10-10 22:43:50 +00:00
|
|
|
from django.contrib.auth.models import User
|
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
from .models import UserSettings, Subscription
|
|
|
|
from .utils.extended_interpolation_with_env import ExtendedInterpolatorWithEnv
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
_CONFIG_DIR = os.path.join(dj_settings.BASE_DIR, 'config')
|
|
|
|
_LOG_FILE = 'log.log'
|
|
|
|
_LOG_PATH = os.path.join(_CONFIG_DIR, _LOG_FILE)
|
|
|
|
_LOG_FORMAT = '%(asctime)s|%(process)d|%(thread)d|%(name)s|%(filename)s|%(lineno)d|%(levelname)s|%(message)s'
|
2018-10-10 22:43:50 +00:00
|
|
|
|
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
class AppSettings(ConfigParser):
|
|
|
|
_DEFAULT_INTERPOLATION = ExtendedInterpolatorWithEnv()
|
|
|
|
__DEFAULTS_FILE = 'defaults.ini'
|
|
|
|
__SETTINGS_FILE = 'config.ini'
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(allow_no_value=True, *args, **kwargs)
|
|
|
|
self.__defaults_path = os.path.join(_CONFIG_DIR, AppSettings.__DEFAULTS_FILE)
|
|
|
|
self.__settings_path = os.path.join(_CONFIG_DIR, AppSettings.__SETTINGS_FILE)
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def initialize(self):
|
|
|
|
self.read([self.__defaults_path, self.__settings_path])
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def save(self):
|
|
|
|
if os.path.exists(self.__settings_path):
|
|
|
|
# Create a backup
|
|
|
|
copyfile(self.__settings_path, self.__settings_path + ".backup")
|
|
|
|
else:
|
|
|
|
# Ensure directory exists
|
|
|
|
settings_dir = os.path.dirname(self.__settings_path)
|
|
|
|
os.makedirs(settings_dir, exist_ok=True)
|
|
|
|
|
|
|
|
with open(self.__settings_path, 'w') as f:
|
|
|
|
self.write(f)
|
|
|
|
|
|
|
|
def __get_combined_dict(self, vars: Optional[Any], sub: Optional[Subscription], user: Optional[User]) -> ChainMap:
|
|
|
|
vars_dict = {}
|
|
|
|
sub_overloads_dict = {}
|
|
|
|
user_settings_dict = {}
|
|
|
|
|
|
|
|
if vars is not None:
|
|
|
|
vars_dict = vars
|
|
|
|
|
|
|
|
if sub is not None:
|
|
|
|
sub_overloads_dict = sub.get_overloads_dict()
|
|
|
|
|
|
|
|
if user is not None:
|
|
|
|
user_settings = UserSettings.find_by_user(user)
|
|
|
|
if user_settings is not None:
|
|
|
|
user_settings_dict = user_settings.to_dict()
|
|
|
|
|
|
|
|
return ChainMap(vars_dict, sub_overloads_dict, user_settings_dict)
|
|
|
|
|
|
|
|
def get_user(self, user: User, section: str, option: Any, vars=None, fallback=object()) -> str:
|
|
|
|
return super().get(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, None, user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def getboolean_user(self, user: User, section: str, option: Any, vars=None, fallback=object()) -> bool:
|
|
|
|
return super().getboolean(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, None, user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def getint_user(self, user: User, section: str, option: Any, vars=None, fallback=object()) -> int:
|
|
|
|
return super().getint(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, None, user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def getfloat_user(self, user: User, section: str, option: Any, vars=None, fallback=object()) -> float:
|
|
|
|
return super().getfloat(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, None, user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def get_sub(self, sub: Subscription, section: str, option: Any, vars=None, fallback=object()) -> str:
|
|
|
|
return super().get(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, sub, sub.user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def getboolean_sub(self, sub: Subscription, section: str, option: Any, vars=None, fallback=object()) -> bool:
|
|
|
|
return super().getboolean(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, sub, sub.user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def getint_sub(self, sub: Subscription, section: str, option: Any, vars=None, fallback=object()) -> int:
|
|
|
|
return super().getint(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, sub, sub.user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
def getfloat_sub(self, sub: Subscription, section: str, option: Any, vars=None, fallback=object()) -> float:
|
|
|
|
return super().getfloat(section, option,
|
|
|
|
fallback=fallback,
|
|
|
|
vars=self.__get_combined_dict(vars, sub, sub.user))
|
2018-10-10 22:43:50 +00:00
|
|
|
|
2018-10-27 00:33:45 +00:00
|
|
|
|
|
|
|
settings = AppSettings()
|
|
|
|
|
|
|
|
|
|
|
|
def initialize_app_config():
|
|
|
|
settings.initialize()
|
|
|
|
__initialize_logger()
|
|
|
|
logging.info('Application started!')
|
|
|
|
|
|
|
|
|
|
|
|
def __initialize_logger():
|
|
|
|
log_level_str = settings.get('global', 'LogLevel', fallback='INFO')
|
|
|
|
|
|
|
|
try:
|
|
|
|
log_level = getattr(logging, log_level_str)
|
|
|
|
logging.basicConfig(filename=_LOG_PATH, level=log_level, format=_LOG_FORMAT)
|
|
|
|
|
|
|
|
except AttributeError:
|
|
|
|
logging.basicConfig(filename=_LOG_PATH, level=logging.INFO, format=_LOG_FORMAT)
|
|
|
|
logging.warning('Invalid log level "%s" in config file.', log_level_str)
|