Refactor: split code into several django apps (we call them modules).
This commit is contained in:
2
dav_base/config/__init__.py
Normal file
2
dav_base/config/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import apps
|
||||
from . import modules
|
||||
71
dav_base/config/apps.py
Normal file
71
dav_base/config/apps.py
Normal 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
132
dav_base/config/modules.py
Normal 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)
|
||||
Reference in New Issue
Block a user