django-configglue-0.6/0000755000175000017500000000000011617055055014576 5ustar ricardoricardodjango-configglue-0.6/PKG-INFO0000644000175000017500000000225111617055055015673 0ustar ricardoricardoMetadata-Version: 1.0 Name: django-configglue Version: 0.6 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.6/README.txt0000644000175000017500000000075711617033273016303 0ustar ricardoricardoRunning 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.6/LICENSE.txt0000644000175000017500000001770111617033273016425 0ustar ricardoricardodjango-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.6/setup_helpers.py0000644000175000017500000000306111617033273020030 0ustar ricardoricardo# 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.6/setup.cfg0000644000175000017500000000007311617055055016417 0ustar ricardoricardo[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 django-configglue-0.6/MANIFEST.in0000644000175000017500000000011411617033273016326 0ustar ricardoricardoinclude *.py *.txt graft testproject graft third-party global-exclude *.pyc django-configglue-0.6/third-party/0000755000175000017500000000000011617055055017045 5ustar ricardoricardodjango-configglue-0.6/third-party/django/0000755000175000017500000000000011617055055020307 5ustar ricardoricardodjango-configglue-0.6/third-party/django/LICENSE0000644000175000017500000000302611617033273021313 0ustar ricardoricardoCopyright (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.6/testproject/0000755000175000017500000000000011617055055017144 5ustar ricardoricardodjango-configglue-0.6/testproject/testrunner.py0000644000175000017500000000064311617033273021730 0ustar ricardoricardo#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.6/testproject/main-13.cfg0000644000175000017500000000024611617033273020772 0ustar ricardoricardo[django] installed_apps = django_configglue databases = databases [databases] default = db_default [db_default] engine = django.db.backends.sqlite3 name = :memory: django-configglue-0.6/testproject/main-12.cfg0000644000175000017500000000030611617033273020766 0ustar ricardoricardo[django] database_engine = sqlite3 database_name = :memory: installed_apps = django_configglue databases = databases [databases] default = db_default [db_default] engine = sqlite3 name = :memory: django-configglue-0.6/testproject/main.cfg0000644000175000017500000000013711617033273020550 0ustar ricardoricardo[django] database_engine = sqlite3 database_name = :memory: installed_apps = django_configglue django-configglue-0.6/testproject/settings.py0000777000175000017500000000000011617033273030604 2../django_configglue/tests/settings.pyustar ricardoricardodjango-configglue-0.6/testproject/manage.py0000755000175000017500000000103611617033273020747 0ustar ricardoricardo#!/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.6/testproject/__init__.py0000644000175000017500000000000011617033273021241 0ustar ricardoricardodjango-configglue-0.6/setup.py0000644000175000017500000000342211617033273016307 0ustar ricardoricardo# 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.0.2-final', 'configglue >= 1.0'], # tests test_suite='testproject.testrunner.runtests', tests_require=['mock'], ) django-configglue-0.6/django_configglue/0000755000175000017500000000000011617055055020242 5ustar ricardoricardodjango-configglue-0.6/django_configglue/models.py0000644000175000017500000000022011617033273022067 0ustar ricardoricardo# 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.6/django_configglue/management/0000755000175000017500000000000011617055055022356 5ustar ricardoricardodjango-configglue-0.6/django_configglue/management/commands/0000755000175000017500000000000011617055055024157 5ustar ricardoricardodjango-configglue-0.6/django_configglue/management/commands/settings.py0000644000175000017500000001245011617033273026371 0ustar ricardoricardo# 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.6/django_configglue/management/commands/__init__.py0000644000175000017500000000022011617033273026260 0ustar ricardoricardo# 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.6/django_configglue/management/__init__.py0000644000175000017500000000611611617033273024471 0ustar ricardoricardo# 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. import sys import django import django.core.management from configglue.glue import schemaconfigglue from django.core.management import ManagementUtility, LaxOptionParser from django.core.management.base import BaseCommand, handle_default_options from django.conf import settings from django_configglue import utils class GlueManagementUtility(ManagementUtility): # This function was mostly taken from the django project. # Please see the license file in the third-party/django directory. def execute(self): """ Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. """ # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = LaxOptionParser(usage="%prog subcommand [options] [args]", version=django.get_version(), option_list=BaseCommand.option_list) try: configglue_parser = settings.__CONFIGGLUE_PARSER__ parser, options, args = schemaconfigglue(configglue_parser, op=parser, argv=self.argv) # remove schema-related options from the argv list self.argv = args utils.update_settings(configglue_parser, settings) except AttributeError: # no __CONFIGGLUE_PARSER__ found, fall back to standard django # options parsing options, args = parser.parse_args(self.argv) handle_default_options(options) except: # Ignore any option errors at this point. args = self.argv try: subcommand = self.argv[1] except IndexError: sys.stderr.write("Type '%s help' for usage.\n" % self.prog_name) sys.exit(1) if subcommand == 'help': if len(args) > 2: self.fetch_command(args[2]).print_help(self.prog_name, args[2]) else: parser.print_lax_help() sys.stderr.write(self.main_help_text() + '\n') sys.exit(1) # Special-cases: We want 'django-admin.py --version' and # 'django-admin.py --help' to work, for backwards compatibility. elif self.argv[1:] == ['--version']: # LaxOptionParser already takes care of printing the version. pass elif self.argv[1:] == ['--help']: parser.print_lax_help() sys.stderr.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv) # We're going to go ahead and use our own ManagementUtility here, thank you. django.core.management.ManagementUtility = GlueManagementUtility django-configglue-0.6/django_configglue/tests/0000755000175000017500000000000011617055055021404 5ustar ricardoricardodjango-configglue-0.6/django_configglue/tests/test_configglue.py0000644000175000017500000003060011617051501025126 0ustar ricardoricardo# -*- 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 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 django.conf.project_template import settings as project_settings from mock import patch from django_configglue.management import GlueManagementUtility from django_configglue.utils import ( SETTINGS_ENCODING, configglue, get_django_settings, update_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.2 final', strict=True), BaseDjangoSchema) # test get invalid version self.assertRaises(ValueError, schemas.get, '1.1', strict=True) def test_schema_versions(self): django_102 = schemas.get('1.0.2 final')() django_112 = schemas.get('1.1.2')() self.assertEqual(django_102.version, '1.0.2 final') self.assertEqual(django_112.version, '1.1.2') self.assertFalse(django_102 is django_112) 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 opt_type, default in data: schema_cls = schemas.build('bogus', {'foo': default}) # do common checks self.assert_schema_structure(schema_cls, 'bogus', {'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(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) class GlueManagementUtilityTestCase(ConfigGlueDjangoCommandTestCase): def setUp(self): super(GlueManagementUtilityTestCase, self).setUp() self.util = GlueManagementUtility() def execute(self): self.begin_capture() try: self.util.execute() finally: self.end_capture() def test_execute_no_args(self): self.util.argv = [''] self.assertRaises(SystemExit, self.execute) self.assertEqual(self.capture['stderr'], "Type '%s help' for usage.\n" % self.util.prog_name) def test_execute_help(self): self.util.argv = ['', 'help'] self.assertRaises(SystemExit, self.execute) self.assertTrue(self.util.main_help_text() in self.capture['stderr']) def test_execute_help_option(self): self.util.argv = ['', '--help'] self.execute() self.assertTrue(self.util.main_help_text() in self.capture['stderr']) def test_execute_help_for_command(self): self.util.argv = ['', 'help', 'settings'] self.execute() self.assertTrue('Show settings attributes' in self.capture['stdout']) def test_execute_version(self): from django import get_version self.util.argv = ['', '--version'] self.execute() self.assertTrue(get_version() in self.capture['stdout']) def test_execute(self): self.util.argv = ['', 'settings'] self.execute() self.assertTrue('Show settings attributes' in self.capture['stdout']) def test_execute_settings_exception(self): 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'] self.assertRaises(SystemExit, self.execute) self.assertTrue( self.util.main_help_text() in self.capture['stderr']) finally: wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER @patch('django_configglue.utils.update_settings') def test_execute_configglue_exception(self, mock_update_settings): mock_update_settings.side_effect = Exception() self.util.argv = ['', 'help'] self.assertRaises(SystemExit, self.execute) self.assertTrue(self.util.main_help_text() in self.capture['stderr']) def test_execute_with_schema_options(self): self.util.argv = ['', '--django_debug=False', 'help', 'settings'] self.execute() self.assertTrue('Show settings attributes' in self.capture['stdout']) 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'}) django-configglue-0.6/django_configglue/tests/test_settings.py0000644000175000017500000002053411617051501024651 0ustar ricardoricardoimport pdb # 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 ManagementUtility from mock import patch, Mock 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.capture['stdout'].startswith('Usage: ')) def test_get(self): self.call_command('installed_apps') expected_output = "INSTALLED_APPS = ['django_configglue']" self.assertEqual(self.capture['stdout'].strip(), expected_output) def test_get_not_found(self): self.call_command('bogus') expected_output = "setting BOGUS not found" self.assertEqual(self.capture['stdout'].strip(), expected_output) def test_show(self): expected_values = [ "ROOT_URLCONF = 'urls'", "SITE_ID = 1", "SETTINGS_MODULE = 'django_configglue.tests.settings'", "SETTINGS_ENCODING = '%s'" % SETTINGS_ENCODING, ] django_version = django.VERSION[:2] if django_version == (1, 1): expected_values.append("DATABASE_SUPPORTS_TRANSACTIONS = True") self.call_command(show_current=True) output_lines = self.capture['stdout'].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.capture['stdout'].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.capture['stdout'].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.capture['stdout'].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.capture['stdout'].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.capture['stdout'].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): self.expected_schema = schemas.get( django.get_version(), strict=True)() mock_get_version = Mock(return_value='foo') 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() super(GeneratedSettingsTestCase, self).setUp() 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 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 'foo'",), {}), (("Dynamically creating schema for version 'foo'",), {})]) class ValidateCommandTestCase(ConfigGlueDjangoCommandTestCase): COMMAND = 'settings' def test_valid_config(self): self.call_command(validate=True) expected_output = 'Settings appear to be fine.' self.assertEqual(self.capture['stdout'].strip(), expected_output) def test_invalid_config(self): config = """ [bogus] invalid_setting = foo """ self.set_config(config) self.load_settings() self.assertRaises(SystemExit, self.call_command, validate=True) try: self.call_command(validate=True) except SystemExit, e: self.assertEqual(e.code, 1) error_msg = 'Error: Settings did not validate against schema.' self.assertTrue(self.capture['stderr'].strip().startswith( error_msg)) 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.capture['stdout'].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.capture['stdout']) def test_update_settings(self): self.assertTrue(settings.DEBUG) args = ['manage.py', 'settings', '--django_debug=False', 'DEBUG'] utility = ManagementUtility(argv=args) self.begin_capture() try: utility.execute() finally: self.end_capture() self.assertTrue('False' in self.capture['stdout']) def test_version_is_printed_once(self): args = ['manage.py', '--version'] utility = ManagementUtility(argv=args) self.begin_capture() try: utility.execute() finally: self.end_capture() expected = get_version() self.assertTrue(self.capture['stdout'].count(expected) == 1) def test_noargs_doesnt_error(self): args = ['manage.py'] utility = ManagementUtility(argv=args) self.begin_capture() try: self.assertRaises(SystemExit, utility.execute) finally: self.end_capture() self.assertFalse('Unknown command' in self.capture['stdout']) django-configglue-0.6/django_configglue/tests/settings.py0000644000175000017500000000102411617033273023611 0ustar ricardoricardo# 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.3': main_cfg = 'main-13.cfg' elif version >= '1.2': main_cfg = 'main-12.cfg' configglue(DjangoSchema, [main_cfg, 'test.cfg'], __name__) django-configglue-0.6/django_configglue/tests/helpers.py0000644000175000017500000001435311617033273023424 0ustar ricardoricardo# 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 from configglue.schema import ( ListOption, TupleOption, Schema, ) class ConfigGlueDjangoCommandTestCase(TestCase): COMMAND = '' def setUp(self): # disable logging during tests self.level = logging.getLogger().level logging.disable(logging.ERROR) config = textwrap.dedent(""" [django] database_engine = sqlite3 database_name = :memory: installed_apps = django_configglue time_zone = Europe/London """) if django.VERSION[:2] > (1, 1): # since 1.2 use multi database settings format config += textwrap.dedent(""" databases = databases [databases] default = db_default [db_default] engine = 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') def set_config(self, config): config_file = open('test.cfg', 'w') config_file.write(config) config_file.close() @property def wrapped_settings(self): wrapped = '_target' if django.VERSION[:3] > (1, 0, 2): wrapped = '_wrapped' # make sure the wrapped object is not None # by just querying it for a setting getattr(settings, 'DEBUG', False) assert(getattr(settings, wrapped) != None) 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'), } # force django to reload its settings setattr(settings, self.wrapped_settings, None) # 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) 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.capture = {'stdout': sys.stdout.read(), 'stderr': 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): # disable logging during tests self.level = logging.getLogger().level logging.disable(logging.ERROR) def tearDown(self): # re-enable logging logging.getLogger().setLevel(self.level) def assert_schema_structure(self, schema_cls, version, options): self.assertTrue(issubclass(schema_cls, Schema)) self.assertEqual(schema_cls.version, 'bogus') 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))): self.assertEqual(list(option.default), list(expected_option.default)) else: self.assertEqual(option.default, expected_option.default) django-configglue-0.6/django_configglue/tests/__init__.py0000644000175000017500000000040711617033273023514 0ustar ricardoricardo# 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 * django-configglue-0.6/django_configglue/schema.py0000644000175000017500000014464311617051501022060 0ustar ricardoricardo# 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 from django.conf import global_settings from django.conf.project_template import settings as 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.2 final' # 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', 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") 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") ################## # 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') Django112Base = derivate_django_schema( BaseDjangoSchema, exclude=['jing_path']) class Django112Schema(Django112Base): version = '1.1.2' # sections class django(Django112Base.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 Django125Schema(Django112Schema): version = '1.2.5' # sections class django(Django112Schema.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(), }), default={ 'default': { 'ENGINE': 'django.db.backends.', 'NAME': '', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } }) 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', ]) 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( Django125Schema, exclude=['cache_backend']) class Django13Schema(Django13Base): version = '1.3' # sections class django(Django13Base.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')), ('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() 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") ########### # LOGGING # ########### logging_config = StringOption( default='django.utils.log.dictConfig', help='The callable to use to configure logging') logging = DictOption( spec={ 'version': IntOption(default=1), 'disable_existing_loggers': BoolOption(default=False), 'handlers': DictOption(spec={ 'mail_admins': DictOption(spec={ 'level': StringOption(default='ERROR'), 'class': StringOption( default='django.utils.log.AdminEmailHandler'), }), }), 'loggers': DictOption( spec={ 'django.request': DictOption( spec={ 'handlers': ListOption( item=StringOption(), default=['mail_admins']), 'level': StringOption(default='ERROR'), 'propagate': BoolOption(default=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.") ############### # 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: 'http://foo.com/media/', '/media/'") 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): if version_string is None: version_string = get_version() if options is None: 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) class DjangoSchema(Schema): version = version_string class django(Section): 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: return StringOption(name=name, default=value, null=True) else: 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 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, '1.0.2 final') schemas.register(BaseDjangoSchema, '1.0.4') schemas.register(Django112Schema) schemas.register(Django112Schema, '1.1.4') schemas.register(Django125Schema) schemas.register(Django13Schema) django-configglue-0.6/django_configglue/utils.py0000644000175000017500000000325011617033273021752 0ustar ricardoricardo# Copyright 2010-2011 Canonical Ltd. This software is licensed under the # GNU Lesser General Public License version 3 (see the file LICENSE). 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 django-configglue-0.6/django_configglue/__init__.py0000644000175000017500000000035211617033273022351 0ustar ricardoricardo# Copyright 2010-2011 Canonical Ltd. This software is licensed under the # GNU Lesser General Public License version 3 (see the file LICENSE). __version__ = '0.6' # monkey-patch django's management utility from . import management django-configglue-0.6/django_configglue.egg-info/0000755000175000017500000000000011617055055021734 5ustar ricardoricardodjango-configglue-0.6/django_configglue.egg-info/PKG-INFO0000644000175000017500000000225111617055053023027 0ustar ricardoricardoMetadata-Version: 1.0 Name: django-configglue Version: 0.6 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.6/django_configglue.egg-info/top_level.txt0000644000175000017500000000002211617055053024456 0ustar ricardoricardodjango_configglue django-configglue-0.6/django_configglue.egg-info/SOURCES.txt0000644000175000017500000000160511617055055023622 0ustar ricardoricardoLICENSE.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_settings.py testproject/__init__.py testproject/main-12.cfg testproject/main-13.cfg testproject/main.cfg testproject/manage.py testproject/settings.py testproject/testrunner.py third-party/django/LICENSEdjango-configglue-0.6/django_configglue.egg-info/requires.txt0000644000175000017500000000004711617055053024333 0ustar ricardoricardodjango >= 1.0.2-final configglue >= 1.0django-configglue-0.6/django_configglue.egg-info/dependency_links.txt0000644000175000017500000000000111617055053026000 0ustar ricardoricardo