django-configglue-0.7.1/0000755000175000017500000000000012236762416016202 5ustar ricardoricardo00000000000000django-configglue-0.7.1/LICENSE.txt0000664000175000017500000001770112136764467020044 0ustar ricardoricardo00000000000000django-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/0000755000175000017500000000000012236762416020451 5ustar ricardoricardo00000000000000django-configglue-0.7.1/third-party/django/0000755000175000017500000000000012236762416021713 5ustar ricardoricardo00000000000000django-configglue-0.7.1/third-party/django/LICENSE0000664000175000017500000000302612136764467022732 0ustar ricardoricardo00000000000000Copyright (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/0000755000175000017500000000000012236762416021646 5ustar ricardoricardo00000000000000django-configglue-0.7.1/django_configglue/management/0000755000175000017500000000000012236762416023762 5ustar ricardoricardo00000000000000django-configglue-0.7.1/django_configglue/management/__init__.py0000664000175000017500000000626412145240342026071 0ustar ricardoricardo00000000000000# 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/0000755000175000017500000000000012236762416025563 5ustar ricardoricardo00000000000000django-configglue-0.7.1/django_configglue/management/commands/__init__.py0000664000175000017500000000022012136764467027677 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000001245012136764467030010 0ustar ricardoricardo00000000000000# 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/0000755000175000017500000000000012236762416023010 5ustar ricardoricardo00000000000000django-configglue-0.7.1/django_configglue/tests/test_settings.py0000664000175000017500000002107512236751653026271 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000001510212136764467025034 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000004005412145240342026534 0ustar ricardoricardo00000000000000# -*- 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__.py0000664000175000017500000000044112136764467025131 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000000111012136764467025224 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000000143012145240360025645 0ustar ricardoricardo00000000000000import 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.py0000664000175000017500000000422112136764467023370 0ustar ricardoricardo00000000000000# 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__.py0000664000175000017500000000035412236761734023765 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000000022012136764467023506 0ustar ricardoricardo00000000000000# 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.py0000664000175000017500000023722212236761665023477 0ustar ricardoricardo00000000000000# 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/0000755000175000017500000000000012236762416020550 5ustar ricardoricardo00000000000000django-configglue-0.7.1/testproject/manage.py0000775000175000017500000000103612136764467022366 0ustar ricardoricardo00000000000000#!/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.py0000664000175000017500000000064312136764467023347 0ustar ricardoricardo00000000000000#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.cfg0000664000175000017500000000024612136764467022411 0ustar ricardoricardo00000000000000[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__.py0000664000175000017500000000000012136764467022660 0ustar ricardoricardo00000000000000django-configglue-0.7.1/testproject/main-14.cfg0000664000175000017500000000024612136764467022412 0ustar ricardoricardo00000000000000[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.cfg0000664000175000017500000000030312145240264022365 0ustar ricardoricardo00000000000000[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.py0000777000175000017500000000000012136764467032221 2../django_configglue/tests/settings.pyustar ricardoricardo00000000000000django-configglue-0.7.1/testproject/main.cfg0000664000175000017500000000005412136764467022165 0ustar ricardoricardo00000000000000[django] installed_apps = django_configglue django-configglue-0.7.1/setup.cfg0000644000175000017500000000007312236762416020023 0ustar ricardoricardo00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 django-configglue-0.7.1/PKG-INFO0000644000175000017500000000225312236762416017301 0ustar ricardoricardo00000000000000Metadata-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.py0000664000175000017500000000306112136764467021447 0ustar ricardoricardo00000000000000# 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.txt0000664000175000017500000000075712136764467017722 0ustar ricardoricardo00000000000000Running 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.in0000664000175000017500000000011412136764467017745 0ustar ricardoricardo00000000000000include *.py *.txt graft testproject graft third-party global-exclude *.pyc django-configglue-0.7.1/django_configglue.egg-info/0000755000175000017500000000000012236762416023340 5ustar ricardoricardo00000000000000django-configglue-0.7.1/django_configglue.egg-info/top_level.txt0000664000175000017500000000002212236762415026065 0ustar ricardoricardo00000000000000django_configglue django-configglue-0.7.1/django_configglue.egg-info/dependency_links.txt0000664000175000017500000000000112236762415027407 0ustar ricardoricardo00000000000000 django-configglue-0.7.1/django_configglue.egg-info/PKG-INFO0000664000175000017500000000225312236762415024440 0ustar ricardoricardo00000000000000Metadata-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.txt0000664000175000017500000000170412236762416025230 0ustar ricardoricardo00000000000000LICENSE.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/LICENSEdjango-configglue-0.7.1/django_configglue.egg-info/requires.txt0000664000175000017500000000004112236762415025734 0ustar ricardoricardo00000000000000django >= 1.3.7 configglue >= 1.0django-configglue-0.7.1/setup.py0000664000175000017500000000341412136764467017727 0ustar ricardoricardo00000000000000# 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'], )