diff --git a/AUTHORS b/AUTHORS
index 9413a51884..3eb0a68be9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -97,6 +97,7 @@ answer newbie questions, and generally made Django that much better:
Ned Batchelder
batiste@dosimple.ch
Batman
+ Oliver Beattie
Brian Beck
Shannon -jj Behrens
Esdras Beleza
diff --git a/django/test/utils.py b/django/test/utils.py
index be586c75a6..fc4558875e 100644
--- a/django/test/utils.py
+++ b/django/test/utils.py
@@ -207,7 +207,6 @@ class override_settings(object):
"""
def __init__(self, **kwargs):
self.options = kwargs
- self.wrapped = settings._wrapped
def __enter__(self):
self.enable()
@@ -246,6 +245,7 @@ class override_settings(object):
override = UserSettingsHolder(settings._wrapped)
for key, new_value in self.options.items():
setattr(override, key, new_value)
+ self.wrapped = settings._wrapped
settings._wrapped = override
for key, new_value in self.options.items():
setting_changed.send(sender=settings._wrapped.__class__,
@@ -253,6 +253,7 @@ class override_settings(object):
def disable(self):
settings._wrapped = self.wrapped
+ del self.wrapped
for key in self.options:
new_value = getattr(settings, key, None)
setting_changed.send(sender=settings._wrapped.__class__,
diff --git a/tests/servers/tests.py b/tests/servers/tests.py
index 3377793d68..be74afe820 100644
--- a/tests/servers/tests.py
+++ b/tests/servers/tests.py
@@ -95,6 +95,11 @@ class LiveServerAddress(LiveServerBase):
else:
del os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS']
+ @classmethod
+ def tearDownClass(cls):
+ # skip it, as setUpClass doesn't call its parent either
+ pass
+
@classmethod
def raises_exception(cls, address, exception):
os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = address
diff --git a/tests/settings_tests/tests.py b/tests/settings_tests/tests.py
index f8d66bb2b7..625c4f31df 100644
--- a/tests/settings_tests/tests.py
+++ b/tests/settings_tests/tests.py
@@ -9,17 +9,19 @@ from django.test.utils import override_settings
from django.utils import unittest, six
-@override_settings(TEST='override')
+@override_settings(TEST='override', TEST_OUTER='outer')
class FullyDecoratedTranTestCase(TransactionTestCase):
available_apps = []
def test_override(self):
self.assertEqual(settings.TEST, 'override')
+ self.assertEqual(settings.TEST_OUTER, 'outer')
@override_settings(TEST='override2')
def test_method_override(self):
self.assertEqual(settings.TEST, 'override2')
+ self.assertEqual(settings.TEST_OUTER, 'outer')
def test_decorated_testcase_name(self):
self.assertEqual(FullyDecoratedTranTestCase.__name__, 'FullyDecoratedTranTestCase')
@@ -168,6 +170,29 @@ class SettingsTests(TestCase):
self.assertRaises(AttributeError, getattr, settings, 'USE_I18N')
self.assertEqual(settings.USE_I18N, previous_i18n)
+ def test_override_settings_nested(self):
+ """
+ Test that override_settings uses the actual _wrapped attribute at
+ runtime, not when it was instantiated.
+ """
+
+ self.assertRaises(AttributeError, getattr, settings, 'TEST')
+ self.assertRaises(AttributeError, getattr, settings, 'TEST2')
+
+ inner = override_settings(TEST2='override')
+ with override_settings(TEST='override'):
+ self.assertEqual('override', settings.TEST)
+ with inner:
+ self.assertEqual('override', settings.TEST)
+ self.assertEqual('override', settings.TEST2)
+ # inner's __exit__ should have restored the settings of the outer
+ # context manager, not those when the class was instantiated
+ self.assertEqual('override', settings.TEST)
+ self.assertRaises(AttributeError, getattr, settings, 'TEST2')
+
+ self.assertRaises(AttributeError, getattr, settings, 'TEST')
+ self.assertRaises(AttributeError, getattr, settings, 'TEST2')
+
def test_allowed_include_roots_string(self):
"""
ALLOWED_INCLUDE_ROOTS is not allowed to be incorrectly set to a string