diff --git a/docs/internals/contributing/writing-code/submitting-patches.txt b/docs/internals/contributing/writing-code/submitting-patches.txt index 012d1b278a..12be5c8e24 100644 --- a/docs/internals/contributing/writing-code/submitting-patches.txt +++ b/docs/internals/contributing/writing-code/submitting-patches.txt @@ -176,12 +176,11 @@ There are a couple reasons that code in Django might be deprecated: As the :ref:`deprecation policy` describes, the first release of Django that deprecates a feature (``A.B``) should raise a ``RemovedInDjangoXXWarning`` (where XX is the Django version where the feature -will be removed) when the deprecated feature is invoked. Assuming -we have a good test coverage, these warnings will be shown by the test suite -when :ref:`running it ` with warnings enabled: -``python -Wall runtests.py``. This is annoying and the output of the test suite -should remain clean. Thus, when adding a ``RemovedInDjangoXXWarning`` you need -to eliminate or silence any warnings generated when running the tests. +will be removed) when the deprecated feature is invoked. Assuming we have good +test coverage, these warnings are converted to errors when :ref:`running the +test suite ` with warnings enabled: +``python -Wall runtests.py``. Thus, when adding a ``RemovedInDjangoXXWarning`` +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 @@ -191,9 +190,11 @@ behavior in one of two ways: import warnings + from django.utils.deprecation import RemovedInDjangoXXWarning + def test_foo(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=RemovedInDjangoXXWarning) # invoke deprecated behavior # go ahead with the rest of the test @@ -207,6 +208,20 @@ behavior in one of two ways: class MyDeprecatedTests(IgnorePendingDeprecationWarningsMixin, unittest.TestCase): ... +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:: + + import warnings + + def test_foo_deprecation_warning(self): + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter('always') # prevent warnings from appearing as errors + # invoke deprecated behavior + + self.assertEqual(len(warns), 1) + msg = str(warns[0].message) + self.assertEqual(msg, 'Expected deprecation message') + Finally, there are a couple of updates to Django's documentation to make: #) If the existing feature is documented, mark it deprecated in documentation diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index e3376fe8e4..7d8be94803 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -416,6 +416,7 @@ class TestInlineAdminForm(TestCase): iaf2 = InlineAdminForm(None, None, {}, {}, poll) poll_ct = ContentType.objects.get_for_model(Poll) with warnings.catch_warnings(record=True) as recorded: + warnings.filterwarnings('always') with self.assertRaises(AttributeError): iaf.original_content_type_id msg = force_text(recorded.pop().message) diff --git a/tests/decorators/tests.py b/tests/decorators/tests.py index 4a49dcc71d..467901eebf 100644 --- a/tests/decorators/tests.py +++ b/tests/decorators/tests.py @@ -64,7 +64,8 @@ full_decorator = compose( ) # suppress the deprecation warning of memoize -with warnings.catch_warnings(record=True): +with warnings.catch_warnings(): + warnings.filterwarnings('ignore') fully_decorated = memoize(fully_decorated, {}, 1) fully_decorated = full_decorator(fully_decorated) diff --git a/tests/deprecation/tests.py b/tests/deprecation/tests.py index 185971dffa..79a6284cf6 100644 --- a/tests/deprecation/tests.py +++ b/tests/deprecation/tests.py @@ -238,6 +238,7 @@ class DeprecatingSimpleTestCaseUrls(unittest.TestCase): pass with warnings.catch_warnings(record=True) as recorded: + warnings.filterwarnings('always') suite = unittest.TestLoader().loadTestsFromTestCase(TempTestCase) with open(os.devnull, 'w') as devnull: unittest.TextTestRunner(stream=devnull, verbosity=2).run(suite) diff --git a/tests/generic_views/test_edit.py b/tests/generic_views/test_edit.py index bd48aef11b..5773730bf1 100644 --- a/tests/generic_views/test_edit.py +++ b/tests/generic_views/test_edit.py @@ -62,6 +62,8 @@ class FormMixinTests(TestCase): def test_get_form_missing_form_class_default_value(self): with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always') + class MissingDefaultValue(FormMixin): request = RequestFactory().get('/') form_class = forms.Form diff --git a/tests/i18n/urls.py b/tests/i18n/urls.py index d225bff453..196cea92b8 100644 --- a/tests/i18n/urls.py +++ b/tests/i18n/urls.py @@ -3,13 +3,14 @@ import warnings from django.conf.urls.i18n import i18n_patterns from django.http import HttpResponse, StreamingHttpResponse +from django.utils.deprecation import RemovedInDjango20Warning from django.utils.translation import ugettext_lazy as _ -# test deprecated version of i18_patterns() function (with prefix). Remove it +# test deprecated version of i18n_patterns() function (with prefix). Remove it # and convert to list of urls() in Django 2.0 -with warnings.catch_warnings(record=True): - warnings.filterwarnings('ignore', module='django.conf.urls.18n') +with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=RemovedInDjango20Warning) urlpatterns = i18n_patterns('', (r'^simple/$', lambda r: HttpResponse()), diff --git a/tests/logging_tests/tests.py b/tests/logging_tests/tests.py index d0a3a92eff..eb760a56da 100644 --- a/tests/logging_tests/tests.py +++ b/tests/logging_tests/tests.py @@ -101,6 +101,7 @@ class WarningLoggerTests(TestCase): # undocumented and (I assume) brittle. self._old_capture_state = bool(getattr(logging, '_warnings_showwarning', False)) logging.captureWarnings(True) + warnings.filterwarnings('always') # this convoluted setup is to avoid printing this deprecation to # stderr during test running - as the test runner forces deprecations diff --git a/tests/runtests.py b/tests/runtests.py index 830c83e9c1..a336b7f6d2 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -20,8 +20,8 @@ from django.utils._os import upath from django.utils import six -warnings.simplefilter("default", RemovedInDjango19Warning) -warnings.simplefilter("default", RemovedInDjango20Warning) +warnings.simplefilter("error", RemovedInDjango19Warning) +warnings.simplefilter("error", RemovedInDjango20Warning) CONTRIB_MODULE_PATH = 'django.contrib' diff --git a/tests/urlpatterns_reverse/erroneous_urls.py b/tests/urlpatterns_reverse/erroneous_urls.py index b4d6132966..b08376dc91 100644 --- a/tests/urlpatterns_reverse/erroneous_urls.py +++ b/tests/urlpatterns_reverse/erroneous_urls.py @@ -1,14 +1,15 @@ import warnings from django.conf.urls import url +from django.utils.deprecation import RemovedInDjango20Warning from . import views # Test deprecated behavior of passing strings as view to url(). # Some of these can be removed in Django 2.0 as they aren't convertable to -# callabls. -with warnings.catch_warnings(record=True): - warnings.filterwarnings('ignore', module='django.conf.urls') +# callables. +with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=RemovedInDjango20Warning) urlpatterns = [ # View has erroneous import url(r'erroneous_inner/$', views.erroneous_view), diff --git a/tests/urlpatterns_reverse/included_namespace_urls.py b/tests/urlpatterns_reverse/included_namespace_urls.py index 29947f47cd..2472e7c07d 100644 --- a/tests/urlpatterns_reverse/included_namespace_urls.py +++ b/tests/urlpatterns_reverse/included_namespace_urls.py @@ -1,6 +1,7 @@ import warnings from django.conf.urls import patterns, url, include +from django.utils.deprecation import RemovedInDjango20Warning from .namespace_urls import URLObject from .views import view_class_instance @@ -9,8 +10,8 @@ from .views import view_class_instance testobj3 = URLObject('testapp', 'test-ns3') # test deprecated patterns() function. convert to list of urls() in Django 2.0 -with warnings.catch_warnings(record=True) as w: - warnings.filterwarnings('ignore', module='django.conf.urls') +with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=RemovedInDjango20Warning) urlpatterns = patterns('urlpatterns_reverse.views', url(r'^normal/$', 'empty_view', name='inc-normal-view'), diff --git a/tests/urlpatterns_reverse/urls.py b/tests/urlpatterns_reverse/urls.py index 4ba596d81c..825ded40a2 100644 --- a/tests/urlpatterns_reverse/urls.py +++ b/tests/urlpatterns_reverse/urls.py @@ -1,6 +1,7 @@ import warnings from django.conf.urls import patterns, url, include +from django.utils.deprecation import RemovedInDjango20Warning from .views import ( absolute_kwargs_view, defaults_view, empty_view, empty_view_partial, @@ -14,8 +15,8 @@ other_patterns = [ ] # test deprecated patterns() function. convert to list of urls() in Django 2.0 -with warnings.catch_warnings(record=True): - warnings.filterwarnings('ignore', module='django.conf.urls') +with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=RemovedInDjango20Warning) urlpatterns = patterns('', url(r'^places/([0-9]+)/$', empty_view, name='places'),