django-configglue-0.7.1/ 0000755 0001750 0001750 00000000000 12236762416 016202 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/LICENSE.txt 0000664 0001750 0001750 00000017701 12136764467 020044 0 ustar ricardo ricardo 0000000 0000000 django-configglue is Copyright 2010 Canonical Ltd.
Canonical Ltd ("Canonical") distributes the source code for the
django-configglue under the GNU Lesser General Public License,
version 3 ("LGPLv3"). The full text of this licence can be found
in /usr/share/common-licenses/LGPL-3.
Third-party copyright in this distribution is noted where applicable.
All rights not expressly granted are reserved.
=========================================================================
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
django-configglue-0.7.1/third-party/ 0000755 0001750 0001750 00000000000 12236762416 020451 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/third-party/django/ 0000755 0001750 0001750 00000000000 12236762416 021713 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/third-party/django/LICENSE 0000664 0001750 0001750 00000003026 12136764467 022732 0 ustar ricardo ricardo 0000000 0000000 Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
django-configglue-0.7.1/django_configglue/ 0000755 0001750 0001750 00000000000 12236762416 021646 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/django_configglue/management/ 0000755 0001750 0001750 00000000000 12236762416 023762 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/django_configglue/management/__init__.py 0000664 0001750 0001750 00000006264 12145240342 026071 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd.
# Copyright Django Software Foundation and individual contributors
# This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE)
# except where third-party/django/LICENSE applies.
from optparse import BadOptionError
import django
from django.core import management
from django.conf import settings
from configglue.glue import schemaconfigglue
from django_configglue import utils
class LaxOptionParser(management.LaxOptionParser):
# Subclasses django's to avoid a bug
def _process_long_opt(self, rargs, values):
arg = rargs.pop(0)
# Value explicitly attached to arg? Pretend it's the next
# argument.
if "=" in arg:
(opt, next_arg) = arg.split("=", 1)
rargs.insert(0, next_arg)
had_explicit_value = True
else:
opt = arg
had_explicit_value = False
try:
opt = self._match_long_opt(opt)
except BadOptionError:
# Here's the addition in our subclass, we take care to take
# the value back out of rargs so that it isn't duplicated if
# this code path is hit.
if had_explicit_value:
rargs.pop(0)
raise
option = self._long_opt[opt]
if option.takes_value():
nargs = option.nargs
if len(rargs) < nargs:
if nargs == 1:
self.error(_("%s option requires an argument") % opt)
else:
self.error(_("%s option requires %d arguments")
% (opt, nargs))
elif nargs == 1:
value = rargs.pop(0)
else:
value = tuple(rargs[0:nargs])
del rargs[0:nargs]
elif had_explicit_value:
self.error(_("%s option does not take a value") % opt)
else:
value = None
option.process(opt, value, values, self)
class GlueManagementUtility(management.ManagementUtility):
def execute(self):
"""Override the base class to handle the schema-related options. """
configglue_parser = getattr(settings, '__CONFIGGLUE_PARSER__', None)
if configglue_parser is not None:
# We need a lax option parser that:
# - allows the '%prog subcommand [options] [args]' format
# - will receive the schema options from configglue
# - doesn't attempt to recognize django options
lax_parser = LaxOptionParser(
usage="%prog subcommand [options] [args]")
parser, options, args = schemaconfigglue(
configglue_parser, op=lax_parser, argv=self.argv)
utils.update_settings(configglue_parser, settings)
# remove schema-related options from the argv list
self.argv = args
super(GlueManagementUtility, self).execute()
def execute_from_command_line(argv=None):
utility = GlueManagementUtility(argv)
utility.execute()
if django.VERSION[:2] < (1, 4):
# We're going to go ahead and use our own ManagementUtility here
management.ManagementUtility = GlueManagementUtility
django-configglue-0.7.1/django_configglue/management/commands/ 0000755 0001750 0001750 00000000000 12236762416 025563 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/django_configglue/management/commands/__init__.py 0000664 0001750 0001750 00000000220 12136764467 027677 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
django-configglue-0.7.1/django_configglue/management/commands/settings.py 0000664 0001750 0001750 00000012450 12136764467 030010 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import os
import sys
from optparse import make_option, OptionParser
from configglue.glue import schemaconfigglue
from django.conf import settings, global_settings
from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--global', action='store_true',
dest='include_global',
help='include global settings in lookup'),
make_option('--show', action='store_true', dest='show_current',
help='show current settings'),
make_option('--locate', action='store_true', dest='locate',
help='show location of setting definitions'),
make_option('--validate', action='store_true', dest='validate',
help='validate current settings'),
)
help = ('Show settings attributes (value, location), or '
'validate current settings')
args = '[setting ...]'
def handle(self, *args, **options):
show_current = options.get('show_current')
include_global = options.get('include_global')
locate = options.get('locate')
validate = options.get('validate')
if not args and not (show_current or validate):
self.print_help(sys.argv[0], sys.argv[1])
return
if validate:
output = self.validate_settings()
else:
setting_list = map(str.upper, args)
if locate:
output = self.locate(setting_list)
else:
output = self.get(setting_list)
if show_current:
output += self.show(include_global)
return output
def show(self, include_global=False):
def is_setting(name):
return not name.startswith('__') and name.isupper()
global_settings_ = set(k for k in dir(global_settings) if
is_setting(k))
all_settings = set(k for k in dir(settings) if is_setting(k))
lines = []
if include_global:
local_settings = all_settings
else:
local_settings = all_settings - global_settings_
for name in local_settings:
lines.append("%s = %r" % (name, getattr(settings, name)))
return '\n'.join(lines)
def get(self, keys):
__marker = object()
output = ''
for key in keys:
value = getattr(settings, key, __marker)
if value is __marker:
output = "setting %s not found" % key
else:
output = "%s = %r" % (key, value)
return output
def locate(self, keys):
location = None
try:
parser = settings.__CONFIGGLUE_PARSER__
except AttributeError:
# this is a normal settings file, not generated by configglue
module = __import__(settings.SETTINGS_MODULE, globals(),
locals(), [''])
location = module.__file__
output = []
if location is None:
# looking in configglue settings
for key in keys:
cases = [key, key.lower(), key.upper()]
for case in cases:
location = parser.locate(option=case)
if location is not None:
msg = "setting %s last defined in %r"
output.append(msg % (key.upper(),
os.path.realpath(location)))
break
else:
output.append("setting %s not found" % key.upper())
else:
# looking in django settings
for key in map(str.upper, keys):
if key in dir(settings):
msg = "setting %s last defined in %r"
output.append(msg % (key, os.path.realpath(location)))
else:
output.append("setting %s not found" % key)
return '\n'.join(output)
def validate_settings(self):
is_valid = True
msg = 'Settings appear to be fine.'
try:
parser = settings.__CONFIGGLUE_PARSER__
except AttributeError:
# this is a normal settings file, not generated by configglue
msg = 'The settings module was not generated by configglue. '
msg += 'Can only validate configglue generated settings.'
return msg
is_valid, errors = parser.is_valid(report=True)
if not is_valid:
msg = "Settings did not validate against schema.\n\n%s\n"
errors = '\n'.join(errors)
raise CommandError(msg % errors)
return msg
def create_parser(self, prog_name, subcommand):
"""
Add all our SchemaConfigParser's options so they can be shown
in help messages and such.
"""
parser = OptionParser(prog=prog_name,
usage=self.usage(subcommand),
version=self.get_version(),
option_list=self.option_list)
configglue_parser = settings.__CONFIGGLUE_PARSER__
op, options, args = schemaconfigglue(configglue_parser, op=parser)
return op
django-configglue-0.7.1/django_configglue/tests/ 0000755 0001750 0001750 00000000000 12236762416 023010 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/django_configglue/tests/test_settings.py 0000664 0001750 0001750 00000021075 12236751653 026271 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import os.path
import django
from django import get_version
from django.conf import settings
from django.core.management import CommandError
from mock import patch, Mock
from django_configglue.management import GlueManagementUtility
from django_configglue.utils import SETTINGS_ENCODING
from django_configglue.schema import schemas
from django_configglue.tests.helpers import (
ConfigGlueDjangoCommandTestCase,
SchemaHelperTestCase,
)
class SettingsCommandTestCase(ConfigGlueDjangoCommandTestCase):
COMMAND = 'settings'
def test_no_args(self):
self.call_command()
self.assertTrue(self.output.startswith('Usage: '))
def test_get(self):
self.call_command('installed_apps')
expected_output = "INSTALLED_APPS = ['django_configglue']"
self.assertEqual(self.output.strip(), expected_output)
def test_get_not_found(self):
self.call_command('bogus')
expected_output = "setting BOGUS not found"
self.assertEqual(self.output.strip(), expected_output)
def test_show(self):
expected_values = [
'SITE_ID = 1',
"SETTINGS_MODULE = 'django_configglue.tests.settings'",
"ROOT_URLCONF = 'urls'",
"SETTINGS_ENCODING = '%s'" % SETTINGS_ENCODING,
]
# Django 1.6 needs special treatment (BASE_DIR is not a core setting,
# but it's a very useful convention from the example project)
if django.VERSION >= (1, 6, 0):
expected_values.append("BASE_DIR = ''")
self.call_command(show_current=True)
output_lines = self.output.strip().split('\n')
self.assertEqual(set(expected_values), set(output_lines))
def test_show_global(self):
self.call_command(show_current=True, include_global=True)
expected_output = dict([(key, getattr(settings, key)) for key in
dir(settings) if self.is_setting(key)])
# process output into dictionary
items = map(lambda x: x.split(' = '),
self.output.strip().split('\n'))
items = map(lambda x: (x[0].strip(), eval(x[1].strip())),
(t for t in items if self.is_setting(t[0])))
output = dict(items)
# test equality
self.assertEqual(output, expected_output)
def test_locate_setting(self):
self.call_command('time_zone', locate=True)
location = os.path.join(os.path.realpath(os.path.curdir), 'test.cfg')
expected_output = "setting TIME_ZONE last defined in '%s'" % location
self.assertEqual(self.output.strip(), expected_output)
def test_locate_setting_not_found(self):
self.call_command('bogus', locate=True)
expected_output = 'setting BOGUS not found'
self.assertEqual(self.output.strip(), expected_output)
def test_locate_setting_no_configglue_parser(self):
wrapped = getattr(settings, self.wrapped_settings)
old_CONFIGGLUE_PARSER = wrapped.__CONFIGGLUE_PARSER__
del wrapped.__CONFIGGLUE_PARSER__
try:
self.call_command('time_zone', locate=True)
mod = __import__('django_configglue.tests.settings', globals(),
locals(), [''])
location = os.path.realpath(mod.__file__)
expected_output = "setting TIME_ZONE last defined in %r" % location
self.assertEqual(self.output.strip(), expected_output)
finally:
wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER
def test_locate_setting_not_found_no_configglue_parser(self):
wrapped = getattr(settings, self.wrapped_settings)
old_CONFIGGLUE_PARSER = wrapped.__CONFIGGLUE_PARSER__
del wrapped.__CONFIGGLUE_PARSER__
try:
self.call_command('bogus', locate=True)
expected_output = 'setting BOGUS not found'
self.assertEqual(self.output.strip(), expected_output)
finally:
wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER
def test_wrapped_settings(self):
# the settings object has a _target attribute
# this is true for versions of django <= 1.0.2
expected = '_target'
if django.VERSION[:3] > (1, 0, 2):
# the settings object has a _wrapped attribute
# this is true for versions of django > 1.0.2
expected = '_wrapped'
self.assertEqual(self.wrapped_settings, expected)
class GeneratedSettingsTestCase(ConfigGlueDjangoCommandTestCase,
SchemaHelperTestCase):
def setUp(self):
super(GeneratedSettingsTestCase, self).setUp()
self.expected_schema = schemas.get(
django.get_version(), strict=True)()
self.version = '.'.join(django.get_version().split('.')[:2]) + '.foo'
mock_get_version = Mock(return_value=self.version)
self.patch_get_version = patch(
'django_configglue.tests.settings.django.get_version',
mock_get_version)
self.patch_get_version.start()
self.mock_warn = Mock()
self.patch_warn = patch(
'django_configglue.schema.logging.warn', self.mock_warn)
self.patch_warn.start()
def tearDown(self):
self.patch_get_version.stop()
self.patch_warn.stop()
super(GeneratedSettingsTestCase, self).tearDown()
def test_generated_schema(self):
# import here so that the necessary modules can be mocked before
# being required
self.load_settings()
from django.conf import settings
schema = settings.__CONFIGGLUE_PARSER__.schema
self.assert_schemas_equal(schema, self.expected_schema)
self.assertEqual(self.mock_warn.call_args_list,
[(("No schema registered for version '%s'" % self.version,),
{}),
(("Dynamically creating schema for version '%s'" % self.version,),
{})])
class ValidateCommandTestCase(ConfigGlueDjangoCommandTestCase):
COMMAND = 'settings'
def test_valid_config(self):
try:
self.call_command(validate=True)
except SystemExit:
pass
expected_output = 'Settings appear to be fine.'
self.assertEqual(self.output.strip(), expected_output)
def test_invalid_config(self):
config = """
[bogus]
invalid_setting = foo
"""
self.set_config(config)
self.load_settings()
try:
self.call_command(validate=True)
except (SystemExit, CommandError), e:
error_msg = 'Settings did not validate against schema.'
self.assertTrue((error_msg in self.output.strip()) or
error_msg in str(e))
def test_no_configglue_parser(self):
wrapped = getattr(settings, self.wrapped_settings)
old_CONFIGGLUE_PARSER = wrapped.__CONFIGGLUE_PARSER__
del wrapped.__CONFIGGLUE_PARSER__
try:
self.call_command(validate=True)
expected_output = ('The settings module was not generated by '
'configglue. Can only validate configglue generated settings.')
self.assertEqual(self.output.strip(), expected_output)
finally:
wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER
class CommandLineIntegrationTestCase(ConfigGlueDjangoCommandTestCase):
COMMAND = 'settings'
def test_help(self):
self.call_command()
self.assertTrue('--django_debug' in self.output)
def test_update_settings(self):
self.assertTrue(settings.DEBUG)
args = ['manage.py', 'settings', '--django_debug=False', 'DEBUG']
utility = GlueManagementUtility(argv=args)
self.begin_capture()
try:
utility.execute()
finally:
self.end_capture()
self.assertTrue('False' in self.output)
def test_version_is_printed_once(self):
args = ['manage.py', '--version']
utility = GlueManagementUtility(argv=args)
self.begin_capture()
try:
utility.execute()
finally:
self.end_capture()
expected = get_version()
self.assertEqual(1, self.output.count(expected))
def test_noargs_doesnt_error(self):
args = ['manage.py']
utility = GlueManagementUtility(argv=args)
self.begin_capture()
try:
utility.execute()
except SystemExit:
# Django <= 1.3 uses SystemExit to terminate management
# command
pass
finally:
self.end_capture()
self.assertFalse('Unknown command' in self.output)
django-configglue-0.7.1/django_configglue/tests/helpers.py 0000664 0001750 0001750 00000015102 12136764467 025034 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import logging
import os
import sys
import textwrap
from StringIO import StringIO
import django
from django.core import management
from django.conf import settings
from django.test import TestCase
try:
from django.utils.functional import empty
except ImportError:
empty = None
from configglue.schema import (
ListOption,
TupleOption,
Schema,
)
class ConfigGlueDjangoCommandTestCase(TestCase):
COMMAND = ''
def setUp(self):
super(ConfigGlueDjangoCommandTestCase, self).setUp()
# disable logging during tests
self.level = logging.getLogger().level
logging.disable(logging.ERROR)
config = textwrap.dedent("""
[django]
installed_apps = django_configglue
time_zone = Europe/London
databases = databases
[databases]
default = db_default
[db_default]
engine = django.db.backends.sqlite3
name = :memory:
""")
self.set_config(config)
self._DJANGO_SETTINGS_MODULE = self.load_settings()
def tearDown(self):
# re-enable logging
logging.getLogger().setLevel(self.level)
self.load_settings(self._DJANGO_SETTINGS_MODULE)
self.assertEqual(os.environ['DJANGO_SETTINGS_MODULE'],
self._DJANGO_SETTINGS_MODULE)
os.remove('test.cfg')
super(ConfigGlueDjangoCommandTestCase, self).tearDown()
def set_config(self, config):
config_file = open('test.cfg', 'w')
config_file.write(config)
config_file.close()
@property
def wrapped_settings(self):
# make sure the wrapped object is not None
# by just querying it for a setting
getattr(settings, 'DEBUG', False)
assert(getattr(settings, '_wrapped') is not empty)
return '_wrapped'
def load_settings(self, module='django_configglue.tests.settings'):
old_module = os.environ['DJANGO_SETTINGS_MODULE']
# remove old settings module
if old_module in sys.modules:
del sys.modules[old_module]
# keep runtime settings
extra_settings = {}
if django.VERSION[:2] == (1, 1):
extra_settings = {
'DATABASE_NAME': settings.DATABASE_NAME,
'DATABASE_SUPPORTS_TRANSACTIONS': getattr(
settings, 'DATABASE_SUPPORTS_TRANSACTIONS'),
}
# save _original_allowed_hosts so that the teardown will work
# properly
_original_allowed_hosts = getattr(
settings, '_original_allowed_hosts', None)
# force django to reload its settings
setattr(settings, self.wrapped_settings, empty)
# update settings module for next reload
os.environ['DJANGO_SETTINGS_MODULE'] = module
# synch extra settings
for key, value in extra_settings.items():
setattr(settings, key, value)
settings._original_allowed_hosts = _original_allowed_hosts
if hasattr(self, 'extra_settings'):
for key, value in self.extra_settings.items():
setattr(settings, key, value)
self.extra_settings = extra_settings
return old_module
def is_setting(self, name):
return not name.startswith('__') and name.isupper()
def begin_capture(self):
self._stdout = sys.stdout
self._stderr = sys.stderr
sys.stdout = StringIO()
sys.stderr = StringIO()
def end_capture(self):
sys.stdout.seek(0)
sys.stderr.seek(0)
self.output = sys.stdout.read() + sys.stderr.read()
sys.stdout = self._stdout
sys.stderr = self._stderr
def call_command(self, *args, **kwargs):
self.begin_capture()
try:
management.call_command(self.COMMAND, *args, **kwargs)
finally:
self.end_capture()
class SchemaHelperTestCase(TestCase):
def setUp(self):
super(SchemaHelperTestCase, self).setUp()
# disable logging during tests
self.level = logging.getLogger().level
logging.disable(logging.ERROR)
def tearDown(self):
# re-enable logging
logging.getLogger().setLevel(self.level)
super(SchemaHelperTestCase, self).tearDown()
def assert_schema_structure(self, schema_cls, version, options):
self.assertTrue(issubclass(schema_cls, Schema))
self.assertEqual(schema_cls.version, version)
schema = schema_cls()
# assert sections
section_names = [section.name for section in schema.sections()]
self.assertEqual(section_names, ['django'])
# assert options for django section
option_names = [option.name for option in schema.options('django')]
self.assertEqual(option_names, options.keys())
# assert options
for name, value in options.items():
option = schema.section('django').option(name)
self.assertEqual(type(option), type(value))
self.assertEqual(option.default, value.default)
def assert_schemas_equal(self, this, other):
# compare schemas
this_sections = sorted(
[section.name for section in this.sections()])
other_sections = sorted(
[section.name for section in other.sections()])
self.assertEqual(this_sections, other_sections)
self.assertEqual(this_sections, ['django'])
# compare options
section = this.section('django')
expected_section = other.section('django')
options = section.options()
this_options = sorted(
[option.name for option in options])
other_options = sorted(
[option.name for option in expected_section.options()])
self.assertEqual(this_options, other_options)
for option in options:
expected_option = expected_section.option(option.name)
# handle special case for list/tuple
# django defaults to tuples for options it defines as lists
if (isinstance(option, (ListOption, TupleOption)) or
isinstance(expected_option, (ListOption, TupleOption))):
if option.default is None:
self.assertIsNone(expected_option.default)
else:
self.assertEqual(list(option.default),
list(expected_option.default))
else:
self.assertEqual(option.default,
expected_option.default)
django-configglue-0.7.1/django_configglue/tests/test_configglue.py 0000664 0001750 0001750 00000040054 12145240342 026534 0 ustar ricardo ricardo 0000000 0000000 # -*- coding: utf-8 -*-
# Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import inspect
import textwrap
from cStringIO import StringIO
from optparse import BadOptionError
from unittest import TestCase
import django
from configglue.schema import (
BoolOption,
DictOption,
IntOption,
ListOption,
Schema,
Section,
StringOption,
TupleOption,
)
from configglue.parser import (
CONFIG_FILE_ENCODING,
SchemaConfigParser,
)
from django.conf import settings
from django.conf import global_settings
from mock import patch
from django_configglue import management
from django_configglue.utils import (
SETTINGS_ENCODING,
configglue,
get_django_settings,
update_settings,
get_project_settings,
)
from django_configglue.schema import (
BaseDjangoSchema,
DjangoSchemaFactory,
UpperCaseDictOption,
schemas,
derivate_django_schema,
)
from django_configglue.tests.helpers import (
ConfigGlueDjangoCommandTestCase,
SchemaHelperTestCase,
)
class DjangoSupportTestCase(SchemaHelperTestCase):
def test_get_django_settings(self):
class MySchema(Schema):
foo = IntOption()
bar = DictOption(
spec={'baz': IntOption(),
'BAZ': IntOption()})
expected = {'FOO': 0, 'BAR': {'baz': 0, 'BAZ': 0}}
parser = SchemaConfigParser(MySchema())
result = get_django_settings(parser)
self.assertEqual(result, expected)
def test_get_django_settings_encoding(self):
class MySchema(Schema):
foo = StringOption()
expected = {'FOO': u'€'.encode(SETTINGS_ENCODING)}
config = StringIO(u'[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING))
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertEqual(parser.values('__main__'), {'foo': u'€'})
result = get_django_settings(parser)
self.assertEqual(result, expected)
def test_update_settings(self):
class MySchema(Schema):
foo = IntOption()
env = {}
parser = SchemaConfigParser(MySchema())
update_settings(parser, env)
expected_env = {
'FOO': 0,
'SETTINGS_ENCODING': SETTINGS_ENCODING,
'__CONFIGGLUE_PARSER__': parser,
}
self.assertEqual(env, expected_env)
def test_schemafactory_get(self):
# test get valid version
self.assertEqual(
schemas.get('1.0', strict=True),
BaseDjangoSchema
)
# test get invalid version
self.assertRaises(ValueError, schemas.get, '1.1.1', strict=True)
def test_schema_versions(self):
django_13 = schemas.get('1.3')()
django_14 = schemas.get('1.4')()
self.assertEqual(django_13.version, '1.3')
self.assertEqual(django_14.version, '1.4')
self.assertFalse(django_13 is django_14)
def test_register_without_version(self):
class MySchema(Schema):
pass
schemas = DjangoSchemaFactory()
self.assertRaises(ValueError, schemas.register, MySchema)
def test_configglue(self):
target = {}
schema = schemas.get(django.get_version(), strict=False)
configglue(schema, [], target)
# target is consistent with django's settings module
# except for a few keys
exclude_keys = ['DATABASE_SUPPORTS_TRANSACTIONS', 'SETTINGS_MODULE']
# CACHE_BACKEND has been removed from django 1.3 schema but is
# added by django at runtime, so let's skip that too
if schema.version >= '1.3':
exclude_keys.append('CACHE_BACKEND')
shared_key = lambda x: (not x.startswith('__') and x.upper() == x and
x not in exclude_keys)
expected_keys = set(filter(shared_key, dir(settings)))
target_keys = set(filter(shared_key, target.keys()))
self.assertEqual(expected_keys, target_keys)
@patch('django_configglue.utils.update_settings')
@patch('django_configglue.utils.SchemaConfigParser')
def test_configglue_calls(self, MockSchemaConfigParser,
mock_update_settings):
target = {}
configglue(BaseDjangoSchema, [], target)
MockSchemaConfigParser.assert_called_with(BaseDjangoSchema())
MockSchemaConfigParser.return_value.read.assert_called_with([])
mock_update_settings.assert_called_with(
MockSchemaConfigParser.return_value, target)
def test_schemafactory_build(self):
schemas = DjangoSchemaFactory()
data = [
(IntOption, 1),
(BoolOption, True),
(TupleOption, (1, 2)),
(ListOption, [1, 2]),
(DictOption, {'a': 1}),
(StringOption, 'foo'),
]
for i, (opt_type, default) in enumerate(data):
schema_cls = schemas.build('bogus.%d' % i, {'foo': default}, Schema)
# do common checks
self.assert_schema_structure(schema_cls, 'bogus.%d' % i,
{'foo': opt_type(name='foo', default=default)})
def test_schemafactory_build_django(self):
schemas = DjangoSchemaFactory()
schema = schemas.build()
# get known django schema
# fail for unknown versions of django
django_schema = schemas.get(django.get_version(), strict=True)
self.assert_schemas_equal(schema(), django_schema())
def test_schemafactory_get_django(self):
schemas = DjangoSchemaFactory()
# build a django schema
# get only django settings
options = dict([(name, value) for (name, value) in
inspect.getmembers(settings) if name.isupper()])
schema = schemas.build(django.get_version(), options)
# get known django schema
# fail for unknown versions of django
django_schema = schemas.get(django.get_version(), strict=True)
self.assert_schemas_equal(schema(), django_schema())
def test_schemafactory_build_complex_options(self):
schemas = DjangoSchemaFactory()
options = {
'dict1': {'foo': 1, 'bar': '2'},
'dict2': {'foo': {'bar': 2, 'baz': 3}},
'list1': ['1', '2', '3'],
'list2': [1, 2, 3],
}
expected = {
'dict1': DictOption(name='dict1', default=options['dict1'],
item=StringOption()),
'dict2': DictOption(name='dict2', default=options['dict2'],
item=DictOption()),
'list1': ListOption(name='list1', default=options['list1'],
item=StringOption()),
'list2': ListOption(name='list2', default=options['list2'],
item=IntOption()),
}
schema = schemas.build('foo', options)()
sections = sorted(
[section.name for section in schema.sections()])
section = schema.section('django')
self.assertEqual(sections, ['django'])
for name in options:
option = expected[name]
option.section = section
self.assertEqual(section.option(name), option)
self.assertEqual(section.option(name).item, option.item)
@patch('django_configglue.schema.logging')
def test_schemafactory_get_unknown_build(self, mock_logging):
schemas = DjangoSchemaFactory()
version_string = django.get_version()
self.assertFalse(version_string in schemas._schemas)
# build schema
schema = schemas.get(version_string, strict=False)()
# get expected schema
options = dict([(name.lower(), value) for (name, value) in
inspect.getmembers(global_settings) if name.isupper()])
project_options = dict([(name.lower(), value) for (name, value) in
inspect.getmembers(get_project_settings()) if name.isupper()])
# handle special case of ROOT_URLCONF which depends on the
# project name
root_urlconf = project_options['root_urlconf'].replace(
'{{ project_name }}.', '')
project_options['root_urlconf'] = root_urlconf
options.update(project_options)
expected = schemas.build(django.get_version(), options)()
# compare schemas
self.assert_schemas_equal(schema, expected)
self.assertEqual(mock_logging.warn.call_args_list[0][0][0],
"No schema registered for version '{0}'".format(version_string))
self.assertEqual(mock_logging.warn.call_args_list[1][0][0],
"Dynamically creating schema for version '{0}'".format(
version_string))
def test_derivate_django_schema(self):
class Parent(Schema):
version = 'parent'
class django(Section):
foo = IntOption()
bar = IntOption()
class Child(Parent):
version = 'parent'
class django(Section):
bar = IntOption()
derivated = derivate_django_schema(Parent, exclude=['foo'])
self.assert_schemas_equal(derivated(), Child())
def test_derivate_django_schema_no_exclude(self):
class Parent(Schema):
version = 'parent'
class django(Section):
foo = IntOption()
derivated = derivate_django_schema(Parent)
self.assertEqual(derivated, Parent)
def test_django13_caches(self):
schema = schemas.get('1.3')
expected = DictOption(
item=UpperCaseDictOption(
spec={
'backend': StringOption(),
'location': StringOption()}))
self.assertEqual(schema.django.caches.item, expected.item)
def test_django13_logging_config(self):
schema = schemas.get('1.3')
section = Section(name='django')
expected = StringOption(name='logging_config', null=True,
default='django.utils.log.dictConfig',
help='The callable to use to configure logging')
expected.section = section
self.assertEqual(schema.django.logging_config, expected)
def test_django13_null_logging_config(self):
config = StringIO(textwrap.dedent("""
[django]
logging_config = None
"""))
schema = schemas.get('1.3')
parser = SchemaConfigParser(schema())
parser.readfp(config)
value = parser.values()['django']['logging_config']
self.assertEqual(value, None)
def test_django13_custom_logging_config(self):
config = StringIO(textwrap.dedent("""
[django]
logging_config = foo
"""))
schema = schemas.get('1.3')
parser = SchemaConfigParser(schema())
parser.readfp(config)
value = parser.values()['django']['logging_config']
self.assertEqual(value, 'foo')
def test_django13_logging_default(self):
expected = {
'version': 1,
'handlers': {
'mail_admins': {
'class': 'django.utils.log.AdminEmailHandler',
'level': 'ERROR'}},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True}},
'disable_existing_loggers': False,
}
schema = schemas.get('1.3')
self.assertEqual(schema().django.logging.default, expected)
class GlueManagementUtilityTestCase(ConfigGlueDjangoCommandTestCase):
def setUp(self):
super(GlueManagementUtilityTestCase, self).setUp()
self.util = management.GlueManagementUtility()
def execute(self):
self.begin_capture()
try:
self.util.execute()
finally:
self.end_capture()
def test_execute_no_args(self):
self.util.argv = ['']
try:
self.execute()
except SystemExit:
pass
self.assertTrue(
"Type '%s help ' for help" % (self.util.prog_name,) in
self.output)
@patch('sys.stdout')
def test_execute_help(self, mock_stdout):
mock_stdout.isatty.return_value = False
self.util.argv = ['', 'help']
try:
self.execute()
except SystemExit:
# In earlier versions than 1.4, help was raising SystemExit
pass
self.assertTrue(self.util.main_help_text() in self.output)
@patch('sys.stdout')
def test_execute_help_option(self, mock_stdout):
mock_stdout.isatty.return_value = False
self.util.argv = ['', '--help']
self.execute()
self.assertTrue(self.util.main_help_text() in self.output)
def test_execute_help_for_command(self):
self.util.argv = ['', 'help', 'settings']
self.execute()
self.assertTrue('Show settings attributes' in self.output)
def test_execute_version(self):
from django import get_version
self.util.argv = ['', '--version']
self.execute()
self.assertTrue(get_version() in self.output)
def test_execute(self):
self.util.argv = ['', 'settings']
self.execute()
self.assertTrue('Show settings attributes' in self.output)
@patch('sys.stdout')
def test_execute_settings_exception(self, mock_stdout):
mock_stdout.isatty.return_value = False
from django.conf import settings
wrapped = getattr(settings, self.wrapped_settings)
old_CONFIGGLUE_PARSER = wrapped.__CONFIGGLUE_PARSER__
del wrapped.__CONFIGGLUE_PARSER__
try:
self.util.argv = ['', 'help']
try:
self.execute()
except SystemExit:
pass
self.assertTrue(
self.util.main_help_text() in self.output)
finally:
wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER
def test_execute_with_schema_options(self):
self.util.argv = ['', '--django_debug=False', 'help', 'settings']
self.execute()
self.assertTrue('Show settings attributes' in self.output)
def test_verbosity_is_preserved(self):
self.util.argv = ['', 'settings', '--verbosity=2']
handle_path = ('django_configglue.management.commands.settings.'
'Command.handle')
with patch(handle_path) as mock_handle:
self.execute()
args, options = mock_handle.call_args
self.assertEqual('2', options['verbosity'])
class LaxOptionParserTestCase(TestCase):
def test_explicit_value_for_unknown_option(self):
parser = management.LaxOptionParser()
rargs = ["--foo=bar"]
self.assertRaises(BadOptionError, parser._process_long_opt, rargs, [])
self.assertEqual([], rargs)
class UpperCaseDictOptionTestCase(TestCase):
def test_parse(self):
class MySchema(Schema):
foo = UpperCaseDictOption()
config = StringIO(textwrap.dedent("""
[__main__]
foo = mydict
[mydict]
bar = 42
"""))
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
result = schema.foo.parse('mydict', parser)
self.assertEqual(result, {'BAR': '42'})
class ManagementTestCase(TestCase):
def test_django_13_management_utility(self):
with patch.object(django, 'VERSION', (1, 3)):
# force reloading of module
reload(management)
self.assertEqual(management.management.ManagementUtility,
management.GlueManagementUtility)
def test_django_14_management_utility(self):
with patch.object(django, 'VERSION', (1, 4)):
# force reloading of module
reload(management)
self.assertEqual(management.management.ManagementUtility,
django.core.management.ManagementUtility)
def test_execute_from_command_line(self):
name = 'django_configglue.management.GlueManagementUtility'
with patch(name) as mock_utility:
management.execute_from_command_line()
mock_utility.assert_called_once_with(None)
django-configglue-0.7.1/django_configglue/tests/__init__.py 0000664 0001750 0001750 00000000441 12136764467 025131 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
# import all test modules to conform to Django requirements
from test_configglue import *
from test_settings import *
from test_schema import *
django-configglue-0.7.1/django_configglue/tests/settings.py 0000664 0001750 0001750 00000001110 12136764467 025224 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import django
from django_configglue.utils import configglue
from django_configglue.schema import schemas
DjangoSchema = schemas.get(django.get_version(), strict=False)
version = DjangoSchema.version
main_cfg = 'main.cfg'
if version >= '1.5':
main_cfg = 'main-15.cfg'
elif version >= '1.4':
main_cfg = 'main-14.cfg'
elif version >= '1.3':
main_cfg = 'main-13.cfg'
configglue(DjangoSchema, [main_cfg, 'test.cfg'], __name__)
django-configglue-0.7.1/django_configglue/tests/test_schema.py 0000664 0001750 0001750 00000001430 12145240360 025645 0 ustar ricardo ricardo 0000000 0000000 import textwrap
from cStringIO import StringIO
from unittest import TestCase
from configglue.parser import SchemaConfigParser
from django_configglue.schema import (
BaseDjangoSchema,
Django14Schema,
)
class DjangoSchemaTestCase(TestCase):
def test_time_zone_is_null(self):
config = StringIO(textwrap.dedent("""
[django]
time_zone = None
"""))
parser = SchemaConfigParser(BaseDjangoSchema())
parser.readfp(config)
value = parser.values()['django']['time_zone']
self.assertEqual(value, None)
def test_default_wsgi_application_is_none(self):
parser = SchemaConfigParser(Django14Schema())
value = parser.values()['django']['wsgi_application']
self.assertEqual(value, None)
django-configglue-0.7.1/django_configglue/utils.py 0000664 0001750 0001750 00000004221 12136764467 023370 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import imp
import os
import sys
from configglue.parser import SchemaConfigParser
SETTINGS_ENCODING = 'utf-8'
def get_django_settings(parser):
def encode(item):
if isinstance(item, basestring):
value = item.encode(SETTINGS_ENCODING)
elif isinstance(item, dict):
items = encode(item.items())
value = dict(items)
elif isinstance(item, (list, tuple)):
value = map(encode, item)
else:
value = item
return value
result = {}
for section, data in parser.values().items():
for option, value in data.items():
result[option.upper()] = encode(value)
return result
def update_settings(parser, target):
settings = get_django_settings(parser)
settings.update({
# keep parser reference
'__CONFIGGLUE_PARSER__': parser,
# save encoding used
'SETTINGS_ENCODING': SETTINGS_ENCODING,
})
if isinstance(target, dict):
# import config into target dict (for backwards compatibility)
target.update(settings)
else:
# import config into target module
if isinstance(target, basestring):
# target is the module's name, so import the module first
__import__(target)
target = sys.modules[target]
for name, value in settings.items():
setattr(target, name, value)
def configglue(schema_class, configs, target):
scp = SchemaConfigParser(schema_class())
scp.read(configs)
update_settings(scp, target)
return scp
def get_project_settings():
"""Find project_template settings file, in 1.4 you can't just use import"""
from django import conf
project_template_dir = os.path.join(
os.path.dirname(conf.__file__),
'project_template')
for root, dirs, files in os.walk(project_template_dir):
if 'settings.py' in files:
return imp.load_source('project_settings',
os.path.join(root, 'settings.py'))
django-configglue-0.7.1/django_configglue/__init__.py 0000664 0001750 0001750 00000000354 12236761734 023765 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
__version__ = '0.7.1'
# monkey-patch django's management utility
from . import management
django-configglue-0.7.1/django_configglue/models.py 0000664 0001750 0001750 00000000220 12136764467 023506 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
django-configglue-0.7.1/django_configglue/schema.py 0000664 0001750 0001750 00000237222 12236761665 023477 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
import inspect
import logging
from configglue.schema import (
BoolOption,
Section,
DictOption,
IntOption,
ListOption,
Schema,
StringOption,
TupleOption,
)
from django import get_version, VERSION
from django.conf import global_settings
from django_configglue.utils import get_project_settings
# As in django.conf.global_settings:
# This is defined here as a do-nothing function because we can't import
# django.utils.translation -- that module depends on the settings.
gettext_noop = lambda s: s
class UpperCaseDictOption(DictOption):
""" A DictOption with all upper-case keys. """
def parse(self, section, parser=None, raw=False):
parsed = super(UpperCaseDictOption, self).parse(
section, parser, raw)
result = {}
for k, v in parsed.items():
result[k.upper()] = v
return result
def derivate_django_schema(schema, exclude=None):
"""Return a modified version of a schema.
The source schema *must* have a 'version' attribute and
a 'django' section.
The resulting schema is almost a copy of the original one, except
for excluded options in the 'django' section.
"""
if not exclude:
return schema
# create the schema class
cls = type(schema.__name__, (schema,), {'version': schema.version})
# include all non-excluded options
options = {}
for option in schema().django.options():
if option.name in exclude:
continue
options[option.name] = option
# create the 'django' section
django_section = type('django', (Section,), options)
setattr(cls, 'django', django_section)
return cls
class BaseDjangoSchema(Schema):
version = '1.0'
# Sections
class django(Section):
################
# CORE #
################
debug = BoolOption(default=True)
template_debug = BoolOption(default=True)
debug_propagate_exceptions = BoolOption(default=False,
help="Whether the framework should propagate raw exceptions "
"rather than catching them. This is useful under some "
"testing situations and should never be used on a live site.")
use_etags = BoolOption(default=False,
help="Whether to use the 'Etag' header. This saves bandwidth but "
"slows down performance.")
admins = ListOption(item=TupleOption(length=2), default=[],
help="People who get code error notifications. In the format "
"(('Full Name', 'email@domain.com'), "
"('Full Name', 'anotheremail@domain.com'))")
internal_ips = TupleOption(default=(),
help="Tuple of IP addresses, as strings, that see debug comments, "
"when DEBUG is true and receive x-headers")
time_zone = StringOption(default='America/Chicago', null=True,
help="Local time zone for this installation. All choices can be "
"found here: "
"http://en.wikipedia.org/wiki/List_of_tz_zones_by_name "
"(although not all systems may support all possibilities)")
language_code = StringOption(default='en-us',
help="Language code for this installation. All choices can be "
"found here: "
"http://www.i18nguy.com/unicode/language-identifiers.html")
languages = ListOption(
item=TupleOption(length=2),
default=[('ar', gettext_noop('Arabic')),
('bn', gettext_noop('Bengali')),
('bg', gettext_noop('Bulgarian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('et', gettext_noop('Estonian')),
('es-ar', gettext_noop('Argentinean Spanish')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('hu', gettext_noop('Hungarian')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('ko', gettext_noop('Korean')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('lv', gettext_noop('Latvian')),
('lt', gettext_noop('Lithuanian')),
('mk', gettext_noop('Macedonian')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sr', gettext_noop('Serbian')),
('sv', gettext_noop('Swedish')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('uk', gettext_noop('Ukrainian')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese'))],
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language")
languages_bidi = TupleOption(default=('he', 'ar', 'fa'),
help="Languages using BiDi (right-to-left) layout")
use_i18n = BoolOption(default=True,
help="If you set this to False, Django will make some "
"optimizations so as not to load the internationalization "
"machinery")
locale_paths = ListOption(item=StringOption())
language_cookie_name = StringOption(default='django_language')
managers = ListOption(item=TupleOption(length=2), default=[],
help="Not-necessarily-technical managers of the site. They get "
"broken link notifications and other various e-mails")
default_content_type = StringOption(default='text/html',
help="Default content type and charset to use for all "
"HttpResponse objects, if a MIME type isn't manually "
"specified. These are used to construct the Content-Type "
"header")
default_charset = StringOption(default='utf-8')
file_charset = StringOption(default='utf-8',
help="Encoding of files read from disk (template and initial "
"SQL files)")
server_email = StringOption(
help="E-mail address that error messages come from",
default='root@localhost')
send_broken_link_emails = BoolOption(default=False,
help="Whether to send broken-link e-mails")
database_engine = StringOption(default='',
help="'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3'"
" or 'oracle'")
database_name = StringOption(default='',
help="Or path to database file if using sqlite3")
database_user = StringOption(default='',
help="Not used with sqlite3")
database_password = StringOption(default='',
help="Not used with sqlite3")
database_host = StringOption(default='',
help="Set to empty string for localhost. Not used with sqlite3")
database_port = StringOption(default='',
help="Set to empty string for default. Not used with sqlite3")
database_options = DictOption(
help="Set to empty dictionary for default")
email_host = StringOption(default='localhost',
help="Host for sending e-mail")
email_port = IntOption(default=25,
help="Port for sending e-mail")
email_host_user = StringOption(default='',
help="Optional SMTP authentication information for EMAIL_HOST")
email_host_password = StringOption(default='',
help="Optional SMTP authentication information for EMAIL_HOST")
email_use_tls = BoolOption(default=False,
help="Optional SMTP authentication information for EMAIL_HOST")
installed_apps = ListOption(item=StringOption(),
default=['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites'],
help="List of strings representing installed apps")
template_dirs = ListOption(item=StringOption(),
help="List of locations of the template source files, in search "
"order")
template_loaders = ListOption(item=StringOption(),
default=[
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
],
help="List of callables that know how to import templates from "
"various sources")
template_context_processors = ListOption(
item=StringOption(),
default=['django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media'],
help="List of processors used by RequestContext to populate the "
"context. Each one should be a callable that takes the "
"request object as its only parameter and returns a "
"dictionary to add to the context")
template_string_if_invalid = StringOption(default='',
help="Output to use in template system for invalid "
"(e.g. misspelled) variables")
admin_media_prefix = StringOption(default='/media/',
help="URL prefix for admin media -- CSS, JavaScript and images. "
"Make sure to use a trailing slash. "
"Examples: 'http://foo.com/media/', '/media/'")
default_from_email = StringOption(
default='webmaster@localhost',
help="Default e-mail address to use for various automated "
"correspondence from the site managers")
email_subject_prefix = StringOption(default='[Django] ',
help="Subject-line prefix for email messages send with "
"django.core.mail.mail_admins or ...mail_managers. Make sure "
"to include the trailing space")
append_slash = BoolOption(default=True,
help="Whether to append trailing slashes to URLs")
prepend_www = BoolOption(default=False,
help="Whether to prepend the 'www.' subdomain to URLs that "
"don't have it")
force_script_name = StringOption(null=True,
help="Override the server-derived value of SCRIPT_NAME")
disallowed_user_agents = ListOption(
item=StringOption(),
default=[],
help="List of compiled regular expression objects representing "
"User-Agent strings that are not allowed to visit any page, "
"systemwide. Use this for bad robots/crawlers")
absolute_url_overrides = DictOption()
allowed_include_roots = TupleOption(
help="Tuple of strings representing allowed prefixes for the "
"{% ssi %} tag")
admin_for = ListOption(item=StringOption(),
help="If this is a admin settings module, this should be a list "
"of settings modules (in the format 'foo.bar.baz') for which "
"this admin is an admin")
ignorable_404_starts = ListOption(item=StringOption(),
default=['/cgi-bin/', '/_vti_bin', '/_vti_inf'],
help="404s that may be ignored")
ignorable_404_ends = ListOption(item=StringOption(),
default=['mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi',
'favicon.ico', '.php'])
secret_key = StringOption(raw=True, default='',
help="A secret key for this particular Django installation. Used "
"in secret-key hashing algorithms. Set this in your "
"settings, or Django will complain loudly")
jing_path = StringOption(default='/usr/bin/jing',
help="Path to the 'jing' executable -- needed to validate "
"XMLFields")
default_file_storage = StringOption(
default='django.core.files.storage.FileSystemStorage',
help="Default file storage mechanism that holds media")
media_root = StringOption(default='',
help="Absolute path to the directory that holds media")
media_url = StringOption(default='',
help="URL that handles the media served from MEDIA_ROOT")
file_upload_handlers = ListOption(item=StringOption(),
default=[
'django.core.files.uploadhandler.MemoryFileUploadHandler',
'django.core.files.uploadhandler.TemporaryFileUploadHandler'],
help="List of upload handler classes to be applied in order")
file_upload_max_memory_size = IntOption(default=2621440,
help="Maximum size, in bytes, of a request before it will be "
"streamed to the file system instead of into memory")
file_upload_temp_dir = StringOption(null=True,
help="Directory in which upload streamed files will be "
"temporarily saved. A value of `None` will make Django use "
"the operating system's default temporary directory (i.e. "
"'/tmp' on *nix systems)")
file_upload_permissions = StringOption(null=True,
help="The numeric mode to set newly-uploaded files to. The value "
"should be a mode you'd pass directly to os.chmod; "
"see http://docs.python.org/lib/os-file-dir.html")
date_format = StringOption(default='N j, Y',
help="Default formatting for date objects. See all available "
"format strings here: "
"http://docs.djangoproject.com/en/dev/ref/templates/builtins/"
"#now")
datetime_format = StringOption(default='N j, Y, P',
help="Default formatting for datetime objects. See all available "
"format strings here: "
"http://docs.djangoproject.com/en/dev/ref/templates/builtins/"
"#now")
time_format = StringOption(default='P',
help="Default formatting for time objects. See all available "
"format strings here: "
"http://docs.djangoproject.com/en/dev/ref/templates/builtins/"
"#now")
year_month_format = StringOption(default='F Y',
help="Default formatting for date objects when only the year and "
"month are relevant. See all available format strings here: "
"http://docs.djangoproject.com/en/dev/ref/templates/builtins/"
"#now")
month_day_format = StringOption(default='F j',
help="Default formatting for date objects when only the month and "
"day are relevant. See all available format strings here: "
"http://docs.djangoproject.com/en/dev/ref/templates/builtins/"
"#now")
transactions_managed = BoolOption(default=False,
help="Do you want to manage transactions manually? "
"Hint: you really don't!")
url_validator_user_agent = StringOption(
default="Django/%s (http://www.djangoproject.com)" % get_version(),
help="The User-Agent string to use when checking for URL validity "
"through the isExistingURL validator")
default_tablespace = StringOption(default='',
help="The tablespaces to use for each model when not "
"specified otherwise")
default_index_tablespace = StringOption(default='',
help="The tablespaces to use for each model when not "
"specified otherwise")
##############
# MIDDLEWARE #
##############
middleware_classes = ListOption(item=StringOption(),
default=[
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware'],
help="List of middleware classes to use. Order is important; in "
"the request phase, these middleware classes will be applied "
"in the order given, and in the response phase the "
"middleware will be applied in reverse order")
############
# SESSIONS #
############
session_cookie_name = StringOption(default='sessionid',
help="Cookie name")
session_cookie_age = IntOption(default=60 * 60 * 24 * 7 * 2,
help="Age of cookie, in seconds (default: 2 weeks)")
session_cookie_domain = StringOption(null=True,
help="A string like '.lawrence.com', or None for standard "
"domain cookie")
session_cookie_secure = BoolOption(default=False,
help="Wether the session cookie should be secure (https:// only)")
session_cookie_path = StringOption(default='/',
help="The path of the sesion cookie")
session_save_every_request = BoolOption(default=False,
help="Whether to save the session data on every request")
session_expire_at_browser_close = BoolOption(default=False,
help="Whether a user's session cookie expires when the Web "
"browser is closed")
session_engine = StringOption(
default='django.contrib.sessions.backends.db',
help="The module to store session data")
session_file_path = StringOption(null=True,
help="Directory to store session files if using the file session "
"module. If None, the backend will use a sensible default")
#########
# CACHE #
#########
cache_backend = StringOption(default='locmem://',
help="The cache backend to use. See the docstring in "
"django.core.cache for the possible values")
cache_middleware_key_prefix = StringOption(default='')
cache_middleware_seconds = IntOption(default=600)
####################
# COMMENTS #
####################
comments_allow_profanities = BoolOption(default=False)
profanities_list = ListOption(item=StringOption(),
default=['asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook',
'nigger', 'shit'],
help="The profanities that will trigger a validation error in the "
"'hasNoProfanities' validator. All of these should be in "
"lowercase")
##################
# AUTHENTICATION #
##################
authentication_backends = ListOption(
item=StringOption(),
default=['django.contrib.auth.backends.ModelBackend'])
login_url = StringOption(default='/accounts/login/')
logout_url = StringOption(default='/accounts/logout/')
login_redirect_url = StringOption(default='/accounts/profile/')
password_reset_timeout_days = IntOption(default=3,
help="The number of days a password reset link is valid for")
###########
# TESTING #
###########
test_runner = StringOption(
default='django.test.simple.run_tests',
help="The name of the method to use to invoke the test suite")
test_database_name = StringOption(null=True,
help="The name of the database to use for testing purposes. "
"If None, a name of 'test_' + DATABASE_NAME will be assumed")
test_database_charset = StringOption(null=True,
help="Strings used to set the character set and collation order "
"for the test database. These values are passed literally to "
"the server, so they are backend-dependent. If None, no "
"special settings are sent (system defaults are used)")
test_database_collation = StringOption(null=True,
help="Strings used to set the character set and collation order "
"for the test database. These values are passed literally to "
"the server, so they are backend-dependent. If None, no "
"special settings are sent (system defaults are used)")
############
# FIXTURES #
############
fixture_dirs = ListOption(item=StringOption(),
help="The list of directories to search for fixtures")
####################
# PROJECT TEMPLATE #
####################
site_id = IntOption(default=1)
# use a slightly different default than in the project settings
# template as it includes the {{ project_name }} variable
# not relying on that variable makes more sense in this case
root_urlconf = StringOption(default='urls')
Django11Base = derivate_django_schema(
BaseDjangoSchema, exclude=['jing_path'])
class Django11Schema(Django11Base):
version = '1.1'
# sections
class django(Django11Base.django):
################
# CORE #
################
# update default value
languages = ListOption(
item=TupleOption(length=2),
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language",
default=[
('ar', gettext_noop('Arabic')),
('bg', gettext_noop('Bulgarian')),
('bn', gettext_noop('Bengali')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinean Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy-nl', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hu', gettext_noop('Hungarian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('uk', gettext_noop('Ukrainian')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),
])
class Django12Schema(Django11Schema):
version = '1.2'
# sections
class django(Django11Schema.django):
################
# CORE #
################
# update default value
languages = ListOption(
item=TupleOption(length=2),
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language",
default=[
('ar', gettext_noop('Arabic')),
('bg', gettext_noop('Bulgarian')),
('bn', gettext_noop('Bengali')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-gb', gettext_noop('British English')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy-nl', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hu', gettext_noop('Hungarian')),
('id', gettext_noop('Indonesian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
('nb', gettext_noop('Norwegian Bokmal')),
('nn', gettext_noop('Norwegian Nynorsk')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('uk', gettext_noop('Ukrainian')),
('vi', gettext_noop('Vietnamese')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),
])
use_l10n = BoolOption(
default=True,
help="If you set this to False, Django will not format dates, "
"numbers and calendars according to the current locale")
databases = DictOption(
item=UpperCaseDictOption(spec={
'engine': StringOption(default='django.db.backends.'),
'name': StringOption(),
'user': StringOption(),
'password': StringOption(),
'host': StringOption(),
'port': StringOption(),
'options': DictOption(),
}),
default={
'default': {
'ENGINE': 'django.db.backends.',
'NAME': '',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
'OPTIONS': {},
}
})
database_routers = ListOption(
item=StringOption(),
help="Classes used to implement db routing behaviour")
email_backend = StringOption(
default='django.core.mail.backends.smtp.EmailBackend',
help="The email backend to use. For possible shortcuts see "
"django.core.mail. The default is to use the SMTP backend. "
"Third party backends can be specified by providing a Python "
"path to a module that defines an EmailBackend class.")
installed_apps = ListOption(item=StringOption(),
help="List of strings representing installed apps",
default=[
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
])
template_loaders = ListOption(item=StringOption(),
help="List of callables that know how to import templates from "
"various sources",
default=[
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
])
template_context_processors = ListOption(
item=StringOption(),
help="List of processors used by RequestContext to populate the "
"context. Each one should be a callable that takes the "
"request object as its only parameter and returns a "
"dictionary to add to the context",
default=[
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.contrib.messages.context_processors.messages',
])
use_x_forwarded_host = BoolOption(default=False,
help="A boolean that specifies whether to use the "
"X-Forwarded-Host header in preference to the Host header. "
"This should only be enabled if a proxy which sets this "
"header is in use.")
format_module_path = StringOption(
null=True, default=None,
help="Python module path where user will place custom format "
"definition. The directory where this setting is pointing "
"should contain subdirectories named as the locales, "
"containing a formats.py file")
short_date_format = StringOption(
default='m/d/Y',
help="Default short formatting for date objects")
short_datetime_format = StringOption(
default='m/d/Y P',
help="Default short formatting for datetime objects")
date_input_formats = ListOption(
item=StringOption(),
default=[
# '2006-10-25', '10/25/2006', '10/25/06'
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y',
# 'Oct 25 2006', 'Oct 25, 2006'
'%b %d %Y', '%b %d, %Y',
# '25 Oct 2006', '25 Oct, 2006'
'%d %b %Y', '%d %b, %Y',
# 'October 25 2006', 'October 25, 2006'
'%B %d %Y', '%B %d, %Y',
# '25 October 2006', '25 October, 2006'
'%d %B %Y', '%d %B, %Y',
],
help="Default formats to be used when parsing dates from input "
"boxes, in order")
time_input_formats = ListOption(
item=StringOption(),
default=[
'%H:%M:%S', # '14:30:59'
'%H:%M', # '14:30'
],
help="Default formats to be used when parsing times from input "
"boxes, in order")
datetime_input_formats = ListOption(
item=StringOption(),
default=[
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
'%Y-%m-%d %H:%M', # '2006-10-25 14:30'
'%Y-%m-%d', # '2006-10-25'
'%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
'%m/%d/%Y %H:%M', # '10/25/2006 14:30'
'%m/%d/%Y', # '10/25/2006'
'%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
'%m/%d/%y %H:%M', # '10/25/06 14:30'
'%m/%d/%y', # '10/25/06'
],
help="Default formats to be used when parsing dates and times "
"from input boxes, in order")
first_day_of_week = IntOption(
default=0,
help="First day of week, to be used on calendars. 0 means Sunday, "
"1 means Monday...")
decimal_separator = StringOption(
default='.',
help="Decimal separator symbol")
use_thousand_separator = BoolOption(
default=False,
help="Boolean that sets whether to add thousand separator when "
"formatting numbers")
number_grouping = IntOption(
default=0,
help="Number of digits that will be together, when splitting them "
"by THOUSAND_SEPARATOR. 0 means no grouping, 3 means "
"splitting by thousands...")
thousand_separator = StringOption(
default=',',
help="Thousand separator symbol")
##############
# MIDDLEWARE #
##############
middleware_classes = ListOption(item=StringOption(),
help="List of middleware classes to use. Order is important; in "
"the request phase, these middleware classes will be applied "
"in the order given, and in the response phase the "
"middleware will be applied in reverse order",
default=[
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
])
########
# CSRF #
########
csrf_failure_view = StringOption(
default='django.views.csrf.csrf_failure',
help="Dotted path to callable to be used as view when a request "
"is rejected by the CSRF middleware")
csrf_cookie_name = StringOption(
default='csrftoken',
help="Name for CSRF cookie")
csrf_cookie_domain = StringOption(
null=True,
help="Domain for CSRF cookie")
############
# MESSAGES #
############
message_storage = StringOption(
default='django.contrib.messages.storage.user_messages.'
'LegacyFallbackStorage',
help="Class to be used as messages backend")
###########
# TESTING #
###########
test_runner = StringOption(
default='django.test.simple.DjangoTestSuiteRunner',
help="The name of the class to use to run the test suite")
Django13Base = derivate_django_schema(
Django12Schema,
exclude=[
'cache_backend',
])
class Django13Schema(Django13Base):
version = '1.3'
class django(Django13Base.django):
# update default value
languages = ListOption(
item=TupleOption(length=2),
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language",
default=[
('ar', gettext_noop('Arabic')),
('az', gettext_noop('Azerbaijani')),
('bg', gettext_noop('Bulgarian')),
('bn', gettext_noop('Bengali')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-gb', gettext_noop('British English')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('es-mx', gettext_noop('Mexican Spanish')),
('es-ni', gettext_noop('Nicaraguan Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy-nl', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hu', gettext_noop('Hungarian')),
('id', gettext_noop('Indonesian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
('nb', gettext_noop('Norwegian Bokmal')),
('nn', gettext_noop('Norwegian Nynorsk')),
('pa', gettext_noop('Punjabi')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('uk', gettext_noop('Ukrainian')),
('ur', gettext_noop('Urdu')),
('vi', gettext_noop('Vietnamese')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),
])
installed_apps = ListOption(item=StringOption(),
help="List of strings representing installed apps",
default=[
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
])
template_context_processors = ListOption(
item=StringOption(),
help="List of processors used by RequestContext to populate the "
"context. Each one should be a callable that takes the "
"request object as its only parameter and returns a "
"dictionary to add to the context",
default=[
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.contrib.messages.context_processors.messages',
])
static_root = StringOption(
default='',
help='Absolute path to the directory that holds static files.')
static_url = StringOption(
null=True, default='/static/',
help='URL that handles the static files served from STATIC_ROOT.')
############
# SESSIONS #
############
session_cookie_httponly = BoolOption(
default=False,
help="Whether to use the non-RFC standard htt pOnly flag (IE, "
"FF3+, others)")
#########
# CACHE #
#########
caches = DictOption(
item=UpperCaseDictOption(spec={
'backend': StringOption(),
'location': StringOption()})
)
cache_middleware_alias = StringOption(default='default')
############
# COMMENTS #
############
profanities_list = ListOption(item=StringOption(),
default=[],
help="The profanities that will trigger a validation error in the "
"'hasNoProfanities' validator. All of these should be in "
"lowercase")
comments_banned_users_group = StringOption(
null=True,
help="The group ID that designates which users are banned. "
"Set to None if you're not using it")
comments_moderators_group = StringOption(
null=True,
help="The group ID that designates which users can moderate "
"comments. Set to None if you're not using it")
comments_sketchy_users_group = StringOption(
null=True,
help="The group ID that designates the users whose comments "
"should be e-mailed to MANAGERS. Set to None if you're not "
"using it")
comments_first_few = IntOption(
default=0,
help="The system will e-mail MANAGERS the first "
"COMMENTS_FIRST_FEW comments by each user. Set this to 0 if "
"you want to disable it")
banned_ips = TupleOption(
help="A tuple of IP addresses that have been banned from "
"participating in various Django-powered features")
###########
# LOGGING #
###########
logging_config = StringOption(null=True,
default='django.utils.log.dictConfig',
help='The callable to use to configure logging')
logging = DictOption(
spec={
'version': IntOption(default=1),
'formatters': DictOption(
item=DictOption(
spec={
'format': StringOption(null=True),
'datefmt': StringOption(null=True)})),
'filters': DictOption(
item=DictOption(
spec={'name': StringOption()})),
'handlers': DictOption(
item=DictOption(
spec={
'class': StringOption(fatal=True),
'level': StringOption(),
'formatter': StringOption(),
'filters': StringOption()})),
'loggers': DictOption(
item=DictOption(
spec={
'level': StringOption(),
'propagate': BoolOption(),
'filters': ListOption(item=StringOption()),
'handlers': ListOption(item=StringOption()),
})),
'root': DictOption(
spec={
'level': StringOption(),
'filters': ListOption(item=StringOption()),
'handlers': ListOption(item=StringOption()),
}),
'incremental': BoolOption(default=False),
'disable_existing_loggers': BoolOption(default=False),
},
default={
'version': 1,
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
},
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
},
'disable_existing_loggers': False,
},
help="The default logging configuration. This sends an email to "
"the site admins on every HTTP 500 error. All other records "
"are sent to the bit bucket.")
###############
# STATICFILES #
###############
staticfiles_dirs = ListOption(
item=StringOption(),
help='A list of locations of additional static files')
staticfiles_storage = StringOption(
default='django.contrib.staticfiles.storage.StaticFilesStorage',
help='The default file storage backend used during the build '
'process')
staticfiles_finders = ListOption(
item=StringOption(),
default=[
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
],
help='List of finder classes that know how to find static files '
'in various locations.')
admin_media_prefix = StringOption(default='/static/admin/',
help="URL prefix for admin media -- CSS, JavaScript and images. "
"Make sure to use a trailing slash. "
"Examples: 'htttp://foo.com/media/', '/media/'")
class Django136Schema(Django13Schema):
version = '1.3.6'
class django(Django13Schema.django):
allowed_hosts = ListOption(
item=StringOption(),
help="A list of strings representing the host/domain names "
"that this Django site can serve. This is a security "
"measure to prevent an attacker from poisoning caches and "
"password reset emails with links to malicious hosts by "
"submitting requests with a fake HTTP Host header, which is "
"possible even under many seemingly-safe webserver "
"configurations.")
Django14Base = derivate_django_schema(
Django13Schema,
exclude=[
'admin_media_prefix',
'ignorable_404_starts',
'ignorable_404_ends',
'banned_ips',
'comments_banned_users_group',
'comments_moderators_group',
'comments_sketchy_users_group',
'comments_first_few',
'database_engine',
'database_host',
'database_name',
'database_options',
'database_password',
'database_port',
'database_user',
'test_database_charset',
'test_database_collation',
'test_database_name',
])
class Django14Schema(Django14Base):
version = '1.4'
class django(Django14Base.django):
wsgi_application = StringOption(
help="The full Python path of the WSGI application object"
"that Django's built-in servers (e.g. runserver) will use.",
null=True)
csrf_cookie_secure = BoolOption(
default=False,
help='Whether to use a secure cookie for the CSRF '
'cookie. If this is set to True, the cookie will be marked '
'as "secure," which means browsers may ensure that the '
'cookie is only sent under an HTTPS connection.')
csrf_cookie_path = StringOption(
default='/',
help="The path set on the CSRF cookie. This should either "
"match the URL path of your Django installation or be a "
"parent of that path.")
secure_proxy_ssl_header = TupleOption(
length=2,
default=None,
help="A tuple representing a HTTP header/value combination "
"that signifies a request is secure. This controls the "
"behavior of the request object's is_secure() method.")
ignorable_404_urls = ListOption(
item=StringOption(),
help="List of compiled regular expression objects "
"describing URLs that should be ignored when reporting HTTP "
"404 errors via email (see Error reporting). Use this if "
"your site does not provide a commonly requested file such "
"as favicon.ico or robots.txt, or if it gets hammered by "
"script kiddies.")
password_hashers = ListOption(
item=StringOption(),
help="This is a list of hashing algorithm classes that this "
"Django installation supports. The first entry in this list "
"(that is, settings.PASSWORD_HASHERS[0]) will be used to "
"store passwords, and all the other entries are valid "
"hashers that can be used to check existing passwords.",
default=[
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]
)
x_frame_options = StringOption(
default='SAMEORIGIN',
help="The default value for the X-Frame-Options header used "
"by XFrameOptionsMiddleware.")
use_tz = BoolOption(
default=True,
help="A boolean that specifies if datetimes will be timezone-aware"
" by default or not. If this is set to True, Django will use "
"timezone-aware datetimes internally. Otherwise, Django will "
"use naive datetimes in local time.")
default_exception_reporter_filter = StringOption(
default='django.views.debug.SafeExceptionReporterFilter',
help="Default exception reporter filter class to be used if none "
"has been assigned to the HttpRequest instance yet.")
signing_backend = StringOption(
default='django.core.signing.TimestampSigner',
help="The backend used for signing cookies and other data.")
url_validator_user_agent = StringOption(
default=("Django/%s (https://www.djangoproject.com)" %
get_version()),
help="The User-Agent string to use when checking for URL validity "
"through the isExistingURL validator")
message_storage = StringOption(
default='django.contrib.messages.storage.fallback.'
'FallbackStorage',
help="Class to be used as messages backend")
logging = DictOption(
spec={
'version': IntOption(default=1),
'formatters': DictOption(
item=DictOption(
spec={
'format': StringOption(null=True),
'datefmt': StringOption(null=True)})),
'filters': DictOption(
item=DictOption(
spec={'name': StringOption()})),
'handlers': DictOption(
item=DictOption(
spec={
'class': StringOption(fatal=True),
'level': StringOption(),
'formatter': StringOption(),
'filters': StringOption()})),
'loggers': DictOption(
item=DictOption(
spec={
'level': StringOption(),
'propagate': BoolOption(),
'filters': ListOption(item=StringOption()),
'handlers': ListOption(item=StringOption()),
})),
'root': DictOption(
spec={
'level': StringOption(),
'filters': ListOption(item=StringOption()),
'handlers': ListOption(item=StringOption()),
}),
'incremental': BoolOption(default=False),
'disable_existing_loggers': BoolOption(default=False),
},
default={
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
},
help="The default logging configuration. This sends an email to "
"the site admins on every HTTP 500 error. All other records "
"are sent to the bit bucket.")
template_context_processors = ListOption(
item=StringOption(),
default=['django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
help="List of processors used by RequestContext to populate the "
"context. Each one should be a callable that takes the "
"request object as its only parameter and returns a "
"dictionary to add to the context")
languages = ListOption(
item=TupleOption(length=2),
default=[
('ar', gettext_noop('Arabic')),
('az', gettext_noop('Azerbaijani')),
('bg', gettext_noop('Bulgarian')),
('bn', gettext_noop('Bengali')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-gb', gettext_noop('British English')),
('eo', gettext_noop('Esperanto')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('es-mx', gettext_noop('Mexican Spanish')),
('es-ni', gettext_noop('Nicaraguan Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy-nl', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hu', gettext_noop('Hungarian')),
('id', gettext_noop('Indonesian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('kk', gettext_noop('Kazakh')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('nb', gettext_noop('Norwegian Bokmal')),
('ne', gettext_noop('Nepali')),
('nl', gettext_noop('Dutch')),
('nn', gettext_noop('Norwegian Nynorsk')),
('pa', gettext_noop('Punjabi')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('sw', gettext_noop('Swahili')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('tt', gettext_noop('Tatar')),
('uk', gettext_noop('Ukrainian')),
('ur', gettext_noop('Urdu')),
('vi', gettext_noop('Vietnamese')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese'))],
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language")
session_cookie_httponly = BoolOption(
default=True,
help="Whether to use the non-RFC standard htt pOnly flag (IE, "
"FF3+, others)")
datetime_input_formats = ListOption(
item=StringOption(),
default=[
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
'%Y-%m-%d %H:%M:%S.%f', # '2006-10-25 14:30:59.000200'
'%Y-%m-%d %H:%M', # '2006-10-25 14:30'
'%Y-%m-%d', # '2006-10-25'
'%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
'%m/%d/%Y %H:%M:%S.%f', # '10/25/2006 14:30:59.000200'
'%m/%d/%Y %H:%M', # '10/25/2006 14:30'
'%m/%d/%Y', # '10/25/2006'
'%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
'%m/%d/%y %H:%M:%S.%f', # '10/25/06 14:30:59.000200'
'%m/%d/%y %H:%M', # '10/25/06 14:30'
'%m/%d/%y', # '10/25/06'
],
help="Default formats to be used when parsing dates and times "
"from input boxes, in order")
class Django144Schema(Django14Schema):
version = '1.4.4'
class django(Django14Schema.django):
allowed_hosts = ListOption(
help="A list of strings representing the host/domain names "
"that this Django site can serve. This is a security "
"measure to prevent an attacker from poisoning caches and "
"password reset emails with links to malicious hosts by "
"submitting requests with a fake HTTP Host header, which is "
"possible even under many seemingly-safe webserver "
"configurations.")
languages = ListOption(
item=TupleOption(length=2),
default=[
('af', gettext_noop('Afrikaans')),
('ar', gettext_noop('Arabic')),
('az', gettext_noop('Azerbaijani')),
('bg', gettext_noop('Bulgarian')),
('be', gettext_noop('Belarusian')),
('bn', gettext_noop('Bengali')),
('br', gettext_noop('Breton')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-gb', gettext_noop('British English')),
('eo', gettext_noop('Esperanto')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('es-mx', gettext_noop('Mexican Spanish')),
('es-ni', gettext_noop('Nicaraguan Spanish')),
('es-ve', gettext_noop('Venezuelan Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy-nl', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hu', gettext_noop('Hungarian')),
('ia', gettext_noop('Interlingua')),
('id', gettext_noop('Indonesian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('kk', gettext_noop('Kazakh')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lb', gettext_noop('Luxembourgish')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('nb', gettext_noop('Norwegian Bokmal')),
('ne', gettext_noop('Nepali')),
('nl', gettext_noop('Dutch')),
('nn', gettext_noop('Norwegian Nynorsk')),
('pa', gettext_noop('Punjabi')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('sw', gettext_noop('Swahili')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('tt', gettext_noop('Tatar')),
('udm', gettext_noop('Udmurt')),
('uk', gettext_noop('Ukrainian')),
('ur', gettext_noop('Urdu')),
('vi', gettext_noop('Vietnamese')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),],
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language")
class Django145Schema(Django144Schema):
version = '1.4.5'
class django(Django144Schema.django):
languages = ListOption(
item=TupleOption(length=2),
default=[
('ar', gettext_noop('Arabic')),
('az', gettext_noop('Azerbaijani')),
('bg', gettext_noop('Bulgarian')),
('bn', gettext_noop('Bengali')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-gb', gettext_noop('British English')),
('eo', gettext_noop('Esperanto')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('es-mx', gettext_noop('Mexican Spanish')),
('es-ni', gettext_noop('Nicaraguan Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy-nl', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hu', gettext_noop('Hungarian')),
('id', gettext_noop('Indonesian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('kk', gettext_noop('Kazakh')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('nb', gettext_noop('Norwegian Bokmal')),
('ne', gettext_noop('Nepali')),
('nl', gettext_noop('Dutch')),
('nn', gettext_noop('Norwegian Nynorsk')),
('pa', gettext_noop('Punjabi')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('sw', gettext_noop('Swahili')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('tt', gettext_noop('Tatar')),
('uk', gettext_noop('Ukrainian')),
('ur', gettext_noop('Urdu')),
('vi', gettext_noop('Vietnamese')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),],
help="Languages we provide translations for, out of the box. "
"The language name should be the utf-8 encoded local name "
"for the language")
Django15Base = derivate_django_schema(
Django145Schema,
exclude=[
'url_validator_user_agent',
])
class Django15Schema(Django15Base):
version = '1.5'
class django(Django15Base.django):
caches = DictOption(
item=UpperCaseDictOption(
spec={
'backend': StringOption(),
'location': StringOption()
}),
default={
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
})
auth_user_model = StringOption(
default='auth.User',
help="The model to use to represent a User.")
session_cache_alias = StringOption(
default='default',
help="If you're using cache-based session storage, this selects "
" the cache to use.")
password_hashers = ListOption(
item=StringOption(),
help="This is a list of hashing algorithm classes that this "
"Django installation supports. The first entry in this list "
"(that is, settings.PASSWORD_HASHERS[0]) will be used to "
"store passwords, and all the other entries are valid "
"hashers that can be used to check existing passwords.",
default=[
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
])
class Django153Schema(Django15Schema):
version = '1.5.3'
class django(Django15Schema.django):
# XXX: even though the Django documentation says PickleSerializer is
# the default value, it's not the case with a vanilla 1.5.3 project
session_serializer = StringOption(
default='django.contrib.sessions.serializers.JSONSerializer',
help="Full import path of a serializer class to use for "
"serializing session data.")
Django16Base = derivate_django_schema(
Django153Schema)
class Django16Schema(Django16Base):
version = '1.6'
class django(Django16Base.django):
base_dir = StringOption(
help="Used by the example project to help build paths for other "
"settings variables.")
databases = DictOption(
item=UpperCaseDictOption(spec={
'engine': StringOption(default='django.db.backends.'),
'name': StringOption(),
'user': StringOption(),
'password': StringOption(),
'host': StringOption(),
'port': StringOption(),
'atomic_requests': BoolOption(default=False),
'autocommit': BoolOption(default=True),
'conn_max_age': IntOption(default=0),
}),
default={
'default': {
'ENGINE': 'django.db.backends.',
'NAME': '',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
})
csrf_cookie_httponly = BoolOption(
default=False,
help="Whether to use HttpOnly flag on the CSRF cookie. If this "
"is set to True, client-side JavaScript will not to be able "
"to access the CSRF cookie. See SESSION_COOKIE_HTTPONLY for "
"details on HttpOnly.")
session_serializer = StringOption(
default='django.contrib.sessions.serializers.JSONSerializer',
help="Full import path of a serializer class to use for "
"serializing session data.")
class DjangoSchemaFactory(object):
def __init__(self):
self._schemas = {}
def register(self, schema_cls, version=None):
if version is None:
# fall back to looking the version of the schema class
version = getattr(schema_cls, 'version', None)
if version is None:
raise ValueError(
"No version was specified nor found in schema %r" % schema_cls)
self._schemas[version] = schema_cls
def get(self, version, strict=True):
if version in self._schemas:
return self._schemas[version]
msg = "No schema registered for version %r" % version
if strict:
raise ValueError(msg)
else:
logging.warn(msg)
logging.warn("Dynamically creating schema for version %r" % version)
schema = self.build(version)
return schema
def build(self, version_string=None, options=None,
BaseSchema=BaseDjangoSchema):
if version_string is None:
version_string = get_version()
if options is None:
project_settings = get_project_settings()
options = dict([(name.lower(), value) for (name, value) in
inspect.getmembers(global_settings) if name.isupper()])
project_options = dict([(name.lower(), value) for (name, value) in
inspect.getmembers(project_settings) if name.isupper()])
# handle special case of ROOT_URLCONF which depends on the
# project name
root_urlconf = project_options['root_urlconf'].replace(
'{{ project_name }}.', '')
project_options['root_urlconf'] = root_urlconf
options.update(project_options)
try:
base_version = '{0}.{1}'.format(*VERSION[:2])
BaseSchema = self.get(base_version)
except ValueError:
pass
section_base_class = getattr(BaseSchema, 'django', Section)
class DjangoSchema(BaseSchema):
version = version_string
class django(section_base_class):
pass
def get_option_type(name, value):
type_mappings = {
int: IntOption,
bool: BoolOption,
list: ListOption,
tuple: TupleOption,
dict: DictOption,
str: StringOption,
unicode: StringOption,
}
if value is None:
# Special casing strange value, which by default is None but
# should be set to tuple.
if name == 'secure_proxy_ssl_header':
return TupleOption(name=name, default=None)
return StringOption(name=name, default=value, null=True)
else:
# Clean up values comming from the project template and having
# {{ }} substitutions in them.
if name in ('secret_key', 'wsgi_application'):
value = ''
option_type = type_mappings[type(value)]
kwargs = {'name': name, 'default': value}
if option_type in (DictOption, ListOption):
# get inner item type
if option_type == DictOption:
items = value.values()
else:
items = value
item_type = None
if items:
item_type = type_mappings.get(type(items[0]), None)
# make sure all items have a consistent type
for item in items:
current_item_type = type_mappings.get(
type(item), None)
if current_item_type != item_type:
item_type = None
# mismatching types found. fallback to default
# item type
break
if item_type is not None:
kwargs['item'] = item_type()
return option_type(**kwargs)
for name, value in options.items():
if name == '__CONFIGGLUE_PARSER__':
continue
if not hasattr(DjangoSchema.django, name):
option = get_option_type(name, value)
setattr(DjangoSchema.django, name, option)
# register schema for it to be available during next query
self.register(DjangoSchema, version_string)
return DjangoSchema
schemas = DjangoSchemaFactory()
schemas.register(BaseDjangoSchema)
schemas.register(Django13Schema)
schemas.register(Django136Schema)
schemas.register(Django136Schema, '1.3.7')
schemas.register(Django14Schema)
schemas.register(Django144Schema)
schemas.register(Django145Schema)
schemas.register(Django145Schema, '1.4.8')
schemas.register(Django15Schema)
schemas.register(Django15Schema, '1.5.1')
schemas.register(Django15Schema, '1.5.2')
schemas.register(Django153Schema)
schemas.register(Django153Schema, '1.5.4')
schemas.register(Django16Schema)
django-configglue-0.7.1/testproject/ 0000755 0001750 0001750 00000000000 12236762416 020550 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/testproject/manage.py 0000775 0001750 0001750 00000001036 12136764467 022366 0 ustar ricardo ricardo 0000000 0000000 #!/usr/bin/python
from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)
django-configglue-0.7.1/testproject/testrunner.py 0000664 0001750 0001750 00000000643 12136764467 023347 0 ustar ricardo ricardo 0000000 0000000 #This file mainly exists to allow python setup.py test to work.
import os
import sys
def runtests():
curdir = os.getcwd()
testproject = os.path.join(curdir, 'testproject')
os.chdir(testproject)
sys.path.append(curdir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings'
from django.core.management import call_command
call_command('test', 'django_configglue')
sys.exit(0)
django-configglue-0.7.1/testproject/main-13.cfg 0000664 0001750 0001750 00000000246 12136764467 022411 0 ustar ricardo ricardo 0000000 0000000 [django]
installed_apps = django_configglue
databases = databases
[databases]
default = db_default
[db_default]
engine = django.db.backends.sqlite3
name = :memory:
django-configglue-0.7.1/testproject/__init__.py 0000664 0001750 0001750 00000000000 12136764467 022660 0 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/testproject/main-14.cfg 0000664 0001750 0001750 00000000246 12136764467 022412 0 ustar ricardo ricardo 0000000 0000000 [django]
installed_apps = django_configglue
databases = databases
[databases]
default = db_default
[db_default]
engine = django.db.backends.sqlite3
name = :memory:
django-configglue-0.7.1/testproject/main-15.cfg 0000664 0001750 0001750 00000000303 12145240264 022365 0 ustar ricardo ricardo 0000000 0000000 [django]
installed_apps = django_configglue
databases = databases
secret_key = very-secret-key
[databases]
default = db_default
[db_default]
engine = django.db.backends.sqlite3
name = :memory:
django-configglue-0.7.1/testproject/settings.py 0000777 0001750 0001750 00000000000 12136764467 032221 2../django_configglue/tests/settings.py ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/testproject/main.cfg 0000664 0001750 0001750 00000000054 12136764467 022165 0 ustar ricardo ricardo 0000000 0000000 [django]
installed_apps = django_configglue
django-configglue-0.7.1/setup.cfg 0000644 0001750 0001750 00000000073 12236762416 020023 0 ustar ricardo ricardo 0000000 0000000 [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
django-configglue-0.7.1/PKG-INFO 0000644 0001750 0001750 00000002253 12236762416 017301 0 ustar ricardo ricardo 0000000 0000000 Metadata-Version: 1.1
Name: django-configglue
Version: 0.7.1
Summary: Django commands for managing configglue generated settings
Home-page: https://launchpad.net/django-configglue/
Author: Ricardo Kirkner
Author-email: ricardo.kirkner@canonical.com
License: LGPLv3
Description: Django commands for managing configglue generated settings from the command line.
Commands are available to:
- get the value of a setting
- list all settings used (and their values)
- list all settings used, including django global settings (and
their values)
- locate the definition of a setting (useful when the configuration
is defined throughout several files)
- validate settings (make sure the values match the defined schema)
Keywords: django,configglue,configuration,settings
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
Classifier: Programming Language :: Python
Classifier: Topic :: Utilities
django-configglue-0.7.1/setup_helpers.py 0000664 0001750 0001750 00000003061 12136764467 021447 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
# Copyright 2009-2011 by Barry A. Warsaw
import re
DEFAULT_VERSION_RE = re.compile(r'(?P\d+\.\d(?:\.\d+)?)')
def get_version(filename, pattern=None):
"""Extract the __version__ from a file without importing it.
While you could get the __version__ by importing the module, the very act
of importing can cause unintended consequences. For example, Distribute's
automatic 2to3 support will break. Instead, this searches the file for a
line that starts with __version__, and extract the version number by
regular expression matching.
By default, two or three dot-separated digits are recognized, but by
passing a pattern parameter, you can recognize just about anything. Use
the `version` group name to specify the match group.
:param filename: The name of the file to search.
:type filename: string
:param pattern: Optional alternative regular expression pattern to use.
:type pattern: string
:return: The version that was extracted.
:rtype: string
"""
if pattern is None:
cre = DEFAULT_VERSION_RE
else:
cre = re.compile(pattern)
with open(filename) as fp:
for line in fp:
if line.startswith('__version__'):
mo = cre.search(line)
assert mo, 'No valid __version__ string found'
return mo.group('version')
raise AssertionError('No __version__ assignment found')
django-configglue-0.7.1/README.txt 0000664 0001750 0001750 00000000757 12136764467 017722 0 ustar ricardo ricardo 0000000 0000000 Running tests
=============
django_configglue is a normal django application, so running the tests
should be as easy as running ::
cd testproject
PYTHONPATH=.. python manage.py test django_configglue
As a shortcut, you can also run ::
python setup.py test
.. note:: django-configglue has only been tested with Python 2.6 but should
work on Python 2.4+.
Getting started
===============
For documentation on django-configglue, please refer to the files found under
the ``doc`` folder.
django-configglue-0.7.1/MANIFEST.in 0000664 0001750 0001750 00000000114 12136764467 017745 0 ustar ricardo ricardo 0000000 0000000 include *.py *.txt
graft testproject
graft third-party
global-exclude *.pyc
django-configglue-0.7.1/django_configglue.egg-info/ 0000755 0001750 0001750 00000000000 12236762416 023340 5 ustar ricardo ricardo 0000000 0000000 django-configglue-0.7.1/django_configglue.egg-info/top_level.txt 0000664 0001750 0001750 00000000022 12236762415 026065 0 ustar ricardo ricardo 0000000 0000000 django_configglue
django-configglue-0.7.1/django_configglue.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12236762415 027407 0 ustar ricardo ricardo 0000000 0000000
django-configglue-0.7.1/django_configglue.egg-info/PKG-INFO 0000664 0001750 0001750 00000002253 12236762415 024440 0 ustar ricardo ricardo 0000000 0000000 Metadata-Version: 1.1
Name: django-configglue
Version: 0.7.1
Summary: Django commands for managing configglue generated settings
Home-page: https://launchpad.net/django-configglue/
Author: Ricardo Kirkner
Author-email: ricardo.kirkner@canonical.com
License: LGPLv3
Description: Django commands for managing configglue generated settings from the command line.
Commands are available to:
- get the value of a setting
- list all settings used (and their values)
- list all settings used, including django global settings (and
their values)
- locate the definition of a setting (useful when the configuration
is defined throughout several files)
- validate settings (make sure the values match the defined schema)
Keywords: django,configglue,configuration,settings
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
Classifier: Programming Language :: Python
Classifier: Topic :: Utilities
django-configglue-0.7.1/django_configglue.egg-info/SOURCES.txt 0000664 0001750 0001750 00000001704 12236762416 025230 0 ustar ricardo ricardo 0000000 0000000 LICENSE.txt
MANIFEST.in
README.txt
setup.py
setup_helpers.py
django_configglue/__init__.py
django_configglue/models.py
django_configglue/schema.py
django_configglue/utils.py
django_configglue.egg-info/PKG-INFO
django_configglue.egg-info/SOURCES.txt
django_configglue.egg-info/dependency_links.txt
django_configglue.egg-info/requires.txt
django_configglue.egg-info/top_level.txt
django_configglue/management/__init__.py
django_configglue/management/commands/__init__.py
django_configglue/management/commands/settings.py
django_configglue/tests/__init__.py
django_configglue/tests/helpers.py
django_configglue/tests/settings.py
django_configglue/tests/test_configglue.py
django_configglue/tests/test_schema.py
django_configglue/tests/test_settings.py
testproject/__init__.py
testproject/main-13.cfg
testproject/main-14.cfg
testproject/main-15.cfg
testproject/main.cfg
testproject/manage.py
testproject/settings.py
testproject/testrunner.py
third-party/django/LICENSE django-configglue-0.7.1/django_configglue.egg-info/requires.txt 0000664 0001750 0001750 00000000041 12236762415 025734 0 ustar ricardo ricardo 0000000 0000000 django >= 1.3.7
configglue >= 1.0 django-configglue-0.7.1/setup.py 0000664 0001750 0001750 00000003414 12136764467 017727 0 ustar ricardo ricardo 0000000 0000000 # Copyright 2010-2011 Canonical Ltd. This software is licensed under the
# GNU Lesser General Public License version 3 (see the file LICENSE).
from setuptools import setup, find_packages
from setup_helpers import get_version
setup(
# metadata
name='django-configglue',
version=get_version('django_configglue/__init__.py'),
author='Ricardo Kirkner',
author_email='ricardo.kirkner@canonical.com',
description='Django commands for managing configglue generated settings',
long_description='Django commands for managing configglue generated '
'settings from the command line.\n'
'Commands are available to:\n'
' - get the value of a setting\n'
' - list all settings used (and their values)\n'
' - list all settings used, including django global settings (and\n'
' their values)\n'
' - locate the definition of a setting (useful when the configuration\n'
' is defined throughout several files)\n'
' - validate settings (make sure the values match the defined schema)',
license='LGPLv3',
keywords = ['django', 'configglue', 'configuration', 'settings'],
url = 'https://launchpad.net/django-configglue/',
classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
'Programming Language :: Python',
'Topic :: Utilities',
],
# content
packages=find_packages(exclude=['testproject*']),
install_requires=['django >= 1.3.7', 'configglue >= 1.0'],
# tests
test_suite='testproject.testrunner.runtests',
tests_require=['mock'],
)