Ticket #12012: t12012-alpha1.diff
File t12012-alpha1.diff, 43.3 KB (added by , 14 years ago) |
---|
-
TabularUnified django/conf/__init__.py
diff -r e943e3ecbf20 django/conf/__init__.py
a b 16 16 17 17 ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" 18 18 19 19 20 class LazySettings(LazyObject): 20 21 """ 21 22 A lazy proxy for either global Django settings or a custom settings object. … … 114 115 os.environ['TZ'] = self.TIME_ZONE 115 116 time.tzset() 116 117 118 # Settings are configured, so we can set up the logger 119 # First find the logging configuration function ... 120 logging_config_path, logging_config_func_name = self.LOGGING_CONFIG.rsplit('.', 1) 121 logging_config_module = importlib.import_module(logging_config_path) 122 logging_config_func = getattr(logging_config_module, logging_config_func_name) 123 124 # ... then invoke it with the logging settings 125 logging_config_func(self.LOGGING) 126 117 127 class UserSettingsHolder(object): 118 128 """ 119 129 Holder for user configured settings. -
TabularUnified django/conf/global_settings.py
diff -r e943e3ecbf20 django/conf/global_settings.py
a b 499 499 # django.contrib.messages to avoid imports in this settings file. 500 500 501 501 ########### 502 # LOGGING # 503 ########### 504 505 LOGGING_CONFIG = 'django.utils.log.dictConfig' 506 LOGGING = { 507 'version': 1, 508 'disable_existing_loggers': False, 509 'handlers': { 510 'null': { 511 'level':'DEBUG', 512 'class':'django.utils.log.NullHandler', 513 }, 514 'mail_admins': { 515 'level': 'ERROR', 516 'class': 'django.utils.log.AdminEmailHandler' 517 } 518 }, 519 'loggers': { 520 'django': { 521 'handlers':['null'], 522 'propagate': True, 523 'level':'INFO', 524 }, 525 'django.request':{ 526 'handlers': ['mail_admins'], 527 'level': 'ERROR', 528 'propagate': True, 529 }, 530 } 531 } 532 533 ########### 502 534 # TESTING # 503 535 ########### 504 536 -
TabularUnified django/conf/project_template/settings.py
diff -r e943e3ecbf20 django/conf/project_template/settings.py
a b 94 94 # Uncomment the next line to enable admin documentation: 95 95 # 'django.contrib.admindocs', 96 96 ) 97 98 LOGGING = { 99 'version': 1, 100 'disable_existing_loggers': False, 101 'handlers': { 102 'console':{ 103 'level':'DEBUG', 104 'class':'logging.StreamHandler', 105 }, 106 'mail_admins': { 107 'level': 'ERROR', 108 'class': 'django.utils.log.AdminEmailHandler' 109 } 110 }, 111 'loggers': { 112 'django': { 113 'handlers':['console'], 114 'propagate': True, 115 'level':'INFO', 116 }, 117 'django.request':{ 118 'handlers': ['mail_admins'], 119 'level': 'ERROR', 120 'propagate': True, 121 }, 122 } 123 } -
TabularUnified django/core/handlers/base.py
diff -r e943e3ecbf20 django/core/handlers/base.py
a b 1 import logging 1 2 import sys 2 3 3 4 from django import http … … 5 6 from django.utils.encoding import force_unicode 6 7 from django.utils.importlib import import_module 7 8 9 logger = logging.getLogger('django.request') 10 11 8 12 class BaseHandler(object): 9 13 # Changes that are always applied to a response (in this order). 10 14 response_fixes = [ … … 118 122 119 123 return response 120 124 except http.Http404, e: 125 logger.warning('404 Not Found: %s' % request.path, extra={'request': request}) 121 126 if settings.DEBUG: 122 127 from django.views import debug 123 128 return debug.technical_404_response(request, e) … … 131 136 finally: 132 137 receivers = signals.got_request_exception.send(sender=self.__class__, request=request) 133 138 except exceptions.PermissionDenied: 139 logger.warning('403 Forbidden (Permission denied): %s' % request.path, extra={'request': request}) 134 140 return http.HttpResponseForbidden('<h1>Permission denied</h1>') 135 141 except SystemExit: 136 142 # Allow sys.exit() to actually exit. See tickets #1023 and #4701 … … 155 161 available would be an error. 156 162 """ 157 163 from django.conf import settings 158 from django.core.mail import mail_admins159 164 160 165 if settings.DEBUG_PROPAGATE_EXCEPTIONS: 161 166 raise … … 164 169 from django.views import debug 165 170 return debug.technical_500_response(request, *exc_info) 166 171 167 # When DEBUG is False, send an error message to the admins. 168 subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path) 169 try: 170 request_repr = repr(request) 171 except: 172 request_repr = "Request repr() unavailable" 173 message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr) 174 mail_admins(subject, message, fail_silently=True) 172 logger.error('500 Internal Server Error: %s' % request.path, 173 exc_info=exc_info, 174 extra={'request':request} 175 ) 176 175 177 # If Http500 handler is not installed, re-raise last exception 176 178 if resolver.urlconf_module is None: 177 179 raise exc_info[1], None, exc_info[2] … … 179 181 callback, param_dict = resolver.resolve500() 180 182 return callback(request, **param_dict) 181 183 182 def _get_traceback(self, exc_info=None):183 "Helper function to return the traceback as a string"184 import traceback185 return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))186 187 184 def apply_response_fixes(self, request, response): 188 185 """ 189 186 Applies each of the functions in self.response_fixes to the request and -
TabularUnified django/core/handlers/modpython.py
diff -r e943e3ecbf20 django/core/handlers/modpython.py
a b 1 import logging 1 2 import os 2 3 from pprint import pformat 4 import sys 3 5 from warnings import warn 4 6 5 7 from django import http … … 9 11 from django.utils import datastructures 10 12 from django.utils.encoding import force_unicode, smart_str, iri_to_uri 11 13 14 logger = logging.getLogger('django.request') 15 16 12 17 # NOTE: do *not* import settings (or any module which eventually imports 13 18 # settings) until after ModPythonHandler has been called; otherwise os.environ 14 19 # won't be set up correctly (with respect to settings). … … 200 205 try: 201 206 request = self.request_class(req) 202 207 except UnicodeDecodeError: 208 logger.warning('400 Bad Request (UnicodeDecodeError): %s' % request.path, 209 exc_info=sys.exc_info(), 210 extra={'request': request} 211 ) 203 212 response = http.HttpResponseBadRequest() 204 213 else: 205 214 response = self.get_response(request) -
TabularUnified django/core/handlers/wsgi.py
diff -r e943e3ecbf20 django/core/handlers/wsgi.py
a b 1 import logging 2 from pprint import pformat 3 import sys 1 4 from threading import Lock 2 from pprint import pformat3 5 try: 4 6 from cStringIO import StringIO 5 7 except ImportError: … … 12 14 from django.utils import datastructures 13 15 from django.utils.encoding import force_unicode, iri_to_uri 14 16 17 logger = logging.getLogger('django.request') 18 19 15 20 # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 16 21 STATUS_CODE_TEXT = { 17 22 100: 'CONTINUE', … … 236 241 try: 237 242 request = self.request_class(environ) 238 243 except UnicodeDecodeError: 244 logger.warning('400 Bad Request (UnicodeDecodeError): %s' % request.path, 245 exc_info=sys.exc_info(), 246 extra={'request': request} 247 ) 239 248 response = http.HttpResponseBadRequest() 240 249 else: 241 250 response = self.get_response(request) -
TabularUnified django/db/backends/util.py
diff -r e943e3ecbf20 django/db/backends/util.py
a b 1 1 import datetime 2 2 import decimal 3 import logging 3 4 from time import time 4 5 5 6 from django.utils.hashcompat import md5_constructor 6 7 8 logger = logging.getLogger('django.db.backends') 9 7 10 class CursorDebugWrapper(object): 8 11 def __init__(self, cursor, db): 9 12 self.cursor = cursor … … 15 18 return self.cursor.execute(sql, params) 16 19 finally: 17 20 stop = time() 21 duration = stop - start 18 22 sql = self.db.ops.last_executed_query(self.cursor, sql, params) 19 23 self.db.queries.append({ 20 24 'sql': sql, 21 'time': "%.3f" % (stop - start),25 'time': "%.3f" % duration, 22 26 }) 27 logger.debug('(%.3f) %s; args=%s' % (duration, sql, params), 28 extra={'duration':duration, 'sql':sql, 'params':params} 29 ) 23 30 24 31 def executemany(self, sql, param_list): 25 32 start = time() … … 27 34 return self.cursor.executemany(sql, param_list) 28 35 finally: 29 36 stop = time() 37 duration = stop - start 30 38 self.db.queries.append({ 31 39 'sql': '%s times: %s' % (len(param_list), sql), 32 'time': "%.3f" % (stop - start),40 'time': "%.3f" % duration, 33 41 }) 42 logger.debug('(%.3f) %s; args=%s' % (duration, sql, param_list), 43 extra={'duration':duration, 'sql':sql, 'params':param_list} 44 ) 34 45 35 46 def __getattr__(self, attr): 36 47 if attr in self.__dict__: -
TabularUnified django/db/models/loading.py
diff -r e943e3ecbf20 django/db/models/loading.py
a b 55 55 try: 56 56 if self.loaded: 57 57 return 58 # First, try to invoke the startup sequence for every app. 59 # Only do this once, and at the top level of nesting. 60 if not self.nesting_level: 61 for app_name in settings.INSTALLED_APPS: 62 app_module = import_module(app_name) 63 if module_has_submodule(app_module, 'startup'): 64 import_module('.startup', app_name) 65 # Now try to load every app 58 66 for app_name in settings.INSTALLED_APPS: 59 67 if app_name in self.handled: 60 68 continue 61 69 self.load_app(app_name, True) 70 # Check to see if we've imported everything. 71 # If some apps have been postponed, try to load them again. 62 72 if not self.nesting_level: 63 73 for app_name in self.postponed: 64 74 self.load_app(app_name) -
TabularUnified django/middleware/common.py
diff -r e943e3ecbf20 django/middleware/common.py
a b 1 import logging 1 2 import re 2 3 3 4 from django.conf import settings … … 7 8 from django.core import urlresolvers 8 9 from django.utils.hashcompat import md5_constructor 9 10 11 logger = logging.getLogger('django.request') 12 13 10 14 class CommonMiddleware(object): 11 15 """ 12 16 "Common" middleware for taking care of some basic operations: … … 38 42 if 'HTTP_USER_AGENT' in request.META: 39 43 for user_agent_regex in settings.DISALLOWED_USER_AGENTS: 40 44 if user_agent_regex.search(request.META['HTTP_USER_AGENT']): 45 logger.warning('403 Forbidden (User agent): %s' % request.path, 46 extra={'request': request} 47 ) 41 48 return http.HttpResponseForbidden('<h1>Forbidden</h1>') 42 49 43 50 # Check for a redirect based on settings.APPEND_SLASH -
TabularUnified django/middleware/csrf.py
diff -r e943e3ecbf20 django/middleware/csrf.py
a b 6 6 """ 7 7 8 8 import itertools 9 import logging 9 10 import re 10 11 import random 11 12 … … 20 21 21 22 _HTML_TYPES = ('text/html', 'application/xhtml+xml') 22 23 24 logger = logging.getLogger('django.request') 25 23 26 # Use the system (hardware-based) random number generator if it exists. 24 27 if hasattr(random, 'SystemRandom'): 25 28 randrange = random.SystemRandom().randrange … … 169 172 # we can use strict Referer checking. 170 173 referer = request.META.get('HTTP_REFERER') 171 174 if referer is None: 175 logger.warning('403 Forbidden (%s): %s' % (REASON_NO_COOKIE, request.path), 176 extra={ 177 'request': request, 178 'reason': REASON_NO_REFERER, 179 } 180 ) 172 181 return reject(REASON_NO_REFERER) 173 182 174 183 # The following check ensures that the referer is HTTPS, 175 184 # the domains match and the ports match - the same origin policy. 176 185 good_referer = 'https://%s/' % request.get_host() 177 186 if not referer.startswith(good_referer): 178 return reject(REASON_BAD_REFERER % 179 (referer, good_referer)) 187 reason = REASON_BAD_REFERER % (referer, good_referer) 188 logger.warning('403 Forbidden (%s): %s' % (reason, request.path), 189 extra={ 190 'request': request, 191 'reason': reason, 192 } 193 ) 194 return reject(reason) 180 195 181 196 # If the user didn't already have a CSRF cookie, then fall back to 182 197 # the Django 1.1 method (hash of session ID), so a request is not … … 190 205 # No CSRF cookie and no session cookie. For POST requests, 191 206 # we insist on a CSRF cookie, and in this way we can avoid 192 207 # all CSRF attacks, including login CSRF. 208 logger.warning('403 Forbidden (%s): %s' % (REASON_NO_COOKIE, request.path), 209 extra={ 210 'request': request, 211 'reason': REASON_NO_COOKIE, 212 } 213 ) 193 214 return reject(REASON_NO_COOKIE) 194 215 else: 195 216 csrf_token = request.META["CSRF_COOKIE"] … … 199 220 if request_csrf_token != csrf_token: 200 221 if cookie_is_new: 201 222 # probably a problem setting the CSRF cookie 223 logger.warning('403 Forbidden (%s): %s' % (REASON_NO_CSRF_COOKIE, request.path), 224 extra={ 225 'request': request, 226 'reason': REASON_NO_CSRF_COOKIE, 227 } 228 ) 202 229 return reject(REASON_NO_CSRF_COOKIE) 203 230 else: 231 logger.warning('403 Forbidden (%s): %s' % (REASON_BAD_TOKEN, request.path), 232 extra={ 233 'request': request, 234 'reason': REASON_BAD_TOKEN, 235 } 236 ) 204 237 return reject(REASON_BAD_TOKEN) 205 238 206 239 return accept() -
TabularUnified new file django/utils/dictconfig.py
diff -r e943e3ecbf20 django/utils/dictconfig.py
- + 1 # This is a copy of the Python logging.config.dictconfig module, 2 # reproduced with permission. It is provided here for backwards 3 # compatibility for Python versions prior to 2.7. 4 # 5 # Copyright 2009-2010 by Vinay Sajip. All Rights Reserved. 6 # 7 # Permission to use, copy, modify, and distribute this software and its 8 # documentation for any purpose and without fee is hereby granted, 9 # provided that the above copyright notice appear in all copies and that 10 # both that copyright notice and this permission notice appear in 11 # supporting documentation, and that the name of Vinay Sajip 12 # not be used in advertising or publicity pertaining to distribution 13 # of the software without specific, written prior permission. 14 # VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15 # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 16 # VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17 # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 18 # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 19 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 21 import logging.handlers 22 import re 23 import sys 24 import types 25 26 IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) 27 28 def valid_ident(s): 29 m = IDENTIFIER.match(s) 30 if not m: 31 raise ValueError('Not a valid Python identifier: %r' % s) 32 return True 33 34 # 35 # This function is defined in logging only in recent versions of Python 36 # 37 try: 38 from logging import _checkLevel 39 except ImportError: 40 def _checkLevel(level): 41 if isinstance(level, int): 42 rv = level 43 elif str(level) == level: 44 if level not in logging._levelNames: 45 raise ValueError('Unknown level: %r' % level) 46 rv = logging._levelNames[level] 47 else: 48 raise TypeError('Level not an integer or a ' 49 'valid string: %r' % level) 50 return rv 51 52 # The ConvertingXXX classes are wrappers around standard Python containers, 53 # and they serve to convert any suitable values in the container. The 54 # conversion converts base dicts, lists and tuples to their wrapped 55 # equivalents, whereas strings which match a conversion format are converted 56 # appropriately. 57 # 58 # Each wrapper should have a configurator attribute holding the actual 59 # configurator to use for conversion. 60 61 class ConvertingDict(dict): 62 """A converting dictionary wrapper.""" 63 64 def __getitem__(self, key): 65 value = dict.__getitem__(self, key) 66 result = self.configurator.convert(value) 67 #If the converted value is different, save for next time 68 if value is not result: 69 self[key] = result 70 if type(result) in (ConvertingDict, ConvertingList, 71 ConvertingTuple): 72 result.parent = self 73 result.key = key 74 return result 75 76 def get(self, key, default=None): 77 value = dict.get(self, key, default) 78 result = self.configurator.convert(value) 79 #If the converted value is different, save for next time 80 if value is not result: 81 self[key] = result 82 if type(result) in (ConvertingDict, ConvertingList, 83 ConvertingTuple): 84 result.parent = self 85 result.key = key 86 return result 87 88 def pop(self, key, default=None): 89 value = dict.pop(self, key, default) 90 result = self.configurator.convert(value) 91 if value is not result: 92 if type(result) in (ConvertingDict, ConvertingList, 93 ConvertingTuple): 94 result.parent = self 95 result.key = key 96 return result 97 98 class ConvertingList(list): 99 """A converting list wrapper.""" 100 def __getitem__(self, key): 101 value = list.__getitem__(self, key) 102 result = self.configurator.convert(value) 103 #If the converted value is different, save for next time 104 if value is not result: 105 self[key] = result 106 if type(result) in (ConvertingDict, ConvertingList, 107 ConvertingTuple): 108 result.parent = self 109 result.key = key 110 return result 111 112 def pop(self, idx=-1): 113 value = list.pop(self, idx) 114 result = self.configurator.convert(value) 115 if value is not result: 116 if type(result) in (ConvertingDict, ConvertingList, 117 ConvertingTuple): 118 result.parent = self 119 return result 120 121 class ConvertingTuple(tuple): 122 """A converting tuple wrapper.""" 123 def __getitem__(self, key): 124 value = tuple.__getitem__(self, key) 125 result = self.configurator.convert(value) 126 if value is not result: 127 if type(result) in (ConvertingDict, ConvertingList, 128 ConvertingTuple): 129 result.parent = self 130 result.key = key 131 return result 132 133 class BaseConfigurator(object): 134 """ 135 The configurator base class which defines some useful defaults. 136 """ 137 138 CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$') 139 140 WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') 141 DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') 142 INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') 143 DIGIT_PATTERN = re.compile(r'^\d+$') 144 145 value_converters = { 146 'ext' : 'ext_convert', 147 'cfg' : 'cfg_convert', 148 } 149 150 # We might want to use a different one, e.g. importlib 151 importer = __import__ 152 153 def __init__(self, config): 154 self.config = ConvertingDict(config) 155 self.config.configurator = self 156 157 def resolve(self, s): 158 """ 159 Resolve strings to objects using standard import and attribute 160 syntax. 161 """ 162 name = s.split('.') 163 used = name.pop(0) 164 found = self.importer(used) 165 for frag in name: 166 used += '.' + frag 167 try: 168 found = getattr(found, frag) 169 except AttributeError: 170 self.importer(used) 171 found = getattr(found, frag) 172 return found 173 174 def ext_convert(self, value): 175 """Default converter for the ext:// protocol.""" 176 return self.resolve(value) 177 178 def cfg_convert(self, value): 179 """Default converter for the cfg:// protocol.""" 180 rest = value 181 m = self.WORD_PATTERN.match(rest) 182 if m is None: 183 raise ValueError("Unable to convert %r" % value) 184 else: 185 rest = rest[m.end():] 186 d = self.config[m.groups()[0]] 187 #print d, rest 188 while rest: 189 m = self.DOT_PATTERN.match(rest) 190 if m: 191 d = d[m.groups()[0]] 192 else: 193 m = self.INDEX_PATTERN.match(rest) 194 if m: 195 idx = m.groups()[0] 196 if not self.DIGIT_PATTERN.match(idx): 197 d = d[idx] 198 else: 199 try: 200 n = int(idx) # try as number first (most likely) 201 d = d[n] 202 except TypeError: 203 d = d[idx] 204 if m: 205 rest = rest[m.end():] 206 else: 207 raise ValueError('Unable to convert ' 208 '%r at %r' % (value, rest)) 209 #rest should be empty 210 return d 211 212 def convert(self, value): 213 """ 214 Convert values to an appropriate type. dicts, lists and tuples are 215 replaced by their converting alternatives. Strings are checked to 216 see if they have a conversion format and are converted if they do. 217 """ 218 if not isinstance(value, ConvertingDict) and isinstance(value, dict): 219 value = ConvertingDict(value) 220 value.configurator = self 221 elif not isinstance(value, ConvertingList) and isinstance(value, list): 222 value = ConvertingList(value) 223 value.configurator = self 224 elif not isinstance(value, ConvertingTuple) and\ 225 isinstance(value, tuple): 226 value = ConvertingTuple(value) 227 value.configurator = self 228 elif isinstance(value, basestring): # str for py3k 229 m = self.CONVERT_PATTERN.match(value) 230 if m: 231 d = m.groupdict() 232 prefix = d['prefix'] 233 converter = self.value_converters.get(prefix, None) 234 if converter: 235 suffix = d['suffix'] 236 converter = getattr(self, converter) 237 value = converter(suffix) 238 return value 239 240 def configure_custom(self, config): 241 """Configure an object with a user-supplied factory.""" 242 c = config.pop('()') 243 if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: 244 c = self.resolve(c) 245 props = config.pop('.', None) 246 # Check for valid identifiers 247 kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) 248 result = c(**kwargs) 249 if props: 250 for name, value in props.items(): 251 setattr(result, name, value) 252 return result 253 254 def as_tuple(self, value): 255 """Utility function which converts lists to tuples.""" 256 if isinstance(value, list): 257 value = tuple(value) 258 return value 259 260 class DictConfigurator(BaseConfigurator): 261 """ 262 Configure logging using a dictionary-like object to describe the 263 configuration. 264 """ 265 266 def configure(self): 267 """Do the configuration.""" 268 269 config = self.config 270 if 'version' not in config: 271 raise ValueError("dictionary doesn't specify a version") 272 if config['version'] != 1: 273 raise ValueError("Unsupported version: %s" % config['version']) 274 incremental = config.pop('incremental', False) 275 EMPTY_DICT = {} 276 logging._acquireLock() 277 try: 278 if incremental: 279 handlers = config.get('handlers', EMPTY_DICT) 280 # incremental handler config only if handler name 281 # ties in to logging._handlers (Python 2.7) 282 if sys.version_info[:2] == (2, 7): 283 for name in handlers: 284 if name not in logging._handlers: 285 raise ValueError('No handler found with ' 286 'name %r' % name) 287 else: 288 try: 289 handler = logging._handlers[name] 290 handler_config = handlers[name] 291 level = handler_config.get('level', None) 292 if level: 293 handler.setLevel(_checkLevel(level)) 294 except StandardError, e: 295 raise ValueError('Unable to configure handler ' 296 '%r: %s' % (name, e)) 297 loggers = config.get('loggers', EMPTY_DICT) 298 for name in loggers: 299 try: 300 self.configure_logger(name, loggers[name], True) 301 except StandardError, e: 302 raise ValueError('Unable to configure logger ' 303 '%r: %s' % (name, e)) 304 root = config.get('root', None) 305 if root: 306 try: 307 self.configure_root(root, True) 308 except StandardError, e: 309 raise ValueError('Unable to configure root ' 310 'logger: %s' % e) 311 else: 312 disable_existing = config.pop('disable_existing_loggers', True) 313 314 logging._handlers.clear() 315 del logging._handlerList[:] 316 317 # Do formatters first - they don't refer to anything else 318 formatters = config.get('formatters', EMPTY_DICT) 319 for name in formatters: 320 try: 321 formatters[name] = self.configure_formatter( 322 formatters[name]) 323 except StandardError, e: 324 raise ValueError('Unable to configure ' 325 'formatter %r: %s' % (name, e)) 326 # Next, do filters - they don't refer to anything else, either 327 filters = config.get('filters', EMPTY_DICT) 328 for name in filters: 329 try: 330 filters[name] = self.configure_filter(filters[name]) 331 except StandardError, e: 332 raise ValueError('Unable to configure ' 333 'filter %r: %s' % (name, e)) 334 335 # Next, do handlers - they refer to formatters and filters 336 # As handlers can refer to other handlers, sort the keys 337 # to allow a deterministic order of configuration 338 handlers = config.get('handlers', EMPTY_DICT) 339 for name in sorted(handlers): 340 try: 341 handler = self.configure_handler(handlers[name]) 342 handler.name = name 343 handlers[name] = handler 344 except StandardError, e: 345 raise ValueError('Unable to configure handler ' 346 '%r: %s' % (name, e)) 347 # Next, do loggers - they refer to handlers and filters 348 349 #we don't want to lose the existing loggers, 350 #since other threads may have pointers to them. 351 #existing is set to contain all existing loggers, 352 #and as we go through the new configuration we 353 #remove any which are configured. At the end, 354 #what's left in existing is the set of loggers 355 #which were in the previous configuration but 356 #which are not in the new configuration. 357 root = logging.root 358 existing = root.manager.loggerDict.keys() 359 #The list needs to be sorted so that we can 360 #avoid disabling child loggers of explicitly 361 #named loggers. With a sorted list it is easier 362 #to find the child loggers. 363 existing.sort() 364 #We'll keep the list of existing loggers 365 #which are children of named loggers here... 366 child_loggers = [] 367 #now set up the new ones... 368 loggers = config.get('loggers', EMPTY_DICT) 369 for name in loggers: 370 if name in existing: 371 i = existing.index(name) 372 prefixed = name + "." 373 pflen = len(prefixed) 374 num_existing = len(existing) 375 i = i + 1 # look at the entry after name 376 while (i < num_existing) and\ 377 (existing[i][:pflen] == prefixed): 378 child_loggers.append(existing[i]) 379 i = i + 1 380 existing.remove(name) 381 try: 382 self.configure_logger(name, loggers[name]) 383 except StandardError, e: 384 raise ValueError('Unable to configure logger ' 385 '%r: %s' % (name, e)) 386 387 #Disable any old loggers. There's no point deleting 388 #them as other threads may continue to hold references 389 #and by disabling them, you stop them doing any logging. 390 #However, don't disable children of named loggers, as that's 391 #probably not what was intended by the user. 392 for log in existing: 393 logger = root.manager.loggerDict[log] 394 if log in child_loggers: 395 logger.level = logging.NOTSET 396 logger.handlers = [] 397 logger.propagate = True 398 elif disable_existing: 399 logger.disabled = True 400 401 # And finally, do the root logger 402 root = config.get('root', None) 403 if root: 404 try: 405 self.configure_root(root) 406 except StandardError, e: 407 raise ValueError('Unable to configure root ' 408 'logger: %s' % e) 409 finally: 410 logging._releaseLock() 411 412 def configure_formatter(self, config): 413 """Configure a formatter from a dictionary.""" 414 if '()' in config: 415 factory = config['()'] # for use in exception handler 416 try: 417 result = self.configure_custom(config) 418 except TypeError, te: 419 if "'format'" not in str(te): 420 raise 421 #Name of parameter changed from fmt to format. 422 #Retry with old name. 423 #This is so that code can be used with older Python versions 424 #(e.g. by Django) 425 config['fmt'] = config.pop('format') 426 config['()'] = factory 427 result = self.configure_custom(config) 428 else: 429 fmt = config.get('format', None) 430 dfmt = config.get('datefmt', None) 431 result = logging.Formatter(fmt, dfmt) 432 return result 433 434 def configure_filter(self, config): 435 """Configure a filter from a dictionary.""" 436 if '()' in config: 437 result = self.configure_custom(config) 438 else: 439 name = config.get('name', '') 440 result = logging.Filter(name) 441 return result 442 443 def add_filters(self, filterer, filters): 444 """Add filters to a filterer from a list of names.""" 445 for f in filters: 446 try: 447 filterer.addFilter(self.config['filters'][f]) 448 except StandardError, e: 449 raise ValueError('Unable to add filter %r: %s' % (f, e)) 450 451 def configure_handler(self, config): 452 """Configure a handler from a dictionary.""" 453 formatter = config.pop('formatter', None) 454 if formatter: 455 try: 456 formatter = self.config['formatters'][formatter] 457 except StandardError, e: 458 raise ValueError('Unable to set formatter ' 459 '%r: %s' % (formatter, e)) 460 level = config.pop('level', None) 461 filters = config.pop('filters', None) 462 if '()' in config: 463 c = config.pop('()') 464 if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: 465 c = self.resolve(c) 466 factory = c 467 else: 468 klass = self.resolve(config.pop('class')) 469 #Special case for handler which refers to another handler 470 if issubclass(klass, logging.handlers.MemoryHandler) and\ 471 'target' in config: 472 try: 473 config['target'] = self.config['handlers'][config['target']] 474 except StandardError, e: 475 raise ValueError('Unable to set target handler ' 476 '%r: %s' % (config['target'], e)) 477 elif issubclass(klass, logging.handlers.SMTPHandler) and\ 478 'mailhost' in config: 479 config['mailhost'] = self.as_tuple(config['mailhost']) 480 elif issubclass(klass, logging.handlers.SysLogHandler) and\ 481 'address' in config: 482 config['address'] = self.as_tuple(config['address']) 483 factory = klass 484 kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) 485 try: 486 result = factory(**kwargs) 487 except TypeError, te: 488 if "'stream'" not in str(te): 489 raise 490 #The argument name changed from strm to stream 491 #Retry with old name. 492 #This is so that code can be used with older Python versions 493 #(e.g. by Django) 494 kwargs['strm'] = kwargs.pop('stream') 495 result = factory(**kwargs) 496 if formatter: 497 result.setFormatter(formatter) 498 if level is not None: 499 result.setLevel(_checkLevel(level)) 500 if filters: 501 self.add_filters(result, filters) 502 return result 503 504 def add_handlers(self, logger, handlers): 505 """Add handlers to a logger from a list of names.""" 506 for h in handlers: 507 try: 508 logger.addHandler(self.config['handlers'][h]) 509 except StandardError, e: 510 raise ValueError('Unable to add handler %r: %s' % (h, e)) 511 512 def common_logger_config(self, logger, config, incremental=False): 513 """ 514 Perform configuration which is common to root and non-root loggers. 515 """ 516 level = config.get('level', None) 517 if level is not None: 518 logger.setLevel(_checkLevel(level)) 519 if not incremental: 520 #Remove any existing handlers 521 for h in logger.handlers[:]: 522 logger.removeHandler(h) 523 handlers = config.get('handlers', None) 524 if handlers: 525 self.add_handlers(logger, handlers) 526 filters = config.get('filters', None) 527 if filters: 528 self.add_filters(logger, filters) 529 530 def configure_logger(self, name, config, incremental=False): 531 """Configure a non-root logger from a dictionary.""" 532 logger = logging.getLogger(name) 533 self.common_logger_config(logger, config, incremental) 534 propagate = config.get('propagate', None) 535 if propagate is not None: 536 logger.propagate = propagate 537 538 def configure_root(self, config, incremental=False): 539 """Configure a root logger from a dictionary.""" 540 root = logging.getLogger() 541 self.common_logger_config(root, config, incremental) 542 543 dictConfigClass = DictConfigurator 544 545 def dictConfig(config): 546 """Configure logging using a dictionary.""" 547 dictConfigClass(config).configure() -
TabularUnified new file django/utils/log.py
diff -r e943e3ecbf20 django/utils/log.py
- + 1 import logging 2 from django.core import mail 3 4 # Make sure a NullHandler is available 5 # This was added in Python 2.7/3.2 6 try: 7 from logging import NullHandler 8 except ImportError: 9 class NullHandler(logging.Handler): 10 def emit(self, record): 11 pass 12 13 # Make sure that dictConfig is available 14 # This was added in Python 2.7/3.2 15 try: 16 from logging.config import dictConfig 17 except ImportError: 18 from django.utils.dictconfig import dictConfig 19 20 # Ensure the creation of the Django logger 21 logger = logging.getLogger('django') 22 23 24 class AdminEmailHandler(logging.Handler): 25 """An exception log handler that emails log entries to site admins 26 27 If the request is passed as the first argument to the log record, 28 request data will be provided in the 29 """ 30 def emit(self, record): 31 import traceback 32 from django.conf import settings 33 34 try: 35 request = record.request 36 37 subject = 'Error (%s IP): %s' % ( 38 (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), 39 request.path 40 ) 41 request_repr = repr(request) 42 except: 43 subject = 'Error: Unknown URL' 44 request_repr = "Request repr() unavailable" 45 46 if record.exc_info: 47 stack_trace = '\n'.join(traceback.format_exception(*record.exc_info)) 48 else: 49 stack_trace = 'No stack trace available' 50 51 message = "%s\n\n%s" % (stack_trace, request_repr) 52 mail.mail_admins(subject, message, fail_silently=True) -
TabularUnified django/views/decorators/http.py
diff -r e943e3ecbf20 django/views/decorators/http.py
a b 10 10 from calendar import timegm 11 11 from datetime import timedelta 12 12 from email.Utils import formatdate 13 import logging 13 14 14 15 from django.utils.decorators import decorator_from_middleware, available_attrs 15 16 from django.utils.http import parse_etags, quote_etag 16 17 from django.middleware.http import ConditionalGetMiddleware 17 18 from django.http import HttpResponseNotAllowed, HttpResponseNotModified, HttpResponse 18 19 20 conditional_page = decorator_from_middleware(ConditionalGetMiddleware) 19 21 20 conditional_page = decorator_from_middleware(ConditionalGetMiddleware) 22 logger = logging.getLogger('django.request') 23 21 24 22 25 def require_http_methods(request_method_list): 23 26 """ … … 33 36 def decorator(func): 34 37 def inner(request, *args, **kwargs): 35 38 if request.method not in request_method_list: 39 logger.warning('405 Method Not Allowed (%s): %s' % (request.method, request.path), 40 extra={'request': request} 41 ) 36 42 return HttpResponseNotAllowed(request_method_list) 37 43 return func(request, *args, **kwargs) 38 44 return wraps(func, assigned=available_attrs(func))(inner) … … 111 117 if request.method in ("GET", "HEAD"): 112 118 response = HttpResponseNotModified() 113 119 else: 120 logger.warning('412 Precondition Failed: %s' % request.path, 121 extra={'request': request} 122 ) 114 123 response = HttpResponse(status=412) 115 124 elif if_match and ((not res_etag and "*" in etags) or 116 125 (res_etag and res_etag not in etags)): 126 logger.warning('412 Precondition Failed: %s' % request.path, 127 extra={'request': request} 128 ) 117 129 response = HttpResponse(status=412) 118 130 elif (not if_none_match and if_modified_since and 119 131 request.method == "GET" and -
TabularUnified django/views/generic/simple.py
diff -r e943e3ecbf20 django/views/generic/simple.py
a b 1 import logging 2 1 3 from django.template import loader, RequestContext 2 4 from django.http import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseGone 3 5 6 logger = logging.getLogger('django.request') 7 8 4 9 def direct_to_template(request, template, extra_context=None, mimetype=None, **kwargs): 5 10 """ 6 11 Render a given template with any extra URL parameters in the context as … … 46 51 klass = permanent and HttpResponsePermanentRedirect or HttpResponseRedirect 47 52 return klass(url % kwargs) 48 53 else: 54 logger.warning('410 Gone: %s' % request.path, extra={'request': request}) 49 55 return HttpResponseGone()