Browse Source

Added ignore_warnings decorator

And removed Ignore*DeprecationWarningsMixin, now obsolete.
Thanks Berker Peksag and Tim Graham for the review.
Claude Paroz 10 years ago
parent
commit
66f9a74b45

+ 4 - 3
django/test/__init__.py

@@ -8,13 +8,14 @@ from django.test.testcases import (
     SimpleTestCase, LiveServerTestCase, skipIfDBFeature,
     skipUnlessDBFeature
 )
-from django.test.utils import modify_settings, override_settings, override_system_checks
+from django.test.utils import (ignore_warnings, modify_settings,
+    override_settings, override_system_checks)
 
 __all__ = [
     'Client', 'RequestFactory', 'TestCase', 'TransactionTestCase',
     'SimpleTestCase', 'LiveServerTestCase', 'skipIfDBFeature',
-    'skipUnlessDBFeature', 'modify_settings', 'override_settings',
-    'override_system_checks'
+    'skipUnlessDBFeature', 'ignore_warnings', 'modify_settings',
+    'override_settings', 'override_system_checks'
 ]
 
 # To simplify Django's test suite; not meant as a public API

+ 35 - 22
django/test/utils.py

@@ -18,7 +18,7 @@ from django.template import Template
 from django.template.loaders import locmem
 from django.test.signals import template_rendered, setting_changed
 from django.utils import six
-from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
+from django.utils.deprecation import RemovedInDjango19Warning
 from django.utils.encoding import force_str
 from django.utils.translation import deactivate
 
@@ -432,27 +432,40 @@ class CaptureQueriesContext(object):
         self.final_queries = len(self.connection.queries_log)
 
 
-class IgnoreDeprecationWarningsMixin(object):
-    warning_classes = [RemovedInDjango19Warning]
-
-    def setUp(self):
-        super(IgnoreDeprecationWarningsMixin, self).setUp()
-        self.catch_warnings = warnings.catch_warnings()
-        self.catch_warnings.__enter__()
-        for warning_class in self.warning_classes:
-            warnings.filterwarnings("ignore", category=warning_class)
-
-    def tearDown(self):
-        self.catch_warnings.__exit__(*sys.exc_info())
-        super(IgnoreDeprecationWarningsMixin, self).tearDown()
-
-
-class IgnorePendingDeprecationWarningsMixin(IgnoreDeprecationWarningsMixin):
-        warning_classes = [RemovedInDjango20Warning]
-
-
-class IgnoreAllDeprecationWarningsMixin(IgnoreDeprecationWarningsMixin):
-        warning_classes = [RemovedInDjango20Warning, RemovedInDjango19Warning]
+class ignore_warnings(object):
+    def __init__(self, **kwargs):
+        self.ignore_kwargs = kwargs
+        if 'message' in self.ignore_kwargs or 'module' in self.ignore_kwargs:
+            self.filter_func = warnings.filterwarnings
+        else:
+            self.filter_func = warnings.simplefilter
+
+    def __call__(self, decorated):
+        if isinstance(decorated, type):
+            # A class is decorated
+            saved_setUp = decorated.setUp
+            saved_tearDown = decorated.tearDown
+
+            def setUp(inner_self):
+                self.catch_warnings = warnings.catch_warnings()
+                self.catch_warnings.__enter__()
+                self.filter_func('ignore', **self.ignore_kwargs)
+                saved_setUp(inner_self)
+
+            def tearDown(inner_self):
+                saved_tearDown(inner_self)
+                self.catch_warnings.__exit__(*sys.exc_info())
+
+            decorated.setUp = setUp
+            decorated.tearDown = tearDown
+            return decorated
+        else:
+            @wraps(decorated)
+            def inner(*args, **kwargs):
+                with warnings.catch_warnings():
+                    self.filter_func('ignore', **self.ignore_kwargs)
+                    return decorated(*args, **kwargs)
+            return inner
 
 
 @contextmanager

+ 16 - 13
docs/internals/contributing/writing-code/submitting-patches.txt

@@ -184,30 +184,33 @@ you need to eliminate or silence any warnings generated when running the tests.
 
 The first step is to remove any use of the deprecated behavior by Django itself.
 Next you can silence warnings in tests that actually test the deprecated
-behavior in one of two ways:
+behavior by using the ``ignore_warnings`` decorator, either at the test or class
+level:
 
 #) In a particular test::
 
-    import warnings
-
+    from django.test import ignore_warnings
     from django.utils.deprecation import RemovedInDjangoXXWarning
 
+    @ignore_warnings(category=RemovedInDjangoXXWarning)
     def test_foo(self):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", category=RemovedInDjangoXXWarning)
-            # invoke deprecated behavior
-        # go ahead with the rest of the test
+        ...
 
-#) For an entire test case, ``django.test.utils`` contains three helpful
-   mixins to silence warnings: ``IgnorePendingDeprecationWarningsMixin``,
-   ``IgnoreDeprecationWarningsMixin``, and
-   ``IgnoreAllDeprecationWarningsMixin``. For example::
+#) For an entire test case::
 
-    from django.test.utils import IgnorePendingDeprecationWarningsMixin
+    from django.test import ignore_warnings
+    from django.utils.deprecation import RemovedInDjangoXXWarning
 
-    class MyDeprecatedTests(IgnorePendingDeprecationWarningsMixin, unittest.TestCase):
+    @ignore_warnings(category=RemovedInDjangoXXWarning)
+    class MyDeprecatedTests(unittest.TestCase):
         ...
 
+.. versionchanged:: 1.8
+
+    Previous versions of Django had some ``Ignore*DeprecationWarningsMixin``
+    classes to prevent warnings from appearing. These have been replaced by the
+    ``ignore_warnings`` decorator.
+
 You can also add a test for the deprecation warning. You'll have to disable the
 "warning as error" behavior in your test by doing::