linkchecker/linkcheck/log.py
2005-06-02 21:54:41 +00:00

200 lines
5 KiB
Python

# -*- coding: iso-8859-1 -*-
# Copyright (C) 2003-2005 Bastian Kleineidam
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
"""
Logging and debug functions.
"""
import logging
import os
import inspect
import cStringIO as StringIO
import linecache
import sys
import re
import time
try:
import thread as _thread
except ImportError:
import dummy_thread as _thread
# memory leak debugging
#import gc
#gc.enable()
#gc.set_debug(gc.DEBUG_LEAK)
# tracing
_trace_ignore = set()
_trace_filter = set()
def trace_ignore (names):
"""
Add given names to trace ignore list.
"""
_trace_ignore.update(names)
def trace_filter (patterns):
"""
Add given patterns to trace filter list.
"""
_trace_filter.update([re.compile(pat) for pat in patterns])
def trace_clear ():
"""
Clear all trace ignores and filters.
"""
global _trace_ignore
global _trace_filter
_trace_ignore = set()
_trace_filter = set()
def _traceit (frame, event, arg):
"""
Print current executed line.
"""
if event == "line":
name = frame.f_globals["__name__"]
if name in _trace_ignore:
return _traceit
for pat in _trace_filter:
if not pat.match(name):
return _traceit
lineno = frame.f_lineno
filename = frame.f_globals["__file__"]
if filename.endswith(".pyc") or filename.endswith(".pyo"):
filename = filename[:-1]
line = linecache.getline(filename, lineno)
print "THREAD(%d) %.2f %s:%d: %s" % \
(_thread.get_ident(), time.time(), name, lineno, line.rstrip())
return _traceit
def trace ():
"""
Start tracing of the current thread (and the current thread only).
"""
sys.settrace(_traceit)
PRINT_LOCALVARS = False
def _stack_format (stack):
"""
Format a stack trace to a message.
@return: formatted stack message
@rtype: string
"""
s = StringIO.StringIO()
s.write('Traceback:')
s.write(os.linesep)
for frame, fname, lineno, method, lines, i in reversed(stack):
s.write(' File %r, line %d, in %s' % (fname, lineno, method))
s.write(os.linesep)
s.write(' %s' % lines[0].lstrip())
if PRINT_LOCALVARS:
for key, value in frame.f_locals.items():
s.write(" %s = " % key)
# be careful not to cause a new error in the error output
try:
s.write(repr(value))
s.write(os.linesep)
except:
s.write("error in repr() call%s" % os.linesep)
return s.getvalue()
def _log (fun, msg, args, tb=False):
"""
Log a message with given function and an optional traceback.
@return: None
"""
fun(msg, *args)
if tb:
# note: get rid of last parts of the stack
fun(_stack_format(inspect.stack()[2:]))
def debug (logname, msg, *args, **kwargs):
"""
Log a debug message.
return: None
"""
log = logging.getLogger(logname)
if log.isEnabledFor(logging.DEBUG):
_log(log.debug, msg, args, tb=kwargs.get("tb"))
def info (logname, msg, *args, **kwargs):
"""
Log an informational message.
return: None
"""
log = logging.getLogger(logname)
if log.isEnabledFor(logging.INFO):
_log(log.info, msg, args, tb=kwargs.get("tb"))
def warn (logname, msg, *args, **kwargs):
"""
Log a warning.
return: None
"""
log = logging.getLogger(logname)
if log.isEnabledFor(logging.WARN):
_log(log.warn, msg, args, tb=kwargs.get("tb"))
def error (logname, msg, *args, **kwargs):
"""
Log an error.
return: None
"""
log = logging.getLogger(logname)
if log.isEnabledFor(logging.ERROR):
_log(log.error, msg, args, tb=kwargs.get("tb"))
def critical (logname, msg, *args, **kwargs):
"""
Log a critical error.
return: None
"""
log = logging.getLogger(logname)
if log.isEnabledFor(logging.CRITICAL):
_log(log.critical, msg, args, tb=kwargs.get("tb"))
def exception (logname, msg, *args, **kwargs):
"""
Log an exception.
return: None
"""
log = logging.getLogger(logname)
if log.isEnabledFor(logging.ERROR):
_log(log.exception, msg, args, tb=kwargs.get("tb"))
def is_debug (logname):
"""
See if logger is on debug level.
"""
return logging.getLogger(logname).isEnabledFor(logging.DEBUG)