|  | # epydoc -- Logging | 
|  | # | 
|  | # Copyright (C) 2005 Edward Loper | 
|  | # Author: Edward Loper <edloper@loper.org> | 
|  | # URL: <http://epydoc.sf.net> | 
|  | # | 
|  | # $Id: log.py 1488 2007-02-14 00:34:27Z edloper $ | 
|  |  | 
|  | """ | 
|  | Functions used to report messages and progress updates to the user. | 
|  | These functions are delegated to zero or more registered L{Logger} | 
|  | objects, which are responsible for actually presenting the information | 
|  | to the user.  Different interfaces are free to create and register | 
|  | their own C{Logger}s, allowing them to present this information in the | 
|  | manner that is best suited to each interface. | 
|  |  | 
|  | @note: I considered using the standard C{logging} package to provide | 
|  | this functionality.  However, I found that it would be too difficult | 
|  | to get that package to provide the behavior I want (esp. with respect | 
|  | to progress displays; but also with respect to message blocks). | 
|  |  | 
|  | @group Message Severity Levels: DEBUG, INFO, WARNING, ERROR, FATAL | 
|  | """ | 
|  | __docformat__ = 'epytext en' | 
|  |  | 
|  | import sys, os | 
|  |  | 
|  | DEBUG = 10 | 
|  | INFO = 20 | 
|  | DOCSTRING_WARNING = 25 | 
|  | WARNING = 30 | 
|  | ERROR = 40 | 
|  | FATAL = 40 | 
|  |  | 
|  | ###################################################################### | 
|  | # Logger Base Class | 
|  | ###################################################################### | 
|  | class Logger: | 
|  | """ | 
|  | An abstract base class that defines the interface for X{loggers}, | 
|  | which are used by epydoc to report information back to the user. | 
|  | Loggers are responsible for tracking two types of information: | 
|  |  | 
|  | - Messages, such as warnings and errors. | 
|  | - Progress on the current task. | 
|  |  | 
|  | This abstract class allows the command-line interface and the | 
|  | graphical interface to each present this information to the user | 
|  | in the way that's most natural for each interface.  To set up a | 
|  | logger, create a subclass of C{Logger} that overrides all methods, | 
|  | and register it using L{register_logger}. | 
|  | """ | 
|  | #//////////////////////////////////////////////////////////// | 
|  | # Messages | 
|  | #//////////////////////////////////////////////////////////// | 
|  |  | 
|  | def log(self, level, message): | 
|  | """ | 
|  | Display a message. | 
|  |  | 
|  | @param message: The message string to display.  C{message} may | 
|  | contain newlines, but does not need to end in a newline. | 
|  | @param level: An integer value indicating the severity of the | 
|  | message. | 
|  | """ | 
|  |  | 
|  | def close(self): | 
|  | """ | 
|  | Perform any tasks needed to close this logger. | 
|  | """ | 
|  |  | 
|  | #//////////////////////////////////////////////////////////// | 
|  | # Message blocks | 
|  | #//////////////////////////////////////////////////////////// | 
|  |  | 
|  | def start_block(self, header): | 
|  | """ | 
|  | Start a new message block.  Any calls to L{info()}, | 
|  | L{warning()}, or L{error()} that occur between a call to | 
|  | C{start_block} and a corresponding call to C{end_block} will | 
|  | be grouped together, and displayed with a common header. | 
|  | C{start_block} can be called multiple times (to form nested | 
|  | blocks), but every call to C{start_block} I{must} be balanced | 
|  | by a call to C{end_block}. | 
|  | """ | 
|  |  | 
|  | def end_block(self): | 
|  | """ | 
|  | End a warning block.  See L{start_block} for details. | 
|  | """ | 
|  |  | 
|  | #//////////////////////////////////////////////////////////// | 
|  | # Progress bar | 
|  | #//////////////////////////////////////////////////////////// | 
|  |  | 
|  | def start_progress(self, header=None): | 
|  | """ | 
|  | Begin displaying progress for a new task.  C{header} is a | 
|  | description of the task for which progress is being reported. | 
|  | Each call to C{start_progress} must be followed by a call to | 
|  | C{end_progress} (with no intervening calls to | 
|  | C{start_progress}). | 
|  | """ | 
|  |  | 
|  | def end_progress(self): | 
|  | """ | 
|  | Finish off the display of progress for the current task.  See | 
|  | L{start_progress} for more information. | 
|  | """ | 
|  |  | 
|  | def progress(self, percent, message=''): | 
|  | """ | 
|  | Update the progress display. | 
|  |  | 
|  | @param percent: A float from 0.0 to 1.0, indicating how much | 
|  | progress has been made. | 
|  | @param message: A message indicating the most recent action | 
|  | that contributed towards that progress. | 
|  | """ | 
|  |  | 
|  | class SimpleLogger(Logger): | 
|  | def __init__(self, threshold=WARNING): | 
|  | self.threshold = threshold | 
|  | def log(self, level, message): | 
|  | if level >= self.threshold: print message | 
|  |  | 
|  | ###################################################################### | 
|  | # Logger Registry | 
|  | ###################################################################### | 
|  |  | 
|  | _loggers = [] | 
|  | """ | 
|  | The list of registered logging functions. | 
|  | """ | 
|  |  | 
|  | def register_logger(logger): | 
|  | """ | 
|  | Register a logger.  Each call to one of the logging functions | 
|  | defined by this module will be delegated to each registered | 
|  | logger. | 
|  | """ | 
|  | _loggers.append(logger) | 
|  |  | 
|  | def remove_logger(logger): | 
|  | _loggers.remove(logger) | 
|  |  | 
|  | ###################################################################### | 
|  | # Logging Functions | 
|  | ###################################################################### | 
|  | # The following methods all just delegate to the corresponding | 
|  | # methods in the Logger class (above) for each registered logger. | 
|  |  | 
|  | def fatal(*messages): | 
|  | """Display the given fatal message.""" | 
|  | message = ' '.join(['%s' % (m,) for m in messages]) | 
|  | for logger in _loggers: logger.log(FATAL, message) | 
|  |  | 
|  | def error(*messages): | 
|  | """Display the given error message.""" | 
|  | message = ' '.join(['%s' % (m,) for m in messages]) | 
|  | for logger in _loggers: logger.log(ERROR, message) | 
|  |  | 
|  | def warning(*messages): | 
|  | """Display the given warning message.""" | 
|  | message = ' '.join(['%s' % (m,) for m in messages]) | 
|  | for logger in _loggers: logger.log(WARNING, message) | 
|  |  | 
|  | def docstring_warning(*messages): | 
|  | """Display the given docstring warning message.""" | 
|  | message = ' '.join(['%s' % (m,) for m in messages]) | 
|  | for logger in _loggers: logger.log(DOCSTRING_WARNING, message) | 
|  |  | 
|  | def info(*messages): | 
|  | """Display the given informational message.""" | 
|  | message = ' '.join(['%s' % (m,) for m in messages]) | 
|  | for logger in _loggers: logger.log(INFO, message) | 
|  |  | 
|  | def debug(*messages): | 
|  | """Display the given debugging message.""" | 
|  | message = ' '.join(['%s' % (m,) for m in messages]) | 
|  | for logger in _loggers: logger.log(DEBUG, message) | 
|  |  | 
|  | def start_block(header): | 
|  | for logger in _loggers: logger.start_block(header) | 
|  | start_block.__doc__ = Logger.start_block.__doc__ | 
|  |  | 
|  | def end_block(): | 
|  | for logger in _loggers: logger.end_block() | 
|  | end_block.__doc__ = Logger.end_block.__doc__ | 
|  |  | 
|  | def start_progress(header=None): | 
|  | for logger in _loggers: logger.start_progress(header) | 
|  | start_progress.__doc__ = Logger.start_progress.__doc__ | 
|  |  | 
|  | def end_progress(): | 
|  | for logger in _loggers: logger.end_progress() | 
|  | end_progress.__doc__ = Logger.end_progress.__doc__ | 
|  |  | 
|  | def progress(percent, message=''): | 
|  | for logger in _loggers: logger.progress(percent, '%s' % message) | 
|  | progress.__doc__ = Logger.progress.__doc__ | 
|  |  | 
|  | def close(): | 
|  | for logger in _loggers: logger.close() |