Package Pyblosxom :: Module _logging
[hide private]
[frames] | no frames]

Source Code for Module Pyblosxom._logging

  1  ####################################################################### 
  2  # This file is part of PyBlosxom. 
  3  # 
  4  # Copyright (c) 2003, 2004, 2005, 2006 Wari Wahab 
  5  #  
  6  # PyBlosxom is distributed under the MIT license.  See the file LICENSE 
  7  # for distribution details. 
  8  # 
  9  # $Id: _logging.py 913 2006-08-08 20:29:42Z willhelm $ 
 10  ####################################################################### 
 11  """ 
 12  Emulates part of the Python2.3 logging module. 
 13   
 14  Note: This will probably not work with Python < 2.2. 
 15  """ 
 16   
 17  __revision__ = "$Revision: 913 $" 
 18   
 19  import os 
 20  import sys 
 21  import time 
 22  import string 
 23  try:  
 24      from cStringIO import StringIO 
 25  except ImportError:  
 26      from StringIO import StringIO 
 27   
 28  _devlogfile = "/tmp/dev-log.log" 
 29  _log = None 
 30   
31 -def dump(msg, *args):
32 """ 33 Utility function to log stuff while working on the _logging module. 34 """ 35 global _log 36 if _log == None or _log.closed: 37 _log = open(_devlogfile, "a") 38 if args: 39 msg = msg % args 40 _log.write(str(msg)) 41 _log.write("\n") 42 _log.flush()
43 44 45 # Log levels 46 CRITICAL = 50 47 FATAL = CRITICAL 48 ERROR = 40 49 WARNING = 30 50 WARN = WARNING 51 INFO = 20 52 DEBUG = 10 53 NOTSET = 0 54 55 # order matters! 56 _names = ['FATAL', 'CRITICAL', 'ERROR', 'WARN', 'WARNING', \ 57 'INFO', 'DEBUG', 'NOTSET'] 58 _levels = {} 59 _level_names = {} 60
61 -def __populate_levels():
62 """ 63 Fills in the _levels and _level_names dictionaries. 64 """ 65 for n in _names: 66 i = eval(n) 67 _levels[n] = i 68 _level_names[i] = n
69 70 __populate_levels() 71 72 73 # _srcfile is used when walking the stack to check when we've got the first 74 # caller stack frame. 75 if string.lower(__file__[-4:]) in ['.pyc', '.pyo']: 76 _srcfile = __file__[:-4] + '.py' 77 else: 78 _srcfile = __file__ 79 _srcfile = os.path.normcase(_srcfile) 80 81 # _startTime is used as the base when calculating the relative time of events 82 _startTime = time.time() 83
84 -def getLevelName(level):
85 """ 86 Return the textual representation of logging level 'level'. 87 88 @param level: Numeric representation of a logging level 89 @type level: C{int} 90 91 @return: Texutal representation of the logging level 92 @rtype: C{str} 93 """ 94 return _level_names.get(level, ("Level %s" % level))
95 96 97 # repository of handlers (for flushing when shutdown is called) 98 _handlers = {} 99
100 -class Filterer(object):
101 """ 102 A stripped down version of the logging.Filterer class. 103 See the logging module for documentation. 104 """
105 - def __init__(self):
106 self.filters = []
107
108 - def addFilter(self, filter):
109 if not (filter in self.filters): 110 self.filters.append(filter)
111
112 - def removeFilter(self, filter):
113 if filter in self.filters: 114 self.filters.remove(filter)
115
116 - def filter(self, record):
117 rv = 1 118 for f in self.filters: 119 if not f.filter(record): 120 rv = 0 121 break 122 return rv
123
124 -class StreamHandler(Filterer):
125 """ 126 A stripped down version of the logging.StreamHandler class. 127 See the logging module for documentation. 128 """
129 - def __init__(self, strm=sys.stderr):
130 Filterer.__init__(self) 131 #dump("StreamHandler.__init__: %s", strm) 132 self.stream = strm 133 self.formatter = None 134 self.level = None 135 global _handlers 136 # store this handler in the global handler repository 137 _handlers[self] = 1
138
139 - def setLevel(self, level):
140 self.level = level
141
142 - def format(self, record):
143 return self.formatter.format(record)
144
145 - def emit(self, record):
146 try: 147 msg = self.format(record) 148 try: 149 self.stream.write("%s\n" % msg) 150 except UnicodeError: 151 self.stream.write("%s\n" % msg.encode("UTF-8")) 152 self.flush() 153 except: 154 self.handleError(record)
155
156 - def handleError(self, record):
157 # handle errors in the logging implementation 158 import traceback 159 ei = sys.exc_info() 160 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) 161 del ei
162
163 - def handle(self, record):
164 rv = self.filter(record) 165 if rv: 166 self.emit(record) 167 return rv
168
169 - def setFormatter(self, formatter):
170 self.formatter = formatter
171
172 - def flush(self):
173 self.stream.flush()
174
175 - def close(self):
176 # do nothing here, could be sys.stdout/stderr 177 pass
178 179
180 -class FileHandler(StreamHandler):
181 """ 182 A stripped down version of the logging.FileHandler class. 183 See the logging module for documentation. 184 """
185 - def __init__(self, filename, mode="a"):
186 super(FileHandler, self).__init__(open(filename, mode)) 187 self.baseFilename = filename 188 self.mode = mode
189
190 - def close(self):
191 self.stream.close()
192 193
194 -class Formatter(object):
195 """ 196 A stripped down version of the logging.Formatter class. 197 See the logging module for documentation. 198 """ 199 converter = time.localtime 200
201 - def __init__(self, fmt="%(message)s"):
202 self._fmt = fmt 203 self.datefmt = None
204
205 - def formatTime(self, record, datefmt=None):
206 ct = self.converter(record.created) 207 if datefmt: 208 s = time.strftime(datefmt, ct) 209 else: 210 t = time.strftime("%Y-%m-%d %H:%M:%S", ct) 211 s = "%s,%03d" % (t, record.msecs) 212 return s
213
214 - def formatException(self, ei):
215 import traceback 216 sio = StringIO() 217 traceback.print_exception(ei[0], ei[1], ei[2], None, sio) 218 s = sio.getvalue() 219 sio.close() 220 if s[-1] == "\n": 221 s = s[:-1] 222 return s
223
224 - def format(self, record):
225 record.message = record.getMessage() 226 if string.find(self._fmt,"%(asctime)") >= 0: 227 record.asctime = self.formatTime(record, self.datefmt) 228 s = self._fmt % record.__dict__ 229 if record.exc_info: 230 if s[-1] != "\n": 231 s = s + "\n" 232 s = s + self.formatException(record.exc_info) 233 return s
234
235 -class LogRecord:
236 """ 237 A stripped down version of the logging.LogRecord class. 238 See the logging module for documentation. 239 """
240 - def __init__(self, name, level, pathname, lineno, msg, args, exc_info):
241 ct = time.time() 242 self.name = name 243 self.msg = msg 244 self.args = args 245 self.levelname = getLevelName(level) 246 self.levelno = level 247 self.pathname = pathname 248 try: 249 self.filename = os.path.basename(pathname) 250 self.module = os.path.splitext(self.filename)[0] 251 except: 252 self.filename = pathname 253 self.module = "Unknown module" 254 self.exc_info = exc_info 255 self.lineno = lineno 256 self.created = ct 257 self.msecs = (ct - long(ct)) * 1000 258 self.relativeCreated = (self.created - _startTime) * 1000 259 if hasattr(os, 'getpid'): 260 self.process = os.getpid() 261 else: 262 self.process = None
263
264 - def __str__(self):
265 return '<LogRecord: %s, %s, %s, %s, "%s">' % \ 266 (self.name, self.levelno, self.pathname, self.lineno, self.msg)
267
268 - def getMessage(self):
269 try: 270 msg = str(self.msg) 271 except UnicodeError: 272 msg = self.msg #Defer encoding till later 273 if self.args: 274 msg = msg % self.args 275 return msg
276 277
278 -class Logger(Filterer):
279 """ 280 A stripped down version of the logging.Logger class. 281 See the logging module for documentation. 282 """
283 - def __init__(self, name, level=NOTSET):
284 Filterer.__init__(self) 285 self.name = name 286 self.setLevel(level) 287 self.handlers = [] 288 self.disabled = 0
289
290 - def _log(self, level, msg, args, exc_info=None):
291 # log the message or not depending on the current loglevel 292 if self.level > level: 293 return 294 if _srcfile: 295 fn, lno = self.__findCaller() 296 else: 297 fn, lno = "<unknown file>", 0 298 if exc_info: 299 exc_info = sys.exc_info() 300 record = self.__makeRecord(self.name, level, fn, lno, \ 301 msg, args, exc_info) 302 self.__callHandlers(record)
303
304 - def __findCaller(self):
305 f = sys._getframe(1) 306 while 1: 307 co = f.f_code 308 filename = os.path.normcase(co.co_filename) 309 if filename == _srcfile: 310 f = f.f_back 311 continue 312 return filename, f.f_lineno
313
314 - def __makeRecord(self, name, level, fn, lno, msg, args, exc_info):
315 return LogRecord(name, level, fn, lno, msg, args, exc_info)
316
317 - def __callHandlers(self, record):
318 for hdlr in self.handlers: 319 if record.levelno >= hdlr.level: 320 hdlr.handle(record)
321 322 323 # public methods 324
325 - def setLevel(self, level):
326 self.level = level
327
328 - def critical(self, msg, *args, **kwargs):
329 apply(self._log, (CRITICAL, msg, args), kwargs)
330 fatal = critical 331
332 - def error(self, msg, *args, **kwargs):
333 apply(self._log, (ERROR, msg, args), kwargs)
334
335 - def warning(self, msg, *args, **kwargs):
336 apply(self._log, (WARNING, msg, args), kwargs)
337 warn = warning 338
339 - def info(self, msg, *args, **kwargs):
340 apply(self._log, (INFO, msg, args), kwargs)
341
342 - def debug(self, msg, *args, **kwargs):
343 apply(self._log, (DEBUG, msg, args), kwargs)
344
345 - def exception(self, msg, *args):
346 apply(self.error, (msg,) + args, {'exc_info': 1})
347
348 - def addHandler(self, hdlr):
349 if not (hdlr in self.handlers): 350 self.handlers.append(hdlr)
351
352 - def removeHandler(self, hdlr):
353 if hdlr in self.handlers: 354 self.handlers.remove(hdlr)
355 356 357 # A dict to keep track of created loggers. 358 _logger_registry = {} 359
360 -def getLogger(log_name=None):
361 """ 362 Creates and returns a logging channel. 363 Registers the created logger in the logger-registry for further reference. 364 """ 365 #dump("getLogger: %s", log_name) 366 global _logger_registry 367 if not log_name: 368 log_name == "root" 369 if not log_name in _logger_registry: 370 _logger_registry[log_name] = Logger(log_name) 371 return _logger_registry[log_name]
372 373
374 -def shutdown():
375 """ 376 Close logfiles and clear the logger-registry. 377 """ 378 #dump("shutdown") 379 global _handlers, _logger_registry 380 for h in _handlers.keys(): 381 h.flush() 382 h.close() 383 _handlers = {} 384 _logger_registry = {}
385