Fixed #25999 -- Removed promotion of RemovedInNextVersionWarning to loud by default.

This commit is contained in:
Tim Graham 2016-01-13 19:02:39 -05:00
parent 28acc0d6df
commit 5b94b17fef
9 changed files with 5 additions and 116 deletions

View File

@ -1,4 +1,3 @@
import logging
import os import os
import sys import sys
@ -54,21 +53,6 @@ class Command(BaseCommand):
if hasattr(test_runner_class, 'add_arguments'): if hasattr(test_runner_class, 'add_arguments'):
test_runner_class.add_arguments(parser) test_runner_class.add_arguments(parser)
def execute(self, *args, **options):
if options['verbosity'] > 0:
# ensure that deprecation warnings are displayed during testing
# the following state is assumed:
# logging.capturewarnings is true
# a "default" level warnings filter has been added for
# DeprecationWarning. See django.conf.LazySettings._configure_logging
logger = logging.getLogger('py.warnings')
handler = logging.StreamHandler()
logger.addHandler(handler)
super(Command, self).execute(*args, **options)
if options['verbosity'] > 0:
# remove the testing-specific handler
logger.removeHandler(handler)
def handle(self, *test_labels, **options): def handle(self, *test_labels, **options):
from django.conf import settings from django.conf import settings
from django.test.utils import get_runner from django.test.utils import get_runner

View File

@ -2,15 +2,12 @@ from __future__ import unicode_literals
import logging import logging
import logging.config # needed when logging_config doesn't start with logging.config import logging.config # needed when logging_config doesn't start with logging.config
import sys
import warnings
from copy import copy from copy import copy
from django.conf import settings from django.conf import settings
from django.core import mail from django.core import mail
from django.core.mail import get_connection from django.core.mail import get_connection
from django.core.management.color import color_style from django.core.management.color import color_style
from django.utils.deprecation import RemovedInNextVersionWarning
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
from django.views.debug import ExceptionReporter from django.views.debug import ExceptionReporter
@ -62,21 +59,11 @@ DEFAULT_LOGGING = {
'level': 'INFO', 'level': 'INFO',
'propagate': False, 'propagate': False,
}, },
'py.warnings': {
'handlers': ['console'],
},
} }
} }
def configure_logging(logging_config, logging_settings): def configure_logging(logging_config, logging_settings):
if not sys.warnoptions:
# Route warnings through python logging
logging.captureWarnings(True)
# RemovedInNextVersionWarning is a subclass of DeprecationWarning which
# is hidden by default, hence we force the "default" behavior
warnings.simplefilter("default", RemovedInNextVersionWarning)
if logging_config: if logging_config:
# First find the logging configuration function ... # First find the logging configuration function ...
logging_config_func = import_string(logging_config) logging_config_func = import_string(logging_config)

View File

@ -92,16 +92,16 @@ So, for example, if we decided to start the deprecation of a function in
Django 4.2: Django 4.2:
* Django 4.2 will contain a backwards-compatible replica of the function which * Django 4.2 will contain a backwards-compatible replica of the function which
will raise a ``RemovedInDjango51Warning``. This warning is silent by will raise a ``RemovedInDjango51Warning``.
default; you can turn on display of these warnings with the ``-Wd`` option
of Python.
* Django 5.0 (the version that follows 4.2) will still contain the * Django 5.0 (the version that follows 4.2) will still contain the
backwards-compatible replica. This warning becomes *loud* by default and backwards-compatible replica.
will likely be quite annoying.
* Django 5.1 will remove the feature outright. * Django 5.1 will remove the feature outright.
The warnings are silent by default. You can turn on display of these warnings
with the ``python -Wd`` option.
A more generic example: A more generic example:
* X.0 * X.0

View File

@ -739,9 +739,6 @@ When :setting:`DEBUG` is ``True``:
* The ``django`` catch-all logger sends all messages at the ``INFO`` level or * The ``django`` catch-all logger sends all messages at the ``INFO`` level or
higher to the console. higher to the console.
* The ``py.warnings`` logger, which handles messages from ``warnings.warn()``,
sends messages to the console.
When :setting:`DEBUG` is ``False``: When :setting:`DEBUG` is ``False``:
* The ``django`` logger send messages with ``ERROR`` or ``CRITICAL`` level to * The ``django`` logger send messages with ``ERROR`` or ``CRITICAL`` level to

View File

@ -12,12 +12,10 @@ from django.core.files.temp import NamedTemporaryFile
from django.test import RequestFactory, SimpleTestCase, override_settings from django.test import RequestFactory, SimpleTestCase, override_settings
from django.test.utils import LoggingCaptureMixin, patch_logger from django.test.utils import LoggingCaptureMixin, patch_logger
from django.utils.deprecation import RemovedInNextVersionWarning from django.utils.deprecation import RemovedInNextVersionWarning
from django.utils.encoding import force_text
from django.utils.log import ( from django.utils.log import (
DEFAULT_LOGGING, AdminEmailHandler, CallbackFilter, RequireDebugFalse, DEFAULT_LOGGING, AdminEmailHandler, CallbackFilter, RequireDebugFalse,
RequireDebugTrue, RequireDebugTrue,
) )
from django.utils.six import StringIO
from .logconfig import MyEmailBackend from .logconfig import MyEmailBackend
@ -121,39 +119,10 @@ class WarningLoggerTests(SimpleTestCase):
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)
# this convoluted setup is to avoid printing this deprecation to
# stderr during test running - as the test runner forces deprecations
# to be displayed at the global py.warnings level
self.logger = logging.getLogger('py.warnings')
self.outputs = []
self.old_streams = []
for handler in self.logger.handlers:
self.old_streams.append(handler.stream)
self.outputs.append(StringIO())
handler.stream = self.outputs[-1]
def tearDown(self): def tearDown(self):
for i, handler in enumerate(self.logger.handlers):
self.logger.handlers[i].stream = self.old_streams[i]
# Reset warnings state. # Reset warnings state.
logging.captureWarnings(self._old_capture_state) logging.captureWarnings(self._old_capture_state)
@override_settings(DEBUG=True)
def test_warnings_capture(self):
with warnings.catch_warnings():
warnings.filterwarnings('always')
warnings.warn('Foo Deprecated', RemovedInNextVersionWarning)
output = force_text(self.outputs[0].getvalue())
self.assertIn('Foo Deprecated', output)
def test_warnings_capture_debug_false(self):
with warnings.catch_warnings():
warnings.filterwarnings('always')
warnings.warn('Foo Deprecated', RemovedInNextVersionWarning)
output = force_text(self.outputs[0].getvalue())
self.assertNotIn('Foo Deprecated', output)
@override_settings(DEBUG=True) @override_settings(DEBUG=True)
def test_error_filter_still_raises(self): def test_error_filter_still_raises(self):
with warnings.catch_warnings(): with warnings.catch_warnings():

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
import atexit import atexit
import copy import copy
import logging
import os import os
import shutil import shutil
import subprocess import subprocess
@ -162,14 +161,6 @@ def setup(verbosity, test_labels, parallel):
log_config['loggers']['django']['level'] = 'ERROR' log_config['loggers']['django']['level'] = 'ERROR'
settings.LOGGING = log_config settings.LOGGING = log_config
if verbosity > 0:
# Ensure any warnings captured to logging are piped through a verbose
# logging handler. If any -W options were passed explicitly on command
# line, warnings are not captured, and this has no effect.
logger = logging.getLogger('py.warnings')
handler = logging.StreamHandler()
logger.addHandler(handler)
warnings.filterwarnings( warnings.filterwarnings(
'ignore', 'ignore',
'The GeoManager class is deprecated.', 'The GeoManager class is deprecated.',

View File

@ -16,8 +16,6 @@ from django.test import (
) )
from django.test.runner import DiscoverRunner, dependency_ordered from django.test.runner import DiscoverRunner, dependency_ordered
from django.test.testcases import connections_support_transactions from django.test.testcases import connections_support_transactions
from django.utils import six
from django.utils.encoding import force_text
from .models import Person from .models import Person
@ -337,32 +335,6 @@ class SetupDatabasesTests(unittest.TestCase):
) )
class DeprecationDisplayTest(AdminScriptTestCase):
# tests for 19546
def setUp(self):
settings = {
'DATABASES': '{"default": {"ENGINE":"django.db.backends.sqlite3", "NAME":":memory:"}}'
}
self.write_settings('settings.py', sdict=settings)
def tearDown(self):
self.remove_settings('settings.py')
def test_runner_deprecation_verbosity_default(self):
args = ['test', '--settings=test_project.settings', 'test_runner_deprecation_app']
out, err = self.run_django_admin(args)
self.assertIn("Ran 1 test", force_text(err))
# change "NextVersion" to "RemovedInDjango\d+" in Django 1.11.
six.assertRegex(self, err, r"RemovedInNextVersionWarning: warning from test")
six.assertRegex(self, err, r"RemovedInNextVersionWarning: module-level warning from deprecation_app")
def test_runner_deprecation_verbosity_zero(self):
args = ['test', '--settings=test_project.settings', '--verbosity=0', 'test_runner_deprecation_app']
out, err = self.run_django_admin(args)
self.assertIn("Ran 1 test", err)
self.assertNotIn("warning from test", err)
class AutoIncrementResetTest(TransactionTestCase): class AutoIncrementResetTest(TransactionTestCase):
""" """
Here we test creating the same model two times in different test methods, Here we test creating the same model two times in different test methods,

View File

@ -1,11 +0,0 @@
import warnings
from django.test import TestCase
from django.utils.deprecation import RemovedInNextVersionWarning
warnings.warn("module-level warning from deprecation_app", RemovedInNextVersionWarning)
class DummyTest(TestCase):
def test_warn(self):
warnings.warn("warning from test", RemovedInNextVersionWarning)