Author: reinhard Date: 2007-07-12 18:08:03 -0500 (Thu, 12 Jul 2007) New Revision: 9758
Added: trunk/gnue-common/src/base/ trunk/gnue-common/src/base/__init__.py trunk/gnue-common/src/base/log.py Modified: trunk/gnue-common/src/apps/GDebug.py Log: Started switch to Python standard logging module. issue123 in-progress Modified: trunk/gnue-common/src/apps/GDebug.py =================================================================== --- trunk/gnue-common/src/apps/GDebug.py 2007-07-12 17:04:23 UTC (rev 9757) +++ trunk/gnue-common/src/apps/GDebug.py 2007-07-12 23:08:03 UTC (rev 9758) @@ -39,60 +39,17 @@ import traceback import types +from gnue.common.base import log + # ----------------------------------------------------------------------------- # Internal global variables # ----------------------------------------------------------------------------- -_fh = sys.__stderr__ # Filehandle to write debug msgs to _DEBUG_LEVELS = [] # Debug levels requested -_DEBUGGER = None # Interactive debugger # ============================================================================= -# Support for redirecting error messages to a file -# ============================================================================= - -# ----------------------------------------------------------------------------- -# Class to catch the stderr stream -# ----------------------------------------------------------------------------- - -class __stderrcatcher: - """ - Output stream for error message. - - sys.stderr is redirected to this class. It prepends "DB000: " in front of - each line and writes everything to the debug file or stderr. - """ - - def __init__ (self, filehandle): - self.filehandle = filehandle - - def write (self, str): - lines = string.split (str, "\n") - while len(lines) and lines [-1] == "": # remove empty lines at the end - del (lines [-1]) - self.filehandle.write (string.join (["DB000: " + s for s in lines], "\n")) - self.filehandle.write ("\n") - self.filehandle.flush () - - def writelines (self, list): - for line in list: - self.write (str) - - -# ----------------------------------------------------------------------------- -# redirect stderr and all debugging output to the given filehandle -# ----------------------------------------------------------------------------- - -def __catchStderr (filehandle): - - global _fh - _fh = filehandle - sys.stderr = __stderrcatcher (filehandle) - - -# ============================================================================= # Support for debugging messages # ============================================================================= @@ -100,7 +57,7 @@ # Placeholders for gDebug/gEnter/gLeave if no debug output is desired at all # ----------------------------------------------------------------------------- -def __noDebug (level, message, dropToDebugger = False): +def __noDebug (level, message): return True @@ -117,87 +74,22 @@ # ----------------------------------------------------------------------------- -# Set the debugger -# ----------------------------------------------------------------------------- - -def setDebugger (debugger): - """ - This function informs the debug system about the use of Python's interactive - debugger. If this is called, subsequent calls to gDebug with the parameter - dropToDebugger set will switch the interactive debugger to trace mode. - """ - - global _DEBUGGER - _DEBUGGER = debugger - - -# ----------------------------------------------------------------------------- -# Dump a message to the debug-output -# ----------------------------------------------------------------------------- - -def __dumpMessage (level, filename, message, dropToDebugger = False): - """ - Write a message to the debug-output. - - @param level: the debug-level the message will be logged in - @param filename: the filename the message originated from - @param message: the message to be logged - @param dropToDebugger: if set to True, Python's interactive debugger will be - switched to trace mode. This requires that setDebugger has been called - before. - """ - - global _fh, _DEBUGGER - - s = time.time () - msecs = (s - long (s)) * 1000 - t = time.strftime ('%Y-%m-%d %H:%M:%S', time.localtime (s)) - stamp = "%s.%03d" % (t, msecs) - - lines = "%s" % message - for line in lines.splitlines (): - _fh.write ("DB%03d: %s %s%s%s" % (level, stamp, filename, line, os.linesep)) - _fh.flush () - - if dropToDebugger and _DEBUGGER: - _DEBUGGER.set_trace () - - -# ----------------------------------------------------------------------------- # Write debug message # ----------------------------------------------------------------------------- -def gDebug (level, message, dropToDebugger = False): +def gDebug (level, message): """ Write a message to the debug-output. This function is available in the global namespace. @param level: the debug-level the message will be logged in @param message: the message to be logged - @param dropToDebugger: if set to True, Python's interactive debugger will be - switched to trace mode. This requires that setDebugger has been called - before. @return: Always true so it can be filtered out via assert """ - if level in _DEBUG_LEVELS : + if level in _DEBUG_LEVELS: + log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message) - # Just to be sure... - if isinstance (message, types.UnicodeType): - message = message.encode ('utf-8') - - # Find out the file from where we were called - caller = traceback.extract_stack()[-2] - try: - if caller[0][-3:] == '.py': - file = "[%s:%s] " % (string.split(caller[0][:-3],'/')[-1], caller[1]) - else: - file = "[%s:%s] " % (string.split(caller[0],'/')[-1], caller[1]) - except: - file = "" - - __dumpMessage (level, file, message, dropToDebugger) - return True # ----------------------------------------------------------------------------- @@ -247,16 +139,8 @@ message = "Entering function %s (%s)" % (funcName, string.join (params, ", ")) - path = frame.f_code.co_filename - if path [-3:] == '.py': - path = string.split (path [:-3], '/') [-1] - else: - path = string.split (path, '/') [-1] + log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message) - filename = "[%s:%s] " % (path, frame.f_code.co_firstlineno) - - __dumpMessage (level, filename, message) - finally: # Make sure to release the reference to the frame object. This keeps # garbage collection doing a fine job :) @@ -301,23 +185,16 @@ resStr = len (result) and ' == %s' % repr (result [0]) or '' message = "Leaving function %s (%s)%s" % (fName, hId, resStr) - path = frame.f_code.co_filename - if path [-3:] == '.py': - path = string.split (path [:-3], '/') [-1] - else: - path = string.split (path, '/') [-1] + log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message) - filename = "[%s:%s] " % (path, frame.f_code.co_firstlineno) - - __dumpMessage (level, filename, message) - finally: # Make sure to release the reference to the frame object. This keeps # garbage collection doing a fine job :) del frame - return True + return True + # ----------------------------------------------------------------------------- # Set debug levels to use and initialize debugging # ----------------------------------------------------------------------------- @@ -350,46 +227,13 @@ __builtin__.__dict__ ['gEnter'] = gEnter __builtin__.__dict__ ['gLeave'] = gLeave - # Redirect debugging and error output to a file if requested - if (file): - __catchStderr (open (file, 'a')) - else: - __catchStderr (sys.__stderr__) - # ----------------------------------------------------------------------------- # Deprecated, for compatibility # ----------------------------------------------------------------------------- -def printMesg (level, message, dropToDebugger = False): +def printMesg (level, message): """ This function is deprecated - use gDebug instead """ - __builtin__.__dict__ ['gDebug'] (level, message, dropToDebugger) - - -# ----------------------------------------------------------------------------- -# FIXME: is it save to remove the following stuff? -# ----------------------------------------------------------------------------- - -class GETrace(Exception): - # - #Exception class representing a debug message - #not yet used for anything and probably won't be :) - # - def __init__(self, level=0, message="Trace Message"): - Exception.__init__(self) - self.level = level - self.message = message - -def handleException(exc_info): - # - # Not used at present - # - type, exception, traceback = exc_info - if (isinstance(exception, GETrace) ): - printMesg( exception.level, exception.message) - elif (not isinstance(exception, SystemExit)): - strings = traceback.format_exception(type, exception, traceback) - text = string.join(strings, '') - printMesg(0, text) + __builtin__.__dict__ ['gDebug'] (level, message) Property changes on: trunk/gnue-common/src/base ___________________________________________________________________ Name: svn:ignore + *.pyc Added: trunk/gnue-common/src/base/__init__.py =================================================================== --- trunk/gnue-common/src/base/__init__.py 2007-07-12 17:04:23 UTC (rev 9757) +++ trunk/gnue-common/src/base/__init__.py 2007-07-12 23:08:03 UTC (rev 9758) @@ -0,0 +1,27 @@ +# GNU Enterprise Common Library - Base Modules +# +# Copyright 2001-2007 Free Software Foundation +# +# This file is part of GNU Enterprise +# +# GNU Enterprise 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, or (at your option) any later version. +# +# GNU Enterprise 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 program; see the file COPYING. If not, +# write to the Free Software Foundation, Inc., 59 Temple Place +# - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +""" +The base package contains a number of modules providing very basic functions +that are used all over the GNU Enterprise tools. +""" Property changes on: trunk/gnue-common/src/base/__init__.py ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/gnue-common/src/base/log.py =================================================================== --- trunk/gnue-common/src/base/log.py 2007-07-12 17:04:23 UTC (rev 9757) +++ trunk/gnue-common/src/base/log.py 2007-07-12 23:08:03 UTC (rev 9758) @@ -0,0 +1,243 @@ +# GNU Enterprise Common Library - Logging support +# +# Copyright 2001-2007 Free Software Foundation +# +# This file is part of GNU Enterprise +# +# GNU Enterprise 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, or (at your option) any later version. +# +# GNU Enterprise 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 program; see the file COPYING. If not, +# write to the Free Software Foundation, Inc., 59 Temple Place +# - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +# We use * and ** magic on purpose. +# pylint: disable-msg=W0142 + +""" +The logging module extends the standard logging module with some convenience +functions related to the logging schema used in GNU Enterprise. +""" + +import inspect +import logging + +__all__ = ['debug', 'info', 'warning', 'deprecated', 'error', 'critical', + 'exception', 'debug_n', 'info_n', 'warning_n', 'deprecated_n', + 'error_n', 'critical_n', 'exception_n'] + + +# TODO: +# - Read debug config +# - function for enter() and leave(), maybe as decorator? +# - function to declare function as deprecated, maybe as decorator? +# - Exception hook + +# ----------------------------------------------------------------------------- +# Log to the logger named after the calling module +# ----------------------------------------------------------------------------- + +def debug(msg, *args, **kwargs): + """ + Write a debug message to the logger named after the calling module. + + @return: always True, so the call can be prefixed with assert. + """ + return debug_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def info(msg, *args, **kwargs): + """ + Write an info message to the logger named after the calling module. + + @return: always True, so the call can be prefixed with assert. + """ + return info_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def warning(msg, *args, **kwargs): + """ + Write a warning message to the logger named after the calling module. + + @return: always True, so the call can be prefixed with assert. + """ + return warning_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def deprecated(msg, *args, **kwargs): + """ + Write a deprecation warning message to the logger named after the calling + module. + + @return: always True, so the call can be prefixed with assert. + """ + return deprecated_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def error(msg, *args, **kwargs): + """ + Write an error message to the logger named after the calling module. + + @return: always True, so the call can be prefixed with assert. + """ + return error_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def critical(msg, *args, **kwargs): + """ + Write a critical error message to the logger named after the calling module. + + @return: always True, so the call can be prefixed with assert. + """ + return critical_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def exception(msg, *args, **kwargs): + """ + Log an exception to the logger named after the calling module. + + @return: always True, so the call can be prefixed with assert. + """ + return exception_n(__caller(), msg, *args, **kwargs) + +# ----------------------------------------------------------------------------- + +def __caller(): + return inspect.stack()[2][0].f_globals['__name__'] + + +# ----------------------------------------------------------------------------- +# Log to a certain logger +# ----------------------------------------------------------------------------- + +def debug_n(name, msg, *args, **kwargs): + """ + Write a debug message to the logger defined through the C{name} parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).debug(msg, *args, **kwargs) + return True + +# ----------------------------------------------------------------------------- + +def info_n(name, msg, *args, **kwargs): + """ + Write an info message to the logger defined through the C{name} parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).info(msg, *args, **kwargs) + return True + +# ----------------------------------------------------------------------------- + +def warning_n(name, msg, *args, **kwargs): + """ + Write a warning message to the logger defined through the C{name} parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).warning(msg, *args, **kwargs) + return True + +# ----------------------------------------------------------------------------- + +def deprecated_n(name, msg, *args, **kwargs): + """ + Write a deprecation warning message to the logger defined through the + C{name} parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).log(31, msg, *args, **kwargs) + return True + +# ----------------------------------------------------------------------------- + +def error_n(name, msg, *args, **kwargs): + """ + Write an error message to the logger defined through the C{name} parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).error(msg, *args, **kwargs) + return True + +# ----------------------------------------------------------------------------- + +def critical_n(name, msg, *args, **kwargs): + """ + Write a critical error message to the logger defined through the C{name} + parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).critical(msg, *args, **kwargs) + return True + +# ----------------------------------------------------------------------------- + +def exception_n(name, msg, *args, **kwargs): + """ + Log an exception to the logger defined through the C{name} parameter. + + @return: always True, so the call can be prefixed with assert. + """ + logging.getLogger(name).exception(msg, *args, **kwargs) + return True + + +# ----------------------------------------------------------------------------- +# Derivate from standard Logger to output correct caller information +# ----------------------------------------------------------------------------- + +class Logger(logging.Logger): + """ + Derivated Logger class to make sure the correct file name is used instead + of "log.py", which is the file actually calling the logger functions. + """ + + def findCaller(self): + """ + Find the stack frame of the caller so that we can note the source + file name, line number and function name. + """ + frame = inspect.currentframe().f_back + while hasattr(frame, 'f_code'): + if frame.f_globals['__name__'] not in [logging.__name__, __name__, + # FIXME: Remove after GDebug has been removed! + 'gnue.common.apps.GDebug']: + code = frame.f_code + return (code.co_filename, frame.f_lineno, code.co_name) + frame = frame.f_back + return ("(unknown file)", 0, "(unknown function)") + +# ----------------------------------------------------------------------------- +# Module initialization +# ----------------------------------------------------------------------------- + +# Use our own Logger class. +logging.setLoggerClass(Logger) + +# Configure logging to a very basic default behaviour to start with. +logging.basicConfig(level=10) + +# Add level for deprecation warnings. +logging.addLevelName(31, 'DEPRECATED') Property changes on: trunk/gnue-common/src/base/log.py ___________________________________________________________________ Name: svn:keywords + Id _______________________________________________ commit-gnue mailing list commit-gnue@gnu.org http://lists.gnu.org/mailman/listinfo/commit-gnue