├── .gitignore ├── .travis.yml ├── CHANGELOG.rst ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── override_settings └── __init__.py ├── setup.py ├── tests ├── __init__.py └── test_django │ ├── __init__.py │ ├── apps │ ├── __init__.py │ └── testapp │ │ ├── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ └── views.py │ └── settings │ ├── __init__.py │ ├── v12.py │ ├── v13.py │ └── v14.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | MANIFEST 3 | dist 4 | build 5 | dist 6 | .tox 7 | *.egg-info 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This isn't as full featured as the tox config, but tests the 2 | # important stuff. 3 | 4 | language: python 5 | 6 | python: 7 | - 2.6 8 | - 2.7 9 | 10 | install: 11 | - pip install --use-mirrors . Django==1.3.3 12 | 13 | script: 14 | - nosetests -x tests -e test_django 15 | 16 | notifications: 17 | email: false 18 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | Development 2 | ----------- 3 | * Use mock to provide fake django.conf.settings object 4 | * Register with Travis CI 5 | * Move tests outside of package 6 | * Use tox to test various Python and Django versions 7 | * Add tests for with/without apps when used as context managers 8 | * Test a few different permutations of SETTING_DELETED 9 | 10 | Version 1.2 11 | ----------- 12 | * Much more robust handling of SETTING_DELETED 13 | 14 | Version 1.1.1 15 | ------------- 16 | * When decorating TestCases, display the original name in output 17 | * Small typo fix in README 18 | * Add test to make sure global settings are unaffected 19 | 20 | Version 1.1 21 | ----------- 22 | * Initial release 23 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Eric Davis 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following 12 | disclaimer in the documentation and/or other materials provided 13 | with the distribution. 14 | * Neither the name of the author nor the names of other 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | django-override-settings 3 | ======================== 4 | 5 | .. image:: https://secure.travis-ci.org/edavis/django-override-settings.png 6 | :target: http://travis-ci.org/#!/edavis/django-override-settings 7 | 8 | django-override-settings provides an easy way to override settings in 9 | Django tests. 10 | 11 | The ``override_settings`` class can be used as either a class/method 12 | decorator or as a context manager to temporarily override the values 13 | of settings. It works by creating a mock ``django.conf.settings`` 14 | object with user-defined attributes. After each test has finished or 15 | the context manager has exited, it resets the values in 16 | ``django.conf.settings`` so each test can run in its own sandbox 17 | without side-effects creeping in. 18 | 19 | This package also provides two convenience functions (``with_apps`` 20 | and ``without_apps``) to modify just ``INSTALLED_APPS`` as well as a 21 | special object (``SETTING_DELETED``) to run tests without a given 22 | setting defined. 23 | 24 | The functionality in this package will eventually be superseded when 25 | Django 1.4 is released as it will come with a built-in 26 | ``override_settings``. But for those maintaining pre-1.4 codebases, 27 | hopefully this package comes in handy. 28 | 29 | Installation 30 | ------------ 31 | 32 | We're on PyPI_:: 33 | 34 | pip install django-override-settings 35 | 36 | .. _PyPI: http://pypi.python.org/pypi/django-override-settings 37 | 38 | Usage 39 | ----- 40 | 41 | If you have a bunch of tests that require a given setting, you can 42 | decorate the class and each test case will use that value. For 43 | example:: 44 | 45 | from django.conf import settings 46 | from django.test import TestCase 47 | from override_settings import override_settings 48 | 49 | @override_settings(FOO="abc") 50 | class TestFoo(TestCase): 51 | def test_foo(self): 52 | self.assertEqual(settings.FOO, "abc") 53 | 54 | Or you can decorate a single test case and have it only apply on that 55 | method:: 56 | 57 | @override_settings(BAR="123") 58 | class TestBar(TestCase): 59 | 60 | @override_settings(BAR="abc") 61 | def test_bar(self): 62 | self.assertEqual(settings.BAR, "abc") 63 | 64 | def test_bar_no_decoration(self): 65 | self.assertEqual(settings.BAR, "123") 66 | 67 | You can also use it as a context manager:: 68 | 69 | class TestBar(TestCase): 70 | @override_settings(BAR="123") 71 | def test_bar(self): 72 | self.assertEqual(settings.BAR, "123") 73 | 74 | with override_settings(BAR="abc") 75 | self.assertEqual(settings.BAR, "abc") 76 | 77 | self.assertEqual(settings.BAR, "123") 78 | 79 | To modify just ``INSTALLED_APPS``, use ``with_apps`` or 80 | ``without_apps``:: 81 | 82 | from override_settings import with_apps, without_apps 83 | 84 | class TestAppModifiers(TestCase): 85 | @with_apps('django.contrib.humanize') 86 | def test_humanize(self): 87 | # ... 88 | 89 | @without_apps('django.contrib.sites') 90 | def test_no_sites(self): 91 | # ... 92 | 93 | To run tests without a setting, use ``SETTING_DELETED``:: 94 | 95 | from override_settings import override_settings, SETTING_DELETED 96 | 97 | class TestMissingSetting(TestCase): 98 | @override_settings(CUSTOM_OPTION=SETTING_DELETED) 99 | def test_delete_custom_option(self): 100 | """ 101 | Useful to make sure a missing setting raises an Exception. 102 | """ 103 | self.assertRaises(AttributeError, getattr, settings, 'CUSTOM_OPTION') 104 | 105 | Requirements 106 | ------------ 107 | 108 | Works on Python versions 2.6 and 2.7 and with Django 1.2 through 1.4. 109 | 110 | To run the test suite, you'll need tox_ (>= 1.4.2) 111 | 112 | .. _tox: http://pypi.python.org/pypi/tox 113 | 114 | Thanks 115 | ------ 116 | 117 | - `Jannis Leidel`_ for both the `original snippet`_ and his work updating it 118 | to work when decorating TestCases as part of `Django proper`_. 119 | 120 | - `Joost Cassee`_ for the idea of ``SETTING_DELETED`` as well as 121 | ``with_apps`` and ``without_apps`` as part of his django-analytical_ 122 | project. 123 | 124 | .. _Jannis Leidel: https://github.com/jezdez 125 | .. _original snippet: http://djangosnippets.org/snippets/2437/ 126 | .. _Django proper: https://code.djangoproject.com/browser/django/trunk/django/test/utils.py 127 | .. _Joost Cassee: https://github.com/jcassee 128 | .. _django-analytical: https://github.com/jcassee/django-analytical 129 | 130 | Contact 131 | ------- 132 | 133 | If you notice any bugs, please `file a ticket`_. 134 | 135 | .. _file a ticket: https://github.com/edavis/django-override-settings/issues 136 | -------------------------------------------------------------------------------- /override_settings/__init__.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import mock 3 | from functools import wraps 4 | from django.conf import global_settings, settings 5 | 6 | SETTING_DELETED = mock.sentinel.SETTING_DELETED 7 | 8 | class override_settings(object): 9 | def __init__(self, **kwargs): 10 | self.options = self.get_global_settings() 11 | self.options.update(kwargs) 12 | self.patcher = mock.patch.object(settings, '_wrapped', **self.options) 13 | 14 | def get_global_settings(self): 15 | """ 16 | Return a dictionary of all global_settings values. 17 | """ 18 | return dict((key, getattr(global_settings, key)) for key in dir(global_settings) 19 | if key.isupper()) 20 | 21 | def __call__(self, test_func): 22 | if isinstance(test_func, type): 23 | def _pre_setup(innerself): 24 | self.enable() 25 | test_func.setUp(innerself) 26 | def _post_teardown(innerself): 27 | test_func.tearDown(innerself) 28 | self.disable() 29 | 30 | # When decorating a class, we need to construct a new class 31 | # with the same name so that the test discovery tools can 32 | # get a useful name. 33 | inner = type( 34 | test_func.__name__, 35 | (test_func,), 36 | { 37 | 'setUp': _pre_setup, 38 | 'tearDown': _post_teardown, 39 | '__module__': test_func.__module__, 40 | }) 41 | return inner 42 | else: 43 | @wraps(test_func) 44 | def inner(*args, **kwargs): 45 | with self: 46 | return test_func(*args, **kwargs) 47 | return inner 48 | 49 | def enable(self): 50 | self.mocked = self.patcher.start() 51 | # Delete attributes set to SETTING_DELETED 52 | for key, value in self.options.iteritems(): 53 | if value is SETTING_DELETED: 54 | delattr(self.mocked, key) 55 | return self.mocked 56 | 57 | def disable(self): 58 | self.patcher.stop() 59 | 60 | def __enter__(self): 61 | self.enable() 62 | 63 | def __exit__(self, exc_type, exc_value, traceback): 64 | self.disable() 65 | 66 | def with_apps(*apps): 67 | """ 68 | Class decorator that makes sure the passed apps are present in 69 | INSTALLED_APPS. 70 | """ 71 | apps_set = set(settings.INSTALLED_APPS) 72 | apps_set.update(apps) 73 | return override_settings(INSTALLED_APPS=list(apps_set)) 74 | 75 | def without_apps(*apps): 76 | """ 77 | Class decorator that makes sure the passed apps are not present in 78 | INSTALLED_APPS. 79 | """ 80 | apps_list = [a for a in settings.INSTALLED_APPS if a not in apps] 81 | return override_settings(INSTALLED_APPS=apps_list) 82 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | try: 4 | from setuptools import setup 5 | except ImportError: 6 | from distutils.core import setup 7 | 8 | setup( 9 | name = "django-override-settings", 10 | version = "1.2", 11 | author = "Eric Davis", 12 | author_email = "ed@npri.org", 13 | description = "Provide a way to override Django's settings when running tests", 14 | long_description = open('README.rst').read(), 15 | url = "http://github.com/edavis/django-override-settings/", 16 | packages = ['override_settings'], 17 | install_requires = ['mock==1.0b1'], 18 | classifiers = [ 19 | "Development Status :: 5 - Production/Stable", 20 | "Framework :: Django", 21 | "Intended Audience :: Developers", 22 | "License :: OSI Approved :: BSD License", 23 | "Natural Language :: English", 24 | "Operating System :: OS Independent", 25 | "Programming Language :: Python", 26 | "Topic :: Software Development :: Testing", 27 | ], 28 | ) 29 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | if not settings.configured: 3 | # Since this test suite is designed to be ran outside of ./manage.py test, 4 | # we need to do some setup first. 5 | # 6 | # We use 'django.contrib.sites' for the without_apps context manager test. 7 | settings.configure(INSTALLED_APPS=['django.contrib.sites']) 8 | 9 | import unittest 10 | from override_settings import ( 11 | override_settings, SETTING_DELETED, 12 | with_apps, without_apps) 13 | 14 | @override_settings(FOO="abc") 15 | class TestOverrideSettingsDecoratedClass(unittest.TestCase): 16 | """ 17 | Provide a decorated class. 18 | """ 19 | def test_override_settings_class_decorator(self): 20 | """ 21 | Settings overwritten at the class level are available in each method. 22 | """ 23 | self.assertEqual(settings.FOO, "abc") 24 | 25 | @override_settings(FOO="abc123") 26 | def test_override_settings_method_decorator(self): 27 | """ 28 | Method level overrides overwrite class level overrides. 29 | """ 30 | self.assertEqual(settings.FOO, "abc123") 31 | 32 | @override_settings(FOO="321") 33 | def test_override_settings_context_manager(self): 34 | """ 35 | Context managers overwrite method and class level decorations. 36 | """ 37 | with override_settings(FOO="xyz"): 38 | self.assertEqual(settings.FOO, "xyz") 39 | 40 | def test_decorated_testcase_module(self): 41 | """ 42 | Make sure __name__ is correctly reported. 43 | """ 44 | self.assertEqual(TestOverrideSettingsDecoratedClass.__module__, __name__) 45 | 46 | class TestOverrideSettingsUndecoratedClass(unittest.TestCase): 47 | """ 48 | Provide an undecorated class. 49 | """ 50 | @override_settings(FOO="123") 51 | def test_override_settings_on_a_method(self): 52 | """ 53 | Override settings can be used for an individual method. 54 | """ 55 | self.assertEqual(settings.FOO, "123") 56 | 57 | def test_override_settings_as_context_manager(self): 58 | """ 59 | Can use override_settings as a context manager. 60 | """ 61 | with override_settings(FOO="321"): 62 | self.assertEqual(settings.FOO, "321") 63 | 64 | def test_undecorated_class_and_method_raises_exception(self): 65 | """ 66 | Make sure settings.FOO isn't available unless set. 67 | """ 68 | self.assertRaises(AttributeError, getattr, settings, "FOO") 69 | 70 | class TestAppModifiers(unittest.TestCase): 71 | """ 72 | Test the with and without apps decorators. 73 | 74 | These are helper decorators to just alter INSTALLED_APPS. 75 | """ 76 | @with_apps('django.contrib.webdesign') 77 | def test_with_apps(self): 78 | """ 79 | The `with_apps` decorator adds apps to INSTALLED_APPS. 80 | """ 81 | self.assertTrue('django.contrib.webdesign' in settings.INSTALLED_APPS) 82 | 83 | @without_apps("django.contrib.sites") 84 | def test_without_apps(self): 85 | """ 86 | The `without_apps` decorator removes apps from INSTALLED_APPS. 87 | """ 88 | self.assertFalse('django.contrib.sites' in settings.INSTALLED_APPS) 89 | 90 | def test_with_and_without_apps_context_manager(self): 91 | """ 92 | Make sure with and without apps work when used as context managers. 93 | """ 94 | with with_apps('django.contrib.webdesign'): 95 | self.assertTrue('django.contrib.webdesign' in settings.INSTALLED_APPS) 96 | self.assertFalse('django.contrib.webdesign' in settings.INSTALLED_APPS) 97 | 98 | with without_apps('django.contrib.sites'): 99 | self.assertFalse('django.contrib.sites' in settings.INSTALLED_APPS) 100 | self.assertTrue('django.contrib.sites' in settings.INSTALLED_APPS) 101 | 102 | @override_settings(DUMMY_OPTION=42) 103 | class TestSettingDeleted(unittest.TestCase): 104 | def test_dummy_option_exists(self): 105 | """ 106 | Deleted options should return after the context manager is finished. 107 | """ 108 | self.assertEqual(settings.DUMMY_OPTION, 42) 109 | 110 | with override_settings(DUMMY_OPTION=SETTING_DELETED): 111 | self.assertRaises(AttributeError, getattr, settings, 'DUMMY_OPTION') 112 | 113 | self.assertEqual(settings.DUMMY_OPTION, 42) 114 | 115 | @override_settings(DUMMY_OPTION=SETTING_DELETED) 116 | def test_delete_dummy_option(self): 117 | """ 118 | Can delete settings at the method level. 119 | """ 120 | self.assertRaises(AttributeError, getattr, settings, 'DUMMY_OPTION') 121 | 122 | def test_dummy_option_exists_after_method_level_delete(self): 123 | """ 124 | Make sure the option returns after deleting it at the method level. 125 | """ 126 | self.assertEqual(settings.DUMMY_OPTION, 42) 127 | 128 | class TestSettingDeletedUndecoratedClass(unittest.TestCase): 129 | """ 130 | Like above, but only delete settings at the method/context manager 131 | level. 132 | """ 133 | @override_settings(DUMMY_OPTION=42) 134 | def test_setting_comes_back_after_context_manager(self): 135 | """ 136 | Deleted options should return after the context manager is finished. 137 | """ 138 | self.assertEqual(settings.DUMMY_OPTION, 42) 139 | 140 | with override_settings(DUMMY_OPTION=SETTING_DELETED): 141 | self.assertRaises(AttributeError, getattr, settings, 'DUMMY_OPTION') 142 | 143 | self.assertEqual(settings.DUMMY_OPTION, 42) 144 | 145 | @override_settings(DUMMY_OPTION=SETTING_DELETED) 146 | def test_delete_dummy_option(self): 147 | """ 148 | Can delete settings at the method level. 149 | """ 150 | self.assertRaises(AttributeError, getattr, settings, 'DUMMY_OPTION') 151 | 152 | @override_settings(USER_ID=SETTING_DELETED) 153 | class TestSettingDeletedDecoratedClass(unittest.TestCase): 154 | """ 155 | settings.USER_ID is gone for all tests. 156 | 157 | Test various ways to temporarily add it back. 158 | """ 159 | @override_settings(USER_ID=1) 160 | def test_set_user_id(self): 161 | self.assertEqual(settings.USER_ID, 1) 162 | 163 | def test_set_user_id_in_context_manager(self): 164 | """ 165 | settings.USER_ID only exists in the context manager. 166 | 167 | Kind of a mirror image of TestSettingsDeleted.test_dummy_option_exists. 168 | """ 169 | self.assertRaises(AttributeError, getattr, settings, "USER_ID") 170 | 171 | with override_settings(USER_ID=1): 172 | self.assertEqual(settings.USER_ID, 1) 173 | 174 | self.assertRaises(AttributeError, getattr, settings, "USER_ID") 175 | 176 | class TestGlobalSettingsUnaffected(unittest.TestCase): 177 | @override_settings(DUMMY_OPTION=42) 178 | def test_global_settings_are_unaffected(self): 179 | """ 180 | Ensure global settings aren't touched. 181 | 182 | We don't want the passed options to be the *only* settings 183 | set. We check here for USE_ETAGS, defined in 184 | django.conf.global_settings and untouched by override_settings. 185 | """ 186 | self.assertEqual(settings.DUMMY_OPTION, 42) 187 | self.assertTrue('USE_ETAGS' in dir(settings)) 188 | 189 | class TestMultipleSettingsAtOnce(unittest.TestCase): 190 | @override_settings(OPTION_A=True) 191 | def test_multiple_options(self): 192 | self.assertEqual(settings.OPTION_A, True) 193 | with override_settings(OPTION_B="abc", OPTION_A=False): 194 | self.assertEqual(settings.OPTION_A, False) 195 | self.assertEqual(settings.OPTION_B, "abc") 196 | self.assertEqual(settings.OPTION_A, True) 197 | -------------------------------------------------------------------------------- /tests/test_django/__init__.py: -------------------------------------------------------------------------------- 1 | # keep nose away 2 | __test__ = False 3 | -------------------------------------------------------------------------------- /tests/test_django/apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edavis/django-override-settings/016a2ba44cf7132d3aeefbfeddaf201217b1d4b6/tests/test_django/apps/__init__.py -------------------------------------------------------------------------------- /tests/test_django/apps/testapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edavis/django-override-settings/016a2ba44cf7132d3aeefbfeddaf201217b1d4b6/tests/test_django/apps/testapp/__init__.py -------------------------------------------------------------------------------- /tests/test_django/apps/testapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /tests/test_django/apps/testapp/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.conf import settings 3 | from override_settings import override_settings 4 | 5 | # This is just a smoke test to make sure actually using 6 | # override_settings in django TestCases still works. 7 | # 8 | # We're just testing the bare minimum. 9 | 10 | class SimpleTest(TestCase): 11 | @override_settings(FOO="abc") 12 | def test_method_decorator(self): 13 | self.assertEqual(settings.FOO, "abc") 14 | 15 | def test_context_manager(self): 16 | self.assertRaises(AttributeError, getattr, settings, "FOO2") 17 | with override_settings(FOO2="abc"): 18 | self.assertEqual(settings.FOO2, "abc") 19 | self.assertRaises(AttributeError, getattr, settings, "FOO2") 20 | 21 | @override_settings(FOO3="abc") 22 | class SimpleTestClassOverride(TestCase): 23 | def test_exists(self): 24 | self.assertEqual(settings.FOO3, "abc") 25 | 26 | def test_exists(self): 27 | self.assertEqual(settings.FOO3, "abc") 28 | -------------------------------------------------------------------------------- /tests/test_django/apps/testapp/views.py: -------------------------------------------------------------------------------- 1 | # Create your views here. 2 | -------------------------------------------------------------------------------- /tests/test_django/settings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edavis/django-override-settings/016a2ba44cf7132d3aeefbfeddaf201217b1d4b6/tests/test_django/settings/__init__.py -------------------------------------------------------------------------------- /tests/test_django/settings/v12.py: -------------------------------------------------------------------------------- 1 | # Django settings for foo project. 2 | 3 | DEBUG = True 4 | TEMPLATE_DEBUG = DEBUG 5 | 6 | ADMINS = ( 7 | # ('Your Name', 'your_email@domain.com'), 8 | ) 9 | 10 | MANAGERS = ADMINS 11 | 12 | DATABASES = { 13 | 'default': { 14 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 15 | 'NAME': ':memory:', # Or path to database file if using sqlite3. 16 | 'USER': '', # Not used with sqlite3. 17 | 'PASSWORD': '', # Not used with sqlite3. 18 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 19 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 20 | } 21 | } 22 | 23 | # Local time zone for this installation. Choices can be found here: 24 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 25 | # although not all choices may be available on all operating systems. 26 | # On Unix systems, a value of None will cause Django to use the same 27 | # timezone as the operating system. 28 | # If running in a Windows environment this must be set to the same as your 29 | # system time zone. 30 | TIME_ZONE = 'America/Chicago' 31 | 32 | # Language code for this installation. All choices can be found here: 33 | # http://www.i18nguy.com/unicode/language-identifiers.html 34 | LANGUAGE_CODE = 'en-us' 35 | 36 | SITE_ID = 1 37 | 38 | # If you set this to False, Django will make some optimizations so as not 39 | # to load the internationalization machinery. 40 | USE_I18N = True 41 | 42 | # If you set this to False, Django will not format dates, numbers and 43 | # calendars according to the current locale 44 | USE_L10N = True 45 | 46 | # Absolute filesystem path to the directory that will hold user-uploaded files. 47 | # Example: "/home/media/media.lawrence.com/" 48 | MEDIA_ROOT = '' 49 | 50 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 51 | # trailing slash if there is a path component (optional in other cases). 52 | # Examples: "http://media.lawrence.com", "http://example.com/media/" 53 | MEDIA_URL = '' 54 | 55 | # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a 56 | # trailing slash. 57 | # Examples: "http://foo.com/media/", "/media/". 58 | ADMIN_MEDIA_PREFIX = '/media/' 59 | 60 | # Make this unique, and don't share it with anybody. 61 | SECRET_KEY = 'fcz!*uhq@eng!h7-s44w0qm6n1c@(e4w1g_t@_#7_l(lsr*5zg' 62 | 63 | # List of callables that know how to import templates from various sources. 64 | TEMPLATE_LOADERS = ( 65 | 'django.template.loaders.filesystem.Loader', 66 | 'django.template.loaders.app_directories.Loader', 67 | # 'django.template.loaders.eggs.Loader', 68 | ) 69 | 70 | MIDDLEWARE_CLASSES = ( 71 | 'django.middleware.common.CommonMiddleware', 72 | 'django.contrib.sessions.middleware.SessionMiddleware', 73 | 'django.middleware.csrf.CsrfViewMiddleware', 74 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 75 | 'django.contrib.messages.middleware.MessageMiddleware', 76 | ) 77 | 78 | ROOT_URLCONF = 'foo.urls' 79 | 80 | TEMPLATE_DIRS = ( 81 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 82 | # Always use forward slashes, even on Windows. 83 | # Don't forget to use absolute paths, not relative paths. 84 | ) 85 | 86 | INSTALLED_APPS = ( 87 | 'django.contrib.auth', 88 | 'django.contrib.contenttypes', 89 | 'django.contrib.sessions', 90 | 'django.contrib.sites', 91 | 'django.contrib.messages', 92 | 'apps.testapp', 93 | # Uncomment the next line to enable the admin: 94 | # 'django.contrib.admin', 95 | # Uncomment the next line to enable admin documentation: 96 | # 'django.contrib.admindocs', 97 | ) 98 | -------------------------------------------------------------------------------- /tests/test_django/settings/v13.py: -------------------------------------------------------------------------------- 1 | # Django settings for foo project. 2 | 3 | DEBUG = True 4 | TEMPLATE_DEBUG = DEBUG 5 | 6 | ADMINS = ( 7 | # ('Your Name', 'your_email@example.com'), 8 | ) 9 | 10 | MANAGERS = ADMINS 11 | 12 | DATABASES = { 13 | 'default': { 14 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 15 | 'NAME': ':memory:', # Or path to database file if using sqlite3. 16 | 'USER': '', # Not used with sqlite3. 17 | 'PASSWORD': '', # Not used with sqlite3. 18 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 19 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 20 | } 21 | } 22 | 23 | # Local time zone for this installation. Choices can be found here: 24 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 25 | # although not all choices may be available on all operating systems. 26 | # On Unix systems, a value of None will cause Django to use the same 27 | # timezone as the operating system. 28 | # If running in a Windows environment this must be set to the same as your 29 | # system time zone. 30 | TIME_ZONE = 'America/Chicago' 31 | 32 | # Language code for this installation. All choices can be found here: 33 | # http://www.i18nguy.com/unicode/language-identifiers.html 34 | LANGUAGE_CODE = 'en-us' 35 | 36 | SITE_ID = 1 37 | 38 | # If you set this to False, Django will make some optimizations so as not 39 | # to load the internationalization machinery. 40 | USE_I18N = True 41 | 42 | # If you set this to False, Django will not format dates, numbers and 43 | # calendars according to the current locale 44 | USE_L10N = True 45 | 46 | # Absolute filesystem path to the directory that will hold user-uploaded files. 47 | # Example: "/home/media/media.lawrence.com/media/" 48 | MEDIA_ROOT = '' 49 | 50 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 51 | # trailing slash. 52 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 53 | MEDIA_URL = '' 54 | 55 | # Absolute path to the directory static files should be collected to. 56 | # Don't put anything in this directory yourself; store your static files 57 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 58 | # Example: "/home/media/media.lawrence.com/static/" 59 | STATIC_ROOT = '' 60 | 61 | # URL prefix for static files. 62 | # Example: "http://media.lawrence.com/static/" 63 | STATIC_URL = '/static/' 64 | 65 | # URL prefix for admin static files -- CSS, JavaScript and images. 66 | # Make sure to use a trailing slash. 67 | # Examples: "http://foo.com/static/admin/", "/static/admin/". 68 | ADMIN_MEDIA_PREFIX = '/static/admin/' 69 | 70 | # Additional locations of static files 71 | STATICFILES_DIRS = ( 72 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 73 | # Always use forward slashes, even on Windows. 74 | # Don't forget to use absolute paths, not relative paths. 75 | ) 76 | 77 | # List of finder classes that know how to find static files in 78 | # various locations. 79 | STATICFILES_FINDERS = ( 80 | 'django.contrib.staticfiles.finders.FileSystemFinder', 81 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 82 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', 83 | ) 84 | 85 | # Make this unique, and don't share it with anybody. 86 | SECRET_KEY = 'qeg!yh#q2iyn76kheugxeb3hmj096z#ei&57nzx85vl3q7u-gg' 87 | 88 | # List of callables that know how to import templates from various sources. 89 | TEMPLATE_LOADERS = ( 90 | 'django.template.loaders.filesystem.Loader', 91 | 'django.template.loaders.app_directories.Loader', 92 | # 'django.template.loaders.eggs.Loader', 93 | ) 94 | 95 | MIDDLEWARE_CLASSES = ( 96 | 'django.middleware.common.CommonMiddleware', 97 | 'django.contrib.sessions.middleware.SessionMiddleware', 98 | 'django.middleware.csrf.CsrfViewMiddleware', 99 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 100 | 'django.contrib.messages.middleware.MessageMiddleware', 101 | ) 102 | 103 | ROOT_URLCONF = 'foo.urls' 104 | 105 | TEMPLATE_DIRS = ( 106 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 107 | # Always use forward slashes, even on Windows. 108 | # Don't forget to use absolute paths, not relative paths. 109 | ) 110 | 111 | INSTALLED_APPS = ( 112 | 'django.contrib.auth', 113 | 'django.contrib.contenttypes', 114 | 'django.contrib.sessions', 115 | 'django.contrib.sites', 116 | 'django.contrib.messages', 117 | 'django.contrib.staticfiles', 118 | 'apps.testapp', 119 | # Uncomment the next line to enable the admin: 120 | # 'django.contrib.admin', 121 | # Uncomment the next line to enable admin documentation: 122 | # 'django.contrib.admindocs', 123 | ) 124 | 125 | # A sample logging configuration. The only tangible logging 126 | # performed by this configuration is to send an email to 127 | # the site admins on every HTTP 500 error. 128 | # See http://docs.djangoproject.com/en/dev/topics/logging for 129 | # more details on how to customize your logging configuration. 130 | LOGGING = { 131 | 'version': 1, 132 | 'disable_existing_loggers': False, 133 | 'handlers': { 134 | 'mail_admins': { 135 | 'level': 'ERROR', 136 | 'class': 'django.utils.log.AdminEmailHandler' 137 | } 138 | }, 139 | 'loggers': { 140 | 'django.request': { 141 | 'handlers': ['mail_admins'], 142 | 'level': 'ERROR', 143 | 'propagate': True, 144 | }, 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /tests/test_django/settings/v14.py: -------------------------------------------------------------------------------- 1 | # Django settings for foo project. 2 | 3 | DEBUG = True 4 | TEMPLATE_DEBUG = DEBUG 5 | 6 | ADMINS = ( 7 | # ('Your Name', 'your_email@example.com'), 8 | ) 9 | 10 | MANAGERS = ADMINS 11 | 12 | DATABASES = { 13 | 'default': { 14 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 15 | 'NAME': ':memory:', # Or path to database file if using sqlite3. 16 | 'USER': '', # Not used with sqlite3. 17 | 'PASSWORD': '', # Not used with sqlite3. 18 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 19 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 20 | } 21 | } 22 | 23 | # Local time zone for this installation. Choices can be found here: 24 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 25 | # although not all choices may be available on all operating systems. 26 | # On Unix systems, a value of None will cause Django to use the same 27 | # timezone as the operating system. 28 | # If running in a Windows environment this must be set to the same as your 29 | # system time zone. 30 | TIME_ZONE = 'America/Chicago' 31 | 32 | # Language code for this installation. All choices can be found here: 33 | # http://www.i18nguy.com/unicode/language-identifiers.html 34 | LANGUAGE_CODE = 'en-us' 35 | 36 | SITE_ID = 1 37 | 38 | # If you set this to False, Django will make some optimizations so as not 39 | # to load the internationalization machinery. 40 | USE_I18N = True 41 | 42 | # If you set this to False, Django will not format dates, numbers and 43 | # calendars according to the current locale. 44 | USE_L10N = True 45 | 46 | # If you set this to False, Django will not use timezone-aware datetimes. 47 | USE_TZ = True 48 | 49 | # Absolute filesystem path to the directory that will hold user-uploaded files. 50 | # Example: "/home/media/media.lawrence.com/media/" 51 | MEDIA_ROOT = '' 52 | 53 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 54 | # trailing slash. 55 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 56 | MEDIA_URL = '' 57 | 58 | # Absolute path to the directory static files should be collected to. 59 | # Don't put anything in this directory yourself; store your static files 60 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 61 | # Example: "/home/media/media.lawrence.com/static/" 62 | STATIC_ROOT = '' 63 | 64 | # URL prefix for static files. 65 | # Example: "http://media.lawrence.com/static/" 66 | STATIC_URL = '/static/' 67 | 68 | # Additional locations of static files 69 | STATICFILES_DIRS = ( 70 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 71 | # Always use forward slashes, even on Windows. 72 | # Don't forget to use absolute paths, not relative paths. 73 | ) 74 | 75 | # List of finder classes that know how to find static files in 76 | # various locations. 77 | STATICFILES_FINDERS = ( 78 | 'django.contrib.staticfiles.finders.FileSystemFinder', 79 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 80 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', 81 | ) 82 | 83 | # Make this unique, and don't share it with anybody. 84 | SECRET_KEY = 'e@s198am#7qs$p)qg#+jyad1rv1grjd^e04$7f-nfv%%1bxp_=' 85 | 86 | # List of callables that know how to import templates from various sources. 87 | TEMPLATE_LOADERS = ( 88 | 'django.template.loaders.filesystem.Loader', 89 | 'django.template.loaders.app_directories.Loader', 90 | # 'django.template.loaders.eggs.Loader', 91 | ) 92 | 93 | MIDDLEWARE_CLASSES = ( 94 | 'django.middleware.common.CommonMiddleware', 95 | 'django.contrib.sessions.middleware.SessionMiddleware', 96 | 'django.middleware.csrf.CsrfViewMiddleware', 97 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 98 | 'django.contrib.messages.middleware.MessageMiddleware', 99 | # Uncomment the next line for simple clickjacking protection: 100 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware', 101 | ) 102 | 103 | ROOT_URLCONF = 'foo.urls' 104 | 105 | # Python dotted path to the WSGI application used by Django's runserver. 106 | WSGI_APPLICATION = 'foo.wsgi.application' 107 | 108 | TEMPLATE_DIRS = ( 109 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 110 | # Always use forward slashes, even on Windows. 111 | # Don't forget to use absolute paths, not relative paths. 112 | ) 113 | 114 | INSTALLED_APPS = ( 115 | 'django.contrib.auth', 116 | 'django.contrib.contenttypes', 117 | 'django.contrib.sessions', 118 | 'django.contrib.sites', 119 | 'django.contrib.messages', 120 | 'django.contrib.staticfiles', 121 | 'apps.testapp', 122 | # Uncomment the next line to enable the admin: 123 | # 'django.contrib.admin', 124 | # Uncomment the next line to enable admin documentation: 125 | # 'django.contrib.admindocs', 126 | ) 127 | 128 | # A sample logging configuration. The only tangible logging 129 | # performed by this configuration is to send an email to 130 | # the site admins on every HTTP 500 error when DEBUG=False. 131 | # See http://docs.djangoproject.com/en/dev/topics/logging for 132 | # more details on how to customize your logging configuration. 133 | LOGGING = { 134 | 'version': 1, 135 | 'disable_existing_loggers': False, 136 | 'filters': { 137 | 'require_debug_false': { 138 | '()': 'django.utils.log.RequireDebugFalse' 139 | } 140 | }, 141 | 'handlers': { 142 | 'mail_admins': { 143 | 'level': 'ERROR', 144 | 'filters': ['require_debug_false'], 145 | 'class': 'django.utils.log.AdminEmailHandler' 146 | } 147 | }, 148 | 'loggers': { 149 | 'django.request': { 150 | 'handlers': ['mail_admins'], 151 | 'level': 'ERROR', 152 | 'propagate': True, 153 | }, 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py26-django12, 3 | py26-django13, 4 | py26-django14, 5 | py27-django12, 6 | py27-django13, 7 | py27-django14 8 | 9 | [testenv] 10 | commands = nosetests -x tests -e 'test_django' 11 | django-admin.py test testapp 12 | setenv = PYTHONPATH=tests/test_django 13 | deps = nose==1.1.2 14 | 15 | ############################################## 16 | # Python 2.6 17 | ############################################## 18 | [testenv:py26-django12] 19 | basepython = python2.6 20 | setenv = {[testenv]setenv} 21 | DJANGO_SETTINGS_MODULE=settings.v12 22 | deps = Django==1.2.7 23 | {[testenv]deps} 24 | 25 | [testenv:py26-django13] 26 | basepython = python2.6 27 | setenv = {[testenv]setenv} 28 | DJANGO_SETTINGS_MODULE=settings.v13 29 | deps = Django==1.3.3 30 | {[testenv]deps} 31 | 32 | [testenv:py26-django14] 33 | basepython = python2.6 34 | setenv = {[testenv]setenv} 35 | DJANGO_SETTINGS_MODULE=settings.v14 36 | deps = Django==1.4.1 37 | {[testenv]deps} 38 | 39 | ############################################## 40 | # Python 2.7 41 | ############################################## 42 | [testenv:py27-django12] 43 | basepython = python2.7 44 | setenv = {[testenv]setenv} 45 | DJANGO_SETTINGS_MODULE=settings.v12 46 | deps = Django==1.2.7 47 | {[testenv]deps} 48 | 49 | [testenv:py27-django13] 50 | basepython = python2.7 51 | setenv = {[testenv]setenv} 52 | DJANGO_SETTINGS_MODULE=settings.v13 53 | deps = Django==1.3.3 54 | {[testenv]deps} 55 | 56 | [testenv:py27-django14] 57 | basepython = python2.7 58 | setenv = {[testenv]setenv} 59 | DJANGO_SETTINGS_MODULE=settings.v14 60 | deps = Django==1.4.1 61 | {[testenv]deps} 62 | --------------------------------------------------------------------------------