Refactor: split code into several django apps (we call them modules).

This commit is contained in:
2018-12-13 14:47:58 +01:00
parent c23dc33d4e
commit 0d5a8c65e3
81 changed files with 739 additions and 332 deletions

View File

@@ -0,0 +1,2 @@
from . import apps
from . import modules

71
dav_base/config/apps.py Normal file
View File

@@ -0,0 +1,71 @@
import importlib
import logging
import re
from django.apps import AppConfig as _AppConfig
from django.core.exceptions import ImproperlyConfigured
logger = logging.getLogger(__name__)
class DefaultSetting(object):
def __init__(self, name, value, key_name=None, validator=None):
self.name = name
self.value = value
if key_name is None:
self.key_name = self.name.upper()
else:
self.key_name = key_name
self.validator = validator
def validate(self, value):
if hasattr(self, 'validator') and self.validator is not None:
if callable(self.validator):
if not self.validator(value):
raise ImproperlyConfigured("Validator callback {clb} returned False".format(clb=self.validator))
else:
if not re.search(self.validator, value):
raise ImproperlyConfigured("Does not match /{re}/".format(re=self.validator))
class AppSettings(object):
def __init__(self, app_name, defaults):
settings_name = 'main.settings-' + app_name
try:
settings_module = importlib.import_module(settings_name)
except ImportError:
settings_module = None
for default in defaults:
if hasattr(settings_module, default.key_name):
value = getattr(settings_module, default.key_name)
try:
default.validate(value)
except ImproperlyConfigured as e:
msg = 'Invalid value of {key} in {module}: {cause}'.format(key=default.key_name,
module=settings_name,
cause=e.message)
raise ImproperlyConfigured(msg)
setattr(self, default.name, value)
elif isinstance(default.value, ImproperlyConfigured):
raise default.value
else:
try:
is_impconf = issubclass(default.value, ImproperlyConfigured)
except TypeError:
is_impconf = False
if is_impconf:
msg = '{key} must be defined in {module}'.format(key=default.key_name,
module=settings_name)
raise default.value(msg)
else:
setattr(self, default.name, default.value)
class AppConfig(_AppConfig):
default_settings = ()
def __init__(self, app_name, app_module):
super(AppConfig, self).__init__(app_name, app_module)
self.settings = AppSettings(app_name, self.default_settings)

132
dav_base/config/modules.py Normal file
View File

@@ -0,0 +1,132 @@
import json
import os
import pkg_resources
from django.conf import settings
from django.conf.urls import url as django_conf_url, include
DJANGO_MAIN_MODULE = 'main'
MODULE_CONFIG_FILE_NAME = 'module_config.json'
class ModuleConfigError(Exception):
pass
class ModuleMeta(object):
_json_file = 'module.json'
_root_url_name = 'root'
def __init__(self, package_name):
self._package_name = package_name
self._additional_apps = []
self._url_prefix = None
self._load_from_package()
def __str__(self):
t = '- {}'.format(self._package_name)
return t
@property
def app(self):
return self._package_name
@property
def additional_apps(self):
return self._additional_apps
@property
def url_conf_pattern(self):
url_pattern = '^'
if self._url_prefix is None:
url_pattern += self._package_name
else:
url_pattern += self._url_prefix
url_pattern += '/'
url_conf = self._package_name + '.urls'
return django_conf_url(url_pattern, include(url_conf, self.url_namespace))
@property
def url_namespace(self):
return self._package_name.replace('.', '_')
def _load_from_package(self):
package_name = self._package_name
json_text = pkg_resources.resource_string(package_name, self._json_file)
meta_dict = json.loads(json_text)
meta_dict['package'] = package_name
self.load_from_dict(meta_dict)
def load_from_dict(self, meta_dict):
self._package_name = meta_dict.get('package', None)
self._additional_apps = meta_dict.get('additional_apps', [])
self._url_prefix = meta_dict.get('url_prefix', None)
def dump_as_dict(self):
d = {
'package': self._package_name,
}
if self._additional_apps:
d['additional_apps'] = self._additional_apps
if self._url_prefix:
d['url_prefix'] = self._url_prefix
return d
class ModuleConfig(object):
_lazy_load = True
def __init__(self, config_file_path=None, django_base_dir=None):
if config_file_path is None:
if django_base_dir is None:
django_base_dir = settings.BASE_DIR
config_file_path = os.path.join(django_base_dir, DJANGO_MAIN_MODULE, MODULE_CONFIG_FILE_NAME)
self._config_file_path = config_file_path
self._modules = dict()
self._loaded = False
if not self._lazy_load:
self._load()
def _lazy_init(self):
if not self._loaded:
self._load()
def _load(self):
path = self._config_file_path
self._modules = dict()
with open(path, 'r') as f:
data = json.load(f)
if 'modules' in data:
for meta_dict in data['modules']:
module_name = meta_dict['package']
self._modules[module_name] = ModuleMeta(module_name)
self._modules[module_name].load_from_dict(meta_dict)
self._loaded = True
@property
def modules(self):
self._lazy_init()
return self._modules
def save(self):
path = self._config_file_path
if os.path.exists(path):
self._lazy_init()
else:
self._loaded = True
data = {
'modules': [],
}
for meta_obj in self._modules.values():
data['modules'].append(meta_obj.dump_as_dict())
with open(path, 'w') as f:
json.dump(data, f, indent=4)