Skip to content

Commit

Permalink
Added ignore_warnings decorator
Browse files Browse the repository at this point in the history
And removed Ignore*DeprecationWarningsMixin, now obsolete.
Thanks Berker Peksag and Tim Graham for the review.
  • Loading branch information
claudep committed Dec 30, 2014
1 parent 8082c75 commit 66f9a74
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 38 deletions.
7 changes: 4 additions & 3 deletions django/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
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
Expand Down
57 changes: 35 additions & 22 deletions django/test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
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

Expand Down Expand Up @@ -432,27 +432,40 @@ def __exit__(self, exc_type, exc_value, traceback):
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
Expand Down
29 changes: 16 additions & 13 deletions docs/internals/contributing/writing-code/submitting-patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand Down

0 comments on commit 66f9a74

Please sign in to comment.