| # epydoc -- Logging |
| # |
| # Copyright (C) 2005 Edward Loper |
| # Author: Edward Loper <[email protected]> |
| # 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() |