| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame^] | 1 | # epydoc -- Logging |
| 2 | # |
| 3 | # Copyright (C) 2005 Edward Loper |
| 4 | # Author: Edward Loper <edloper@loper.org> |
| 5 | # URL: <http://epydoc.sf.net> |
| 6 | # |
| 7 | # $Id: log.py 1488 2007-02-14 00:34:27Z edloper $ |
| 8 | |
| 9 | """ |
| 10 | Functions used to report messages and progress updates to the user. |
| 11 | These functions are delegated to zero or more registered L{Logger} |
| 12 | objects, which are responsible for actually presenting the information |
| 13 | to the user. Different interfaces are free to create and register |
| 14 | their own C{Logger}s, allowing them to present this information in the |
| 15 | manner that is best suited to each interface. |
| 16 | |
| 17 | @note: I considered using the standard C{logging} package to provide |
| 18 | this functionality. However, I found that it would be too difficult |
| 19 | to get that package to provide the behavior I want (esp. with respect |
| 20 | to progress displays; but also with respect to message blocks). |
| 21 | |
| 22 | @group Message Severity Levels: DEBUG, INFO, WARNING, ERROR, FATAL |
| 23 | """ |
| 24 | __docformat__ = 'epytext en' |
| 25 | |
| 26 | import sys, os |
| 27 | |
| 28 | DEBUG = 10 |
| 29 | INFO = 20 |
| 30 | DOCSTRING_WARNING = 25 |
| 31 | WARNING = 30 |
| 32 | ERROR = 40 |
| 33 | FATAL = 40 |
| 34 | |
| 35 | ###################################################################### |
| 36 | # Logger Base Class |
| 37 | ###################################################################### |
| 38 | class Logger: |
| 39 | """ |
| 40 | An abstract base class that defines the interface for X{loggers}, |
| 41 | which are used by epydoc to report information back to the user. |
| 42 | Loggers are responsible for tracking two types of information: |
| 43 | |
| 44 | - Messages, such as warnings and errors. |
| 45 | - Progress on the current task. |
| 46 | |
| 47 | This abstract class allows the command-line interface and the |
| 48 | graphical interface to each present this information to the user |
| 49 | in the way that's most natural for each interface. To set up a |
| 50 | logger, create a subclass of C{Logger} that overrides all methods, |
| 51 | and register it using L{register_logger}. |
| 52 | """ |
| 53 | #//////////////////////////////////////////////////////////// |
| 54 | # Messages |
| 55 | #//////////////////////////////////////////////////////////// |
| 56 | |
| 57 | def log(self, level, message): |
| 58 | """ |
| 59 | Display a message. |
| 60 | |
| 61 | @param message: The message string to display. C{message} may |
| 62 | contain newlines, but does not need to end in a newline. |
| 63 | @param level: An integer value indicating the severity of the |
| 64 | message. |
| 65 | """ |
| 66 | |
| 67 | def close(self): |
| 68 | """ |
| 69 | Perform any tasks needed to close this logger. |
| 70 | """ |
| 71 | |
| 72 | #//////////////////////////////////////////////////////////// |
| 73 | # Message blocks |
| 74 | #//////////////////////////////////////////////////////////// |
| 75 | |
| 76 | def start_block(self, header): |
| 77 | """ |
| 78 | Start a new message block. Any calls to L{info()}, |
| 79 | L{warning()}, or L{error()} that occur between a call to |
| 80 | C{start_block} and a corresponding call to C{end_block} will |
| 81 | be grouped together, and displayed with a common header. |
| 82 | C{start_block} can be called multiple times (to form nested |
| 83 | blocks), but every call to C{start_block} I{must} be balanced |
| 84 | by a call to C{end_block}. |
| 85 | """ |
| 86 | |
| 87 | def end_block(self): |
| 88 | """ |
| 89 | End a warning block. See L{start_block} for details. |
| 90 | """ |
| 91 | |
| 92 | #//////////////////////////////////////////////////////////// |
| 93 | # Progress bar |
| 94 | #//////////////////////////////////////////////////////////// |
| 95 | |
| 96 | def start_progress(self, header=None): |
| 97 | """ |
| 98 | Begin displaying progress for a new task. C{header} is a |
| 99 | description of the task for which progress is being reported. |
| 100 | Each call to C{start_progress} must be followed by a call to |
| 101 | C{end_progress} (with no intervening calls to |
| 102 | C{start_progress}). |
| 103 | """ |
| 104 | |
| 105 | def end_progress(self): |
| 106 | """ |
| 107 | Finish off the display of progress for the current task. See |
| 108 | L{start_progress} for more information. |
| 109 | """ |
| 110 | |
| 111 | def progress(self, percent, message=''): |
| 112 | """ |
| 113 | Update the progress display. |
| 114 | |
| 115 | @param percent: A float from 0.0 to 1.0, indicating how much |
| 116 | progress has been made. |
| 117 | @param message: A message indicating the most recent action |
| 118 | that contributed towards that progress. |
| 119 | """ |
| 120 | |
| 121 | class SimpleLogger(Logger): |
| 122 | def __init__(self, threshold=WARNING): |
| 123 | self.threshold = threshold |
| 124 | def log(self, level, message): |
| 125 | if level >= self.threshold: print message |
| 126 | |
| 127 | ###################################################################### |
| 128 | # Logger Registry |
| 129 | ###################################################################### |
| 130 | |
| 131 | _loggers = [] |
| 132 | """ |
| 133 | The list of registered logging functions. |
| 134 | """ |
| 135 | |
| 136 | def register_logger(logger): |
| 137 | """ |
| 138 | Register a logger. Each call to one of the logging functions |
| 139 | defined by this module will be delegated to each registered |
| 140 | logger. |
| 141 | """ |
| 142 | _loggers.append(logger) |
| 143 | |
| 144 | def remove_logger(logger): |
| 145 | _loggers.remove(logger) |
| 146 | |
| 147 | ###################################################################### |
| 148 | # Logging Functions |
| 149 | ###################################################################### |
| 150 | # The following methods all just delegate to the corresponding |
| 151 | # methods in the Logger class (above) for each registered logger. |
| 152 | |
| 153 | def fatal(*messages): |
| 154 | """Display the given fatal message.""" |
| 155 | message = ' '.join(['%s' % (m,) for m in messages]) |
| 156 | for logger in _loggers: logger.log(FATAL, message) |
| 157 | |
| 158 | def error(*messages): |
| 159 | """Display the given error message.""" |
| 160 | message = ' '.join(['%s' % (m,) for m in messages]) |
| 161 | for logger in _loggers: logger.log(ERROR, message) |
| 162 | |
| 163 | def warning(*messages): |
| 164 | """Display the given warning message.""" |
| 165 | message = ' '.join(['%s' % (m,) for m in messages]) |
| 166 | for logger in _loggers: logger.log(WARNING, message) |
| 167 | |
| 168 | def docstring_warning(*messages): |
| 169 | """Display the given docstring warning message.""" |
| 170 | message = ' '.join(['%s' % (m,) for m in messages]) |
| 171 | for logger in _loggers: logger.log(DOCSTRING_WARNING, message) |
| 172 | |
| 173 | def info(*messages): |
| 174 | """Display the given informational message.""" |
| 175 | message = ' '.join(['%s' % (m,) for m in messages]) |
| 176 | for logger in _loggers: logger.log(INFO, message) |
| 177 | |
| 178 | def debug(*messages): |
| 179 | """Display the given debugging message.""" |
| 180 | message = ' '.join(['%s' % (m,) for m in messages]) |
| 181 | for logger in _loggers: logger.log(DEBUG, message) |
| 182 | |
| 183 | def start_block(header): |
| 184 | for logger in _loggers: logger.start_block(header) |
| 185 | start_block.__doc__ = Logger.start_block.__doc__ |
| 186 | |
| 187 | def end_block(): |
| 188 | for logger in _loggers: logger.end_block() |
| 189 | end_block.__doc__ = Logger.end_block.__doc__ |
| 190 | |
| 191 | def start_progress(header=None): |
| 192 | for logger in _loggers: logger.start_progress(header) |
| 193 | start_progress.__doc__ = Logger.start_progress.__doc__ |
| 194 | |
| 195 | def end_progress(): |
| 196 | for logger in _loggers: logger.end_progress() |
| 197 | end_progress.__doc__ = Logger.end_progress.__doc__ |
| 198 | |
| 199 | def progress(percent, message=''): |
| 200 | for logger in _loggers: logger.progress(percent, '%s' % message) |
| 201 | progress.__doc__ = Logger.progress.__doc__ |
| 202 | |
| 203 | def close(): |
| 204 | for logger in _loggers: logger.close() |