00001
00002
00003
00004 _file__ = 'generalUtils.py'
00005 __title__ = 'This is the general module, which contains everything which is the least specific to any project: all generic and all purpose code should end up here.'
00006 __version__ = '0.1'
00007 __author__ = 'Olivier Boudeville (olivier.boudeville@online.fr)'
00008 __project__ = 'Ceylan'
00009 __creationDate__= '2004, January 31'
00010 __comments__ = "Curiously enough, making an inherited method private does not override base class' one: Display.display could not be Display.__display if subclasses were to be able to redefine it."
00011 __source__ = 'Mark Pilgrim, http://diveintopython.org/, and al.'
00012 __doc__ = __title__ + '\n' + __comments__
00013
00014
00015
00016
00017 true = 1
00018 false = 0
00019
00020
00021
00022 import sys, types, string
00023
00024
00025 class GeneralUtilsException( Exception ):
00026 """Base class for generalUtils exceptions."""
00027
00028
00029 class ApplicationException( Exception ):
00030 """Base class for applicative exceptions."""
00031
00032
00033 def activateNameCompletion():
00034 """Activates python interpreter's command line automatic name completion."""
00035 import rlcompleter
00036 import readline
00037 readline.parse_and_bind( "tab: complete" )
00038 print "Python's name completion activated."
00039
00040
00041 def displayDic( aDic ):
00042 """Displays key-value pairs of specified dictionnary."""
00043
00044 max_len = 0
00045 for k in aDic.keys():
00046 if len(k) > max_len:
00047 max_len = len(k)
00048
00049 for (k,v) in aDic.items():
00050 print ' %*s: %s' % (max_len, k, v)
00051
00052
00053 def displayList( aList ):
00054 """Displays list items, one by line."""
00055 for i in aList:
00056 print i
00057
00058
00059 class Display:
00060 """This class provides abstract display services. It is intended to be subclassed."""
00061
00062 prefixForKeyMessages = "--"
00063 offsetIncrement = 4
00064
00065 normalPrefix = ''
00066 infoPrefix = 'Info: '
00067 debugPrefix = '--> Debug: '
00068 warningPrefix = 'Warning: '
00069 errorPrefix = '#### Error: '
00070
00071 do_debug = true
00072
00073 def __init__( self, spacing = 10, compression = true, truncate = false, verbosity = 2 ):
00074 """
00075 Defines the options for this display to perform its tasks.
00076 - spacing: minimum size for a field,
00077 - compression: if true, a multi-lined field is displayed only on one line,
00078 - truncate: if true, truncates a field to the maximum length this values provides,
00079 - verbosity: sets the level of detail of the display,
00080 + 0: totally silent,
00081 + 1: only most important messages are displayed, those which starts by prefixForKeyMessages,
00082 + 2: all messages are displayed.
00083 """
00084
00085 self.esp = spacing and ( lambda s, spaceNum = spacing: string.ljust( s, spaceNum ) ) or ( lambda s: s )
00086 self.comp = compression and ( lambda s: string.join( s.split(), ' ' ) ) or ( lambda s: s )
00087 self.trunc = truncate and ( lambda s, truncNum = truncate: s[: truncNum ] ) or ( lambda s: s )
00088 self.verb = verbosity
00089 self.offset = 0
00090
00091
00092 def display( self, message, addReturn = true ):
00093 """Displays unconditionnally provided normal message."""
00094 if addReturn:
00095 self.innerDisplayStandard( self.normalPrefix + self.offset * ' ' + message + '\n' )
00096 else:
00097 self.innerDisplayStandard( self.normalPrefix + self.offset * ' ' + message )
00098
00099
00100 def info( self, message, addReturn = true ):
00101 """Displays information message."""
00102
00103 if addReturn:
00104 self.innerDisplayStandard( self.infoPrefix + message + '\n' )
00105 else:
00106 self.innerDisplayStandard( self.infoPrefix + message )
00107
00108
00109 def debug( self, message, addReturn = true ):
00110 """Displays debug message if and only if we are in debug mode."""
00111
00112 if self.do_debug:
00113 if addReturn:
00114 self.innerDisplayStandard( self.debugPrefix + message + '\n' )
00115 else:
00116 self.innerDisplayStandard( self.debugPrefix + message )
00117
00118
00119 def warning( self, message, addReturn = true ):
00120 """Displays provided warning message."""
00121 if addReturn:
00122 self.innerDisplayError( self.warningPrefix + message + '\n' )
00123 else:
00124 self.innerDisplayError( self.warningPrefix + message )
00125
00126
00127 def error( self, message, addReturn = true ):
00128 """Displays provided error message."""
00129 if addReturn:
00130 self.innerDisplayError( self.errorPrefix + message + '\n' )
00131 else:
00132 self.innerDisplayError( self.errorPrefix + message )
00133
00134
00135 def innerDisplayStandard( self, message ):
00136 """
00137 Pure virtual function, to be redefined by implementation classes.
00138 It should have been private, if it could be overridden.
00139 """
00140 pass
00141
00142
00143 def indent( self ):
00144 """Indents one more level for normal messages."""
00145 self.offset += self.offsetIncrement
00146
00147
00148 def desindent( self ):
00149 """Indents one fewer level for normal messages."""
00150 self.offset -= self.offsetIncrement
00151 if self.offset < 0:
00152 self.offset = 0
00153
00154
00155 def blankLine( self ):
00156 if self.verb == 2:
00157 self.innerDisplayStandard( '\n' )
00158
00159
00160 def status( self ):
00161 self.innerDisplayStandard( 'Verbosity level is %s.' % ( self.verb, ) )
00162
00163
00164 def __call__( self, message, addReturn = true ):
00165 if type( message ) == types.StringType:
00166 if self.verb == 2 or ( ( self.verb == 1 ) and ( message[:2] == self.prefixForKeyMessages ) ):
00167 self.display( self.esp( self.trunc( self.comp( message ) ) ), addReturn )
00168 elif type( message ) in [ types.ListType, types.TupleType ]:
00169 for item in message:
00170 self.__call__( item, addReturn )
00171 else:
00172 print 'Display: unsupported message type, unable to display it.'
00173
00174
00175 def setVerbosity( self, newVerbosity = 2 ):
00176 self.verb = newVerbosity
00177
00178
00179
00180 class ScreenDisplay( Display ):
00181 """
00182 This is the Display implementation that uses screen as display output device.
00183 """
00184
00185 def __init__( self, spacing = 10, compression = true, truncate = false, verbosity = 2 ):
00186 """Propagates back setting to ancestor class' constructor."""
00187 Display.__init__( self, spacing, compression, truncate, verbosity )
00188
00189
00190 def innerDisplayStandard( self, message ):
00191 """Displays a message to standard output file descriptor."""
00192 sys.stdout.write( message )
00193 sys.stdout.flush()
00194
00195
00196 def innerDisplayError( self, message ):
00197 """Displays a message to error output file descriptor."""
00198 sys.stderr.write( message )
00199 sys.stderr.flush()
00200
00201
00202
00203 class FileDisplay ( Display ):
00204 """This is the Display implementation that uses files as display output device."""
00205
00206 defaultLogBaseName = "Log"
00207 defaultExtension = "txt"
00208
00209
00210 def __init__( self, logBaseName = defaultLogBaseName, allowOverwrite = true, spacing = 10, compression = true, truncate = false, verbosity = 2):
00211 """
00212 Implements the Display interface so that messages are output to a log file.
00213 - logFilename: defines the file where messages should be stored,
00214 - allowOverwrite: tells whether a previously existing log file could
00215 be overwritten,
00216 - the other parameters have the same semantics as the Display ones.
00217 """
00218
00219 Display.__init__( self, spacing = 10, compression = true, truncate = false, verbosity = 2 )
00220 self.logBaseName = logBaseName
00221 self.allowOverwrite = allowOverwrite
00222 self.logFilename = self.logBaseName + "." + self.defaultExtension
00223 if self.allowOverwrite:
00224 self.logFile = open( self.logFilename, 'w' )
00225 else:
00226 self.logFile = open( self.logFilename, 'a' )
00227 self.status()
00228
00229
00230 def __del__( self ):
00231 """Destructor shall release the resources."""
00232 if self.logFile:
00233 self.logFile.close()
00234
00235
00236 def innerDisplayStandard( self, message ):
00237 self.logFile.write( message + '\n' )
00238 self.logFile.flush()
00239
00240 def innerDisplayError( self, message ):
00241 self.logFile.write( message + '\n' )
00242 self.logFile.flush()
00243
00244
00245
00246 if __name__ == "__main__":
00247 if len( sys.argv ) != 2:
00248 print __doc__
00249 else:
00250 temp = ScreenDisplay()
00251 temp( sys.argv[ 1 ] )
00252
00253