diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 4337bd4c114..3b829ce75b7 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -199,13 +199,8 @@ def compat_patch_logging_config(logging_config): while filter_name in filters: filter_name = filter_name + "_" - def _callback(record): - from django.conf import settings - return not settings.DEBUG - filters[filter_name] = { - "()": "django.utils.log.CallbackFilter", - "callback": _callback - } + "()": "django.utils.log.RequireDebugFalse", + } logging_config["handlers"]["mail_admins"]["filters"] = [filter_name] diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 637b5f4d65e..29c9812be50 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -514,13 +514,13 @@ LOGGING_CONFIG = 'django.utils.log.dictConfig' # The default logging configuration. This sends an email to # the site admins on every HTTP 500 error. All other log # records are sent to the bit bucket. + LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'filters': { 'require_debug_false': { - '()': 'django.utils.log.CallbackFilter', - 'callback': lambda r: not DEBUG + '()': 'django.utils.log.RequireDebugFalse', } }, 'handlers': { diff --git a/django/conf/project_template/settings.py b/django/conf/project_template/settings.py index 3a2243fbc61..b92c1163c39 100644 --- a/django/conf/project_template/settings.py +++ b/django/conf/project_template/settings.py @@ -128,8 +128,7 @@ LOGGING = { 'disable_existing_loggers': False, 'filters': { 'require_debug_false': { - '()': 'django.utils.log.CallbackFilter', - 'callback': lambda r: not DEBUG + '()': 'django.utils.log.RequireDebugFalse' } }, 'handlers': { diff --git a/django/utils/log.py b/django/utils/log.py index a8098fcd2aa..8ce37f53096 100644 --- a/django/utils/log.py +++ b/django/utils/log.py @@ -30,6 +30,7 @@ logger = getLogger('django') if not logger.handlers: logger.addHandler(NullHandler()) + class AdminEmailHandler(logging.Handler): """An exception log handler that emails log entries to site admins. @@ -82,8 +83,12 @@ class CallbackFilter(logging.Filter): def __init__(self, callback): self.callback = callback - def filter(self, record): if self.callback(record): return 1 return 0 + + +class RequireDebugFalse(logging.Filter): + def filter(self, record): + return not settings.DEBUG diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 90c5e24e9d2..f12db2817b4 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -593,8 +593,7 @@ to :class:`django.utils.log.AdminEmailHandler` to prevent admin error emails in 'filters': { 'require_debug_false': { - '()': 'django.utils.log.CallbackFilter', - 'callback': lambda r: not DEBUG + '()': 'django.utils.log.RequireDebugFalse' } }, 'handlers': { diff --git a/docs/topics/logging.txt b/docs/topics/logging.txt index f23b529d972..0175e8576ff 100644 --- a/docs/topics/logging.txt +++ b/docs/topics/logging.txt @@ -504,8 +504,8 @@ Python logging module. Filters ------- -Django provides one log filter in addition to those provided by the -Python logging module. +Django provides two log filters in addition to those provided by the Python +logging module. .. class:: CallbackFilter(callback) @@ -516,14 +516,19 @@ Python logging module. through the filter. Handling of that record will not proceed if the callback returns False. +.. class:: RequireDebugFalse() + + .. versionadded:: 1.4 + + This filter will only pass on records when settings.DEBUG is False. + This filter is used as follows in the default :setting:`LOGGING` configuration to ensure that the :class:`AdminEmailHandler` only sends error emails to admins when :setting:`DEBUG` is `False`:: 'filters': { 'require_debug_false': { - '()': 'django.utils.log.CallbackFilter', - 'callback': lambda r: not DEBUG + '()': 'django.utils.log.RequireDebugFalse', } }, 'handlers': { diff --git a/tests/regressiontests/logging_tests/tests.py b/tests/regressiontests/logging_tests/tests.py index 76c5185e665..a2137399516 100644 --- a/tests/regressiontests/logging_tests/tests.py +++ b/tests/regressiontests/logging_tests/tests.py @@ -4,10 +4,10 @@ import copy from django.conf import compat_patch_logging_config from django.test import TestCase -from django.test.utils import override_settings -from django.utils.log import CallbackFilter, getLogger -from django.core import mail +from django.utils.log import CallbackFilter, RequireDebugFalse, getLogger +from django.test.utils import override_settings +from django.core import mail # logging config prior to using filter with mail_admins @@ -30,7 +30,6 @@ OLD_LOGGING = { } - class PatchLoggingConfigTest(TestCase): """ Tests for backward-compat shim for #16288. These tests should be removed in @@ -50,28 +49,30 @@ class PatchLoggingConfigTest(TestCase): config["handlers"]["mail_admins"]["filters"], ['require_debug_false']) - def test_filter_configuration(self): """ - Test that the debug-false filter is a CallbackFilter with a callback - that works as expected (returns ``not DEBUG``). + Test that the auto-added require_debug_false filter is an instance of + `RequireDebugFalse` filter class. """ config = copy.deepcopy(OLD_LOGGING) compat_patch_logging_config(config) flt = config["filters"]["require_debug_false"] + self.assertEqual(flt["()"], "django.utils.log.RequireDebugFalse") - self.assertEqual(flt["()"], "django.utils.log.CallbackFilter") + def test_require_debug_false_filter(self): + """ + Test the RequireDebugFalse filter class. - callback = flt["callback"] + """ + filter_ = RequireDebugFalse() with self.settings(DEBUG=True): - self.assertEqual(callback("record is not used"), False) + self.assertEqual(filter_.filter("record is not used"), False) with self.settings(DEBUG=False): - self.assertEqual(callback("record is not used"), True) - + self.assertEqual(filter_.filter("record is not used"), True) def test_no_patch_if_filters_key_exists(self): """ @@ -110,6 +111,7 @@ class CallbackFilterTest(TestCase): def test_passes_on_record(self): collector = [] + def _callback(record): collector.append(record) return True