Added a setup method hook for easier startup time code.

This commit is contained in:
Jannis Leidel 2013-05-15 10:57:30 +02:00
parent 6596e191f0
commit df865840bc
5 changed files with 77 additions and 16 deletions

View file

@ -58,4 +58,6 @@ class Settings(six.with_metaclass(SettingsBase)):
to the name of the class.
"""
pass
@classmethod
def setup(cls):
pass

View file

@ -132,6 +132,22 @@ class SettingsImporter(object):
return None
def reraise(exc, prefix=None, suffix=None):
args = exc.args
if not args:
args = ('',)
if prefix is None:
prefix = ''
elif not prefix.endswith((':', ': ')):
prefix = prefix + ': '
if suffix is None:
suffix = ''
elif not (suffix.startswith('(') and suffix.endswith(')')):
suffix = '(' + suffix + ')'
exc.args = ('%s %s %s' % (prefix, exc.args[0], suffix),) + args[1:]
raise
class SettingsLoader(object):
def __init__(self, name, location):
@ -143,31 +159,38 @@ class SettingsLoader(object):
mod = sys.modules[fullname] # pragma: no cover
else:
mod = imp.load_module(fullname, *self.location)
cls_path = '%s.%s' % (mod.__name__, self.name)
try:
cls = getattr(mod, self.name)
except AttributeError: # pragma: no cover
raise ImproperlyConfigured("Couldn't find settings '%s' in "
"module '%s'" %
(self.name, mod.__package__))
except AttributeError as err: # pragma: no cover
reraise(err,
"While trying to find the '%s' settings in module '%s'" %
(self.name, mod.__package__))
try:
cls.setup()
except Exception as err:
reraise(err, "While calling '%s.setup()'" % cls_path)
try:
obj = cls()
except Exception as err:
raise ImproperlyConfigured("Couldn't load settings '%s.%s': %s" %
(mod.__name__, self.name, err))
reraise(err,
"While loading the '%s' settings" % cls_path)
try:
attributes = uppercase_attributes(obj).items()
except Exception as err:
raise ImproperlyConfigured("Couldn't get items of settings "
"'%s.%s': %s" %
(mod.__name__, self.name, err))
reraise(err,
"While getting the items of the '%s' settings" %
cls_path)
for name, value in attributes:
if callable(value) and not getattr(value, 'pristine', False):
try:
value = value()
except Exception as err:
raise ImproperlyConfigured(
"Couldn't call '%s' in '%s.%s': %s" %
(value, mod.__name__, self.name, err))
reraise(err,
"While calling '%s.%s'" % (cls_path, value))
setattr(mod, name, value)
setattr(mod, 'CONFIGURATION', '%s.%s' % (fullname, self.name))
return mod

View file

@ -30,6 +30,10 @@ class Test(Settings):
TEST_RUNNER = 'discover_runner.DiscoverRunner'
def TEMPLATE_CONTEXT_PROCESSORS(self):
return Settings.TEMPLATE_CONTEXT_PROCESSORS + (
'configurations.tests.settings.base.test_callback',)
ATTRIBUTE_SETTING = True
_PRIVATE_SETTING = 'ryan'
@ -49,6 +53,6 @@ class Test(Settings):
def PRISTINE_FUNCTION_SETTING():
return 5
def TEMPLATE_CONTEXT_PROCESSORS(self):
return Settings.TEMPLATE_CONTEXT_PROCESSORS + (
'configurations.tests.settings.base.test_callback',)
@classmethod
def setup(cls):
cls.SETUP_TEST_SETTING = 6

View file

@ -25,6 +25,7 @@ class MainTests(TestCase):
global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
'configurations.tests.settings.base.test_callback',
))
self.assertEqual(main.SETUP_TEST_SETTING, 6)
def test_global_arrival(self):
from django.conf import settings
@ -34,6 +35,7 @@ class MainTests(TestCase):
self.assertTrue(lambda: callable(settings.PRISTINE_LAMBDA_SETTING))
self.assertNotEqual(settings.PRISTINE_FUNCTION_SETTING, 5)
self.assertTrue(lambda: callable(settings.PRISTINE_FUNCTION_SETTING))
self.assertEqual(settings.SETUP_TEST_SETTING, 6)
@patch.dict(os.environ, clear=True, DJANGO_CONFIGURATION='Test')
def test_empty_module_var(self):

View file

@ -155,6 +155,36 @@ Lambdas work, too::
class Prod(Settings):
ACCESS_FUNCTION = pristine(lamda user: user.is_staff)
Setup methods
^^^^^^^^^^^^^
.. versionadded:: 0.3
If there is something required to be set up after all the settings have been
loaded please override the ``setup`` class method like so (don't forget
to apply the Python ``@classmethod`` decorator::
from configurations import Settings
class Prod(Settings):
# ...
@classmethod
def setup(cls):
if something.completely.different():
cls.DEBUG = True
Or do something unrelated to your settings, like connecting to a database::
from configurations import Settings
class Prod(Settings):
# ...
@classmethod
def setup(cls):
import mango
mango.connect('enterprise')
Alternatives
------------