Jelajahi Sumber

Fixed #16568 -- Added RequireDebugFalse filter to prevent sending 500 error emails when DEBUG is True in projects with no explicit LOGGING setting. Thanks to Andreas Pelme for report and patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16840 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Carl Meyer 13 tahun lalu
induk
melakukan
343004c4de

+ 2 - 7
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]

+ 2 - 2
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': {

+ 1 - 2
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': {

+ 6 - 1
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

+ 1 - 2
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': {

+ 9 - 4
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': {

+ 13 - 11
tests/regressiontests/logging_tests/tests.py

@@ -4,12 +4,12 @@ import copy
 
 from django.conf import compat_patch_logging_config
 from django.test import TestCase
+
+from django.utils.log import CallbackFilter, RequireDebugFalse, getLogger
 from django.test.utils import override_settings
-from django.utils.log import CallbackFilter, getLogger
 from django.core import mail
 
 
-
 # logging config prior to using filter with mail_admins
 OLD_LOGGING = {
     'version': 1,
@@ -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