diff --git a/django/test/testcases.py b/django/test/testcases.py index 276d1f3c41..fc49d0d79b 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -11,6 +11,7 @@ from django.db import transaction, connections, DEFAULT_DB_ALIAS from django.http import QueryDict from django.test import _doctest as doctest from django.test.client import Client +from django.test.utils import get_warnings_state, restore_warnings_state from django.utils import simplejson from django.utils.encoding import smart_str @@ -286,6 +287,19 @@ class TransactionTestCase(unittest.TestCase): settings.ROOT_URLCONF = self._old_root_urlconf clear_url_caches() + def save_warnings_state(self): + """ + Saves the state of the warnings module + """ + self._warnings_state = get_warnings_state() + + def restore_warnings_state(self): + """ + Restores the sate of the warnings module to the state + saved by save_warnings_state() + """ + restore_warnings_state(self._warnings_state) + def assertRedirects(self, response, expected_url, status_code=302, target_status_code=200, host=None, msg_prefix=''): """Asserts that a response redirected to a specific URL, and that the diff --git a/django/test/utils.py b/django/test/utils.py index 8ecb5a0e60..517d06ff0b 100644 --- a/django/test/utils.py +++ b/django/test/utils.py @@ -1,6 +1,7 @@ import sys import time import os +import warnings from django.conf import settings from django.core import mail from django.core.mail.backends import locmem @@ -43,6 +44,7 @@ class ContextList(list): return False return True + def instrumented_test_render(self, context): """ An instrumented Template render method, providing a signal @@ -72,6 +74,7 @@ def setup_test_environment(): deactivate() + def teardown_test_environment(): """Perform any global post-test teardown. This involves: @@ -90,6 +93,25 @@ def teardown_test_environment(): del mail.outbox + +def get_warnings_state(): + """ + Returns an object containing the state of the warnings module + """ + # There is no public interface for doing this, but this implementation of + # get_warnings_state and restore_warnings_state appears to work on Python + # 2.4 to 2.7. + return warnings.filters[:] + + +def restore_warnings_state(state): + """ + Restores the state of the warnings module when passed an object that was + returned by get_warnings_state() + """ + warnings.filters = state[:] + + def get_runner(settings): test_path = settings.TEST_RUNNER.split('.') # Allow for Python 2.5 relative paths diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py index 1e0a4046bb..7167e2fbf8 100644 --- a/tests/regressiontests/cache/tests.py +++ b/tests/regressiontests/cache/tests.py @@ -16,6 +16,7 @@ from django.core.cache import get_cache from django.core.cache.backends.base import InvalidCacheBackendError, CacheKeyWarning from django.http import HttpResponse, HttpRequest from django.middleware.cache import FetchFromCacheMiddleware, UpdateCacheMiddleware +from django.test.utils import get_warnings_state, restore_warnings_state from django.utils import translation from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key from django.utils.hashcompat import md5_constructor @@ -379,20 +380,16 @@ class BaseCacheTests(object): # manager to test this warning nicely. Since we can't do that # yet, the cleanest option is to temporarily ask for # CacheKeyWarning to be raised as an exception. + _warnings_state = get_warnings_state() warnings.simplefilter("error", CacheKeyWarning) - # memcached does not allow whitespace or control characters in keys - self.assertRaises(CacheKeyWarning, self.cache.set, 'key with spaces', 'value') - # memcached limits key length to 250 - self.assertRaises(CacheKeyWarning, self.cache.set, 'a' * 251, 'value') - - # The warnings module has no public API for getting the - # current list of warning filters, so we can't save that off - # and reset to the previous value, we have to globally reset - # it. The effect will be the same, as long as the Django test - # runner doesn't add any global warning filters (it currently - # does not). - warnings.resetwarnings() + try: + # memcached does not allow whitespace or control characters in keys + self.assertRaises(CacheKeyWarning, self.cache.set, 'key with spaces', 'value') + # memcached limits key length to 250 + self.assertRaises(CacheKeyWarning, self.cache.set, 'a' * 251, 'value') + finally: + restore_warnings_state(_warnings_state) class DBCacheTests(unittest.TestCase, BaseCacheTests): def setUp(self): diff --git a/tests/regressiontests/templates/loaders.py b/tests/regressiontests/templates/loaders.py index caa3faa6bc..47cd18ae21 100644 --- a/tests/regressiontests/templates/loaders.py +++ b/tests/regressiontests/templates/loaders.py @@ -21,6 +21,7 @@ from django.template import TemplateDoesNotExist, Context from django.template.loaders.eggs import load_template_source as lts_egg from django.template.loaders.eggs import Loader as EggLoader from django.template import loader +from django.test.utils import get_warnings_state, restore_warnings_state # Mock classes and objects for pkg_resources functions. class MockProvider(pkg_resources.NullProvider): @@ -67,11 +68,12 @@ class DeprecatedEggLoaderTest(unittest.TestCase): }) self._old_installed_apps = settings.INSTALLED_APPS settings.INSTALLED_APPS = [] + self._warnings_state = get_warnings_state() warnings.simplefilter("ignore", PendingDeprecationWarning) def tearDown(self): settings.INSTALLED_APPS = self._old_installed_apps - warnings.resetwarnings() + restore_warnings_state(self._warnings_state) def test_existing(self): "A template can be loaded from an egg"