Kaydet (Commit) 3131e9ce authored tarafından Tim Graham's avatar Tim Graham

Fixed #23923 -- Promoted Django's deprecation warnings to errors in runtests.py

üst 860eb01d
...@@ -176,12 +176,11 @@ There are a couple reasons that code in Django might be deprecated: ...@@ -176,12 +176,11 @@ There are a couple reasons that code in Django might be deprecated:
As the :ref:`deprecation policy<internal-release-deprecation-policy>` describes, As the :ref:`deprecation policy<internal-release-deprecation-policy>` describes,
the first release of Django that deprecates a feature (``A.B``) should raise a the first release of Django that deprecates a feature (``A.B``) should raise a
``RemovedInDjangoXXWarning`` (where XX is the Django version where the feature ``RemovedInDjangoXXWarning`` (where XX is the Django version where the feature
will be removed) when the deprecated feature is invoked. Assuming will be removed) when the deprecated feature is invoked. Assuming we have good
we have a good test coverage, these warnings will be shown by the test suite test coverage, these warnings are converted to errors when :ref:`running the
when :ref:`running it <running-unit-tests>` with warnings enabled: test suite <running-unit-tests>` with warnings enabled:
``python -Wall runtests.py``. This is annoying and the output of the test suite ``python -Wall runtests.py``. Thus, when adding a ``RemovedInDjangoXXWarning``
should remain clean. Thus, when adding a ``RemovedInDjangoXXWarning`` you need you need to eliminate or silence any warnings generated when running the tests.
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. 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 Next you can silence warnings in tests that actually test the deprecated
...@@ -191,9 +190,11 @@ behavior in one of two ways: ...@@ -191,9 +190,11 @@ behavior in one of two ways:
import warnings import warnings
from django.utils.deprecation import RemovedInDjangoXXWarning
def test_foo(self): def test_foo(self):
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings():
warnings.simplefilter("always") warnings.simplefilter("ignore", category=RemovedInDjangoXXWarning)
# invoke deprecated behavior # invoke deprecated behavior
# go ahead with the rest of the test # go ahead with the rest of the test
...@@ -207,6 +208,20 @@ behavior in one of two ways: ...@@ -207,6 +208,20 @@ behavior in one of two ways:
class MyDeprecatedTests(IgnorePendingDeprecationWarningsMixin, unittest.TestCase): 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: Finally, there are a couple of updates to Django's documentation to make:
#) If the existing feature is documented, mark it deprecated in documentation #) If the existing feature is documented, mark it deprecated in documentation
......
...@@ -416,6 +416,7 @@ class TestInlineAdminForm(TestCase): ...@@ -416,6 +416,7 @@ class TestInlineAdminForm(TestCase):
iaf2 = InlineAdminForm(None, None, {}, {}, poll) iaf2 = InlineAdminForm(None, None, {}, {}, poll)
poll_ct = ContentType.objects.get_for_model(Poll) poll_ct = ContentType.objects.get_for_model(Poll)
with warnings.catch_warnings(record=True) as recorded: with warnings.catch_warnings(record=True) as recorded:
warnings.filterwarnings('always')
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
iaf.original_content_type_id iaf.original_content_type_id
msg = force_text(recorded.pop().message) msg = force_text(recorded.pop().message)
......
...@@ -64,7 +64,8 @@ full_decorator = compose( ...@@ -64,7 +64,8 @@ full_decorator = compose(
) )
# suppress the deprecation warning of memoize # 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 = memoize(fully_decorated, {}, 1)
fully_decorated = full_decorator(fully_decorated) fully_decorated = full_decorator(fully_decorated)
......
...@@ -238,6 +238,7 @@ class DeprecatingSimpleTestCaseUrls(unittest.TestCase): ...@@ -238,6 +238,7 @@ class DeprecatingSimpleTestCaseUrls(unittest.TestCase):
pass pass
with warnings.catch_warnings(record=True) as recorded: with warnings.catch_warnings(record=True) as recorded:
warnings.filterwarnings('always')
suite = unittest.TestLoader().loadTestsFromTestCase(TempTestCase) suite = unittest.TestLoader().loadTestsFromTestCase(TempTestCase)
with open(os.devnull, 'w') as devnull: with open(os.devnull, 'w') as devnull:
unittest.TextTestRunner(stream=devnull, verbosity=2).run(suite) unittest.TextTestRunner(stream=devnull, verbosity=2).run(suite)
......
...@@ -62,6 +62,8 @@ class FormMixinTests(TestCase): ...@@ -62,6 +62,8 @@ class FormMixinTests(TestCase):
def test_get_form_missing_form_class_default_value(self): def test_get_form_missing_form_class_default_value(self):
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always')
class MissingDefaultValue(FormMixin): class MissingDefaultValue(FormMixin):
request = RequestFactory().get('/') request = RequestFactory().get('/')
form_class = forms.Form form_class = forms.Form
......
...@@ -3,13 +3,14 @@ import warnings ...@@ -3,13 +3,14 @@ import warnings
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.http import HttpResponse, StreamingHttpResponse from django.http import HttpResponse, StreamingHttpResponse
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.translation import ugettext_lazy as _ 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 # and convert to list of urls() in Django 2.0
with warnings.catch_warnings(record=True): with warnings.catch_warnings():
warnings.filterwarnings('ignore', module='django.conf.urls.18n') warnings.filterwarnings('ignore', category=RemovedInDjango20Warning)
urlpatterns = i18n_patterns('', urlpatterns = i18n_patterns('',
(r'^simple/$', lambda r: HttpResponse()), (r'^simple/$', lambda r: HttpResponse()),
......
...@@ -101,6 +101,7 @@ class WarningLoggerTests(TestCase): ...@@ -101,6 +101,7 @@ class WarningLoggerTests(TestCase):
# undocumented and (I assume) brittle. # undocumented and (I assume) brittle.
self._old_capture_state = bool(getattr(logging, '_warnings_showwarning', False)) self._old_capture_state = bool(getattr(logging, '_warnings_showwarning', False))
logging.captureWarnings(True) logging.captureWarnings(True)
warnings.filterwarnings('always')
# this convoluted setup is to avoid printing this deprecation to # this convoluted setup is to avoid printing this deprecation to
# stderr during test running - as the test runner forces deprecations # stderr during test running - as the test runner forces deprecations
......
...@@ -20,8 +20,8 @@ from django.utils._os import upath ...@@ -20,8 +20,8 @@ from django.utils._os import upath
from django.utils import six from django.utils import six
warnings.simplefilter("default", RemovedInDjango19Warning) warnings.simplefilter("error", RemovedInDjango19Warning)
warnings.simplefilter("default", RemovedInDjango20Warning) warnings.simplefilter("error", RemovedInDjango20Warning)
CONTRIB_MODULE_PATH = 'django.contrib' CONTRIB_MODULE_PATH = 'django.contrib'
......
import warnings import warnings
from django.conf.urls import url from django.conf.urls import url
from django.utils.deprecation import RemovedInDjango20Warning
from . import views from . import views
# Test deprecated behavior of passing strings as view to url(). # 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 # Some of these can be removed in Django 2.0 as they aren't convertable to
# callabls. # callables.
with warnings.catch_warnings(record=True): with warnings.catch_warnings():
warnings.filterwarnings('ignore', module='django.conf.urls') warnings.filterwarnings('ignore', category=RemovedInDjango20Warning)
urlpatterns = [ urlpatterns = [
# View has erroneous import # View has erroneous import
url(r'erroneous_inner/$', views.erroneous_view), url(r'erroneous_inner/$', views.erroneous_view),
......
import warnings import warnings
from django.conf.urls import patterns, url, include from django.conf.urls import patterns, url, include
from django.utils.deprecation import RemovedInDjango20Warning
from .namespace_urls import URLObject from .namespace_urls import URLObject
from .views import view_class_instance from .views import view_class_instance
...@@ -9,8 +10,8 @@ from .views import view_class_instance ...@@ -9,8 +10,8 @@ from .views import view_class_instance
testobj3 = URLObject('testapp', 'test-ns3') testobj3 = URLObject('testapp', 'test-ns3')
# test deprecated patterns() function. convert to list of urls() in Django 2.0 # test deprecated patterns() function. convert to list of urls() in Django 2.0
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings():
warnings.filterwarnings('ignore', module='django.conf.urls') warnings.filterwarnings('ignore', category=RemovedInDjango20Warning)
urlpatterns = patterns('urlpatterns_reverse.views', urlpatterns = patterns('urlpatterns_reverse.views',
url(r'^normal/$', 'empty_view', name='inc-normal-view'), url(r'^normal/$', 'empty_view', name='inc-normal-view'),
......
import warnings import warnings
from django.conf.urls import patterns, url, include from django.conf.urls import patterns, url, include
from django.utils.deprecation import RemovedInDjango20Warning
from .views import ( from .views import (
absolute_kwargs_view, defaults_view, empty_view, empty_view_partial, absolute_kwargs_view, defaults_view, empty_view, empty_view_partial,
...@@ -14,8 +15,8 @@ other_patterns = [ ...@@ -14,8 +15,8 @@ other_patterns = [
] ]
# test deprecated patterns() function. convert to list of urls() in Django 2.0 # test deprecated patterns() function. convert to list of urls() in Django 2.0
with warnings.catch_warnings(record=True): with warnings.catch_warnings():
warnings.filterwarnings('ignore', module='django.conf.urls') warnings.filterwarnings('ignore', category=RemovedInDjango20Warning)
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^places/([0-9]+)/$', empty_view, name='places'), url(r'^places/([0-9]+)/$', empty_view, name='places'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment