Renamed Settings class to Configuration to better match what it means. Settings is still importable and is marked to be deprecated in 1.0.

This commit is contained in:
Jannis Leidel 2013-07-27 12:05:39 +02:00
parent aac7af881c
commit e31adbaeed
10 changed files with 79 additions and 66 deletions

View file

@ -19,7 +19,7 @@ Install django-configurations:
pip install django-configurations
Then subclass the included ``configurations.Settings`` class in your
Then subclass the included ``configurations.Configuration`` class in your
project's **settings.py** or any other module you're using to store the
settings constants, e.g.:
@ -27,9 +27,9 @@ settings constants, e.g.:
# mysite/settings.py
from configurations import Settings
from configurations import Configuration
class Dev(Settings):
class Dev(Configuration):
DEBUG = True
Set the ``DJANGO_CONFIGURATION`` environment variable to the name of the class

View file

@ -1,6 +1,6 @@
# flake8: noqa
from .base import Settings
from .base import Settings, Configuration
from .decorators import pristinemethod
__version__ = '0.3'
__all__ = ['Settings', 'pristinemethod']
__all__ = ['Configuration', 'pristinemethod']

View file

@ -1,10 +1,12 @@
import six
import warnings
from django.utils import six
from django.conf import global_settings
from django.core.exceptions import ImproperlyConfigured
from .utils import uppercase_attributes
__all__ = ['Settings']
__all__ = ['Configuration']
install_failure = ("django-configurations settings importer wasn't "
@ -13,7 +15,7 @@ install_failure = ("django-configurations settings importer wasn't "
"http://django-configurations.readthedocs.org/")
class SettingsBase(type):
class ConfigurationBase(type):
def __new__(cls, name, bases, attrs):
if bases != (object,) and bases[0].__name__ != 'NewBase':
@ -23,24 +25,26 @@ class SettingsBase(type):
if not importer.installed:
raise ImproperlyConfigured(install_failure)
settings_vars = uppercase_attributes(global_settings)
parents = [base for base in bases if isinstance(base, SettingsBase)]
parents = [base for base in bases if isinstance(base,
ConfigurationBase)]
if parents:
for base in bases[::-1]:
settings_vars.update(uppercase_attributes(base))
attrs = dict(settings_vars, **attrs)
return super(SettingsBase, cls).__new__(cls, name, bases, attrs)
return super(ConfigurationBase, cls).__new__(cls, name, bases, attrs)
def __repr__(self):
return "<Settings '%s.%s'>" % (self.__module__, self.__name__)
return "<Configuration '{0}.{1}'>".format(self.__module__,
self.__name__)
class Settings(six.with_metaclass(SettingsBase)):
class Configuration(six.with_metaclass(ConfigurationBase)):
"""
The base configuration class to inherit from.
::
class Develop(Settings):
class Develop(Configuration):
EXTRA_AWESOME = True
@property
@ -65,3 +69,12 @@ class Settings(six.with_metaclass(SettingsBase)):
@classmethod
def post_setup(cls):
pass
class Settings(Configuration):
@classmethod
def pre_setup(cls):
warnings.warn("configurations.Settings was renamed to "
"settings.Configuration and will be "
"removed in 1.0", PendingDeprecationWarning)

View file

@ -4,9 +4,9 @@ def pristinemethod(func):
Use it like this::
from configurations import pristinemethod
from configurations import Configuration, pristinemethod
class Develop(Settings):
class Develop(Configuration):
@pristinemethod
def USER_CHECK(user):

View file

@ -30,8 +30,8 @@ class StdoutWrapper(object):
def write(self, msg, *args, **kwargs):
if 'Django version' in msg:
new_msg_part = (", configuration %r" %
os.environ.get(CONFIGURATION_ENVIRONMENT_VARIABLE))
new_msg_part = (", configuration {!r}".format(
os.environ.get(CONFIGURATION_ENVIRONMENT_VARIABLE)))
msg_parts = msg.split('\n')
modified_msg_parts = []
for msg_part in msg_parts:
@ -53,7 +53,7 @@ def patch_inner_run(original):
configuration_options = (
make_option('--configuration',
help='The name of the settings class to load, e.g. '
help='The name of the configuration class to load, e.g. '
'"Development". If this isn\'t provided, the '
'DJANGO_CONFIGURATION environment variable will '
'be used.'),)
@ -69,16 +69,16 @@ def install():
# add the configuration option to all management commands
base.BaseCommand.option_list += configuration_options
sys.meta_path.insert(0, SettingsImporter())
sys.meta_path.insert(0, ConfigurationImporter())
installed = True
# now patch the active runserver command to show a nicer output
commands = management.get_commands()
runserver_path = commands.get('runserver', None)
if runserver_path is not None:
full_path = '%s.management.commands.runserver' % runserver_path
runserver = commands.get('runserver', None)
if runserver is not None:
path = '{0}.management.commands.runserver'.format(runserver)
try:
runserver_module = import_module(full_path)
runserver_module = import_module(path)
except ImportError:
pass
else:
@ -91,9 +91,9 @@ def handle_configurations_option(options):
os.environ[CONFIGURATION_ENVIRONMENT_VARIABLE] = options.configuration
class SettingsImporter(object):
error_msg = ("Settings cannot be imported, "
"environment variable %s is undefined.")
class ConfigurationImporter(object):
error_msg = ("Configuration cannot be imported, "
"environment variable {0} is undefined.")
def __init__(self):
self.argv = sys.argv[:]
@ -107,7 +107,8 @@ class SettingsImporter(object):
self.validate()
def __repr__(self):
return "<SettingsImporter for '%s.%s'>" % (self.module, self.name)
return "<ConfigurationImporter for '{0}.{1}'>".format(self.module,
self.name)
@property
def module(self):
@ -119,16 +120,16 @@ class SettingsImporter(object):
def validate(self):
if self.name is None:
raise ImproperlyConfigured(self.error_msg %
CONFIGURATION_ENVIRONMENT_VARIABLE)
raise ImproperlyConfigured(self.error_msg.format(
CONFIGURATION_ENVIRONMENT_VARIABLE))
if self.module is None:
raise ImproperlyConfigured(self.error_msg %
SETTINGS_ENVIRONMENT_VARIABLE)
raise ImproperlyConfigured(self.error_msg.format(
SETTINGS_ENVIRONMENT_VARIABLE))
def find_module(self, fullname, path=None):
if fullname is not None and fullname == self.module:
module = fullname.rsplit('.', 1)[-1]
return SettingsLoader(self.name, imp.find_module(module, path))
return ConfigurationLoader(self.name, imp.find_module(module, path))
return None
@ -148,7 +149,7 @@ def reraise(exc, prefix=None, suffix=None):
raise
class SettingsLoader(object):
class ConfigurationLoader(object):
def __init__(self, name, location):
self.name = name
@ -159,46 +160,45 @@ 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)
cls_path = '{0}.{1}'.format(mod.__name__, self.name)
try:
cls = getattr(mod, self.name)
except AttributeError as err: # pragma: no cover
reraise(err,
"While trying to find the '%s' settings in module '%s'" %
(self.name, mod.__package__))
reraise(err, "While trying to find the '{0}' "
"settings in module '{1}'".format(self.name,
mod.__package__))
try:
cls.pre_setup()
except Exception as err:
reraise(err, "While calling '%s.pre_setup()'" % cls_path)
reraise(err, "While calling '{0}.pre_setup()'".format(cls_path))
try:
obj = cls()
except Exception as err:
reraise(err,
"While loading the '%s' settings" % cls_path)
reraise(err, "While initializing the '{0}' "
"configuration".format(cls_path))
try:
attributes = uppercase_attributes(obj).items()
except Exception as err:
reraise(err,
"While getting the items of the '%s' settings" %
cls_path)
reraise(err, "While getting the items "
"of the '{0}' configuration".format(cls_path))
for name, value in attributes:
if callable(value) and not getattr(value, 'pristine', False):
try:
value = value()
except Exception as err:
reraise(err,
"While calling '%s.%s'" % (cls_path, value))
reraise(err, "While calling '{0}.{1}'".format(cls_path,
value))
setattr(mod, name, value)
setattr(mod, 'CONFIGURATION', '%s.%s' % (fullname, self.name))
setattr(mod, 'CONFIGURATION', '{0}.{1}'.format(fullname, self.name))
try:
cls.post_setup()
except Exception as err:
reraise(err, "While calling '%s.post_setup()'" % cls_path)
reraise(err, "While calling '{0}.post_setup()'".format(cls_path))
return mod

View file

@ -1,9 +1,9 @@
from configurations import Settings
from configurations import Configuration
def test_callback(request):
return {}
class Base(Settings):
class Base(Configuration):
pass

View file

@ -1,9 +1,9 @@
import os
import uuid
from configurations import Settings, pristinemethod
from configurations import Configuration, pristinemethod
class Test(Settings):
class Test(Configuration):
DEBUG = True
SITE_ID = 1
@ -31,7 +31,7 @@ class Test(Settings):
TEST_RUNNER = 'discover_runner.DiscoverRunner'
def TEMPLATE_CONTEXT_PROCESSORS(self):
return Settings.TEMPLATE_CONTEXT_PROCESSORS + (
return Configuration.TEMPLATE_CONTEXT_PROCESSORS + (
'configurations.tests.settings.base.test_callback',)
ATTRIBUTE_SETTING = True

View file

@ -1,4 +1,4 @@
from configurations import Settings
from configurations import Configuration
class Mixin1(object):
@ -17,7 +17,7 @@ class Mixin2(object):
'some_app.context_processors.processor2',)
class Inheritance(Mixin2, Mixin1, Settings):
class Inheritance(Mixin2, Mixin1, Configuration):
@property
def TEMPLATE_CONTEXT_PROCESSORS(self):

View file

@ -6,7 +6,7 @@ from django.core.exceptions import ImproperlyConfigured
from mock import patch
from configurations.importer import SettingsImporter
from configurations.importer import ConfigurationImporter
class MainTests(TestCase):
@ -41,39 +41,39 @@ class MainTests(TestCase):
@patch.dict(os.environ, clear=True, DJANGO_CONFIGURATION='Test')
def test_empty_module_var(self):
self.assertRaises(ImproperlyConfigured, SettingsImporter)
self.assertRaises(ImproperlyConfigured, ConfigurationImporter)
@patch.dict(os.environ, clear=True,
DJANGO_SETTINGS_MODULE='configurations.tests.settings.main')
def test_empty_class_var(self):
self.assertRaises(ImproperlyConfigured, SettingsImporter)
self.assertRaises(ImproperlyConfigured, ConfigurationImporter)
def test_global_settings(self):
from configurations.base import Settings
self.assertEqual(Settings.LOGGING_CONFIG, 'django.utils.log.dictConfig')
self.assertEqual(repr(Settings),
"<Settings 'configurations.base.Settings'>")
from configurations.base import Configuration
self.assertEqual(Configuration.LOGGING_CONFIG, 'django.utils.log.dictConfig')
self.assertEqual(repr(Configuration),
"<Configuration 'configurations.base.Configuration'>")
def test_repr(self):
from configurations.tests.settings.main import Test
self.assertEqual(repr(Test),
"<Settings 'configurations.tests.settings.main.Test'>")
"<Configuration 'configurations.tests.settings.main.Test'>")
@patch.dict(os.environ, clear=True,
DJANGO_SETTINGS_MODULE='configurations.tests.settings.main',
DJANGO_CONFIGURATION='Test')
def test_initialization(self):
importer = SettingsImporter()
importer = ConfigurationImporter()
self.assertEqual(importer.module, 'configurations.tests.settings.main')
self.assertEqual(importer.name, 'Test')
self.assertEqual(repr(importer),
"<SettingsImporter for 'configurations.tests.settings.main.Test'>")
"<ConfigurationImporter for 'configurations.tests.settings.main.Test'>")
@patch.dict(os.environ, clear=True,
DJANGO_SETTINGS_MODULE='configurations.tests.settings.inheritance',
DJANGO_CONFIGURATION='Inheritance')
def test_initialization_inheritance(self):
importer = SettingsImporter()
importer = ConfigurationImporter()
self.assertEqual(importer.module,
'configurations.tests.settings.inheritance')
self.assertEqual(importer.name, 'Inheritance')

View file

@ -20,7 +20,7 @@ use of the ``from foo import *`` anti-pattern.
Okay, how does it work?
-----------------------
Any subclass of the ``configurations.Settings`` class will automatically
Any subclass of the ``configurations.Configuration`` class will automatically
use the values of its class and instance attributes (including properties
and methods) to set module level variables of the same module -- that's
how Django will interface to the django-configurations based settings during