Package PyFoam :: Package Applications :: Module PyFoamApplication
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Applications.PyFoamApplication

  1  #  ICE Revision: $Id: /local/openfoam/Python/PyFoam/PyFoam/Applications/PyFoamApplication.py 7870 2012-02-15T17:53:40.344304Z bgschaid  $  
  2  """Base class for pyFoam-applications 
  3   
  4  Classes can also be called with a command-line string""" 
  5   
  6  from optparse import OptionGroup 
  7  from PyFoam.Basics.FoamOptionParser import FoamOptionParser 
  8  from PyFoam.Error import error,warning,FatalErrorPyFoamException 
  9  from PyFoam.FoamInformation import oldAppConvention as oldApp 
 10  from PyFoam.RunDictionary.SolutionDirectory import NoTouchSolutionDirectory 
 11   
 12  from PyFoam.Basics.TerminalFormatter import TerminalFormatter 
 13  from PyFoam import configuration 
 14   
 15  format=TerminalFormatter() 
 16  format.getConfigFormat("error") 
 17  format.getConfigFormat("warn") 
 18   
 19  import sys 
 20  from os import path,getcwd,environ 
 21  from copy import deepcopy 
 22   
23 -def pyFoamExceptionHook(type,value,tb):
24 if hasattr(sys,'ps1'): 25 warning("Interactive mode. No debugger") 26 sys.__excepthook__(type,value,tb) 27 elif not (sys.stderr.isatty() and sys.stdin.isatty() and sys.stdout.isatty()): 28 warning("Not on a terminal. No debugger") 29 sys.__excepthook__(type,value,tb) 30 elif issubclass(type,SyntaxError): 31 warning("Syntax error. No debugger") 32 sys.__excepthook__(type,value,tb) 33 else: 34 import traceback,pdb 35 traceback.print_exception(type,value,tb) 36 print 37 pdb.pm()
38
39 -class PyFoamApplication(object):
40 - def __init__(self, 41 args=None, 42 description=None, 43 usage=None, 44 interspersed=False, 45 nr=None, 46 changeVersion=True, 47 exactNr=True, 48 inputApp=None):
49 """ 50 @param description: description of the command 51 @param usage: Usage 52 @param interspersed: Is the command line allowed to be interspersed (options after the arguments) 53 @param args: Command line arguments when using the Application as a 'class' from a script 54 @param nr: Number of required arguments 55 @param changeVersion: May this application change the version of OF used? 56 @param exactNr: Must not have more than the required number of arguments 57 @param inputApp: Application with input data. Used to allow a 'pipe-like' behaviour if the class is used from a Script 58 """ 59 self.parser=FoamOptionParser(args=args, 60 description=description, 61 usage=usage, 62 interspersed=interspersed) 63 self.generalOpts=None 64 65 self.__appData={} 66 if inputApp: 67 self.__appData["inputData"]=inputApp.getData() 68 69 grp=OptionGroup(self.parser, 70 "Default", 71 "Options common to all PyFoam-applications") 72 73 if changeVersion: 74 # the options are evaluated in Basics.FoamOptionParser 75 grp.add_option("--foamVersion", 76 dest="foamVersion", 77 default=None, 78 help="Change the OpenFOAM-version that is to be used") 79 if "WM_PROJECT_VERSION" in environ: 80 grp.add_option("--currentFoamVersion", 81 dest="foamVersion", 82 const=environ["WM_PROJECT_VERSION"], 83 default=None, 84 action="store_const", 85 help="Use the current OpenFOAM-version "+environ["WM_PROJECT_VERSION"]) 86 87 grp.add_option("--force-32bit", 88 dest="force32", 89 default=False, 90 action="store_true", 91 help="Forces the usage of a 32-bit-version if that version exists as 32 and 64 bit. Only used when --foamVersion is used") 92 grp.add_option("--force-64bit", 93 dest="force64", 94 default=False, 95 action="store_true", 96 help="Forces the usage of a 64-bit-version if that version exists as 32 and 64 bit. Only used when --foamVersion is used") 97 grp.add_option("--force-debug", 98 dest="compileOption", 99 const="Debug", 100 default=None, 101 action="store_const", 102 help="Forces the value Debug for the WM_COMPILE_OPTION. Only used when --foamVersion is used") 103 grp.add_option("--force-opt", 104 dest="compileOption", 105 const="Opt", 106 default=None, 107 action="store_const", 108 help="Forces the value Opt for the WM_COMPILE_OPTION. Only used when --foamVersion is used") 109 110 grp.add_option("--psyco-accelerated", 111 dest="psyco", 112 default=False, 113 action="store_true", 114 help="Accelerate the script using the psyco-library (EXPERIMENTAL and requires a separatly installed psyco)") 115 grp.add_option("--profile-python", 116 dest="profilePython", 117 default=False, 118 action="store_true", 119 help="Profile the python-script (not the OpenFOAM-program) - mostly of use for developers") 120 grp.add_option("--profile-cpython", 121 dest="profileCPython", 122 default=False, 123 action="store_true", 124 help="Profile the python-script (not the OpenFOAM-program) using the better cProfile library - mostly of use for developers") 125 grp.add_option("--profile-hotshot", 126 dest="profileHotshot", 127 default=False, 128 action="store_true", 129 help="Profile the python-script using the hotshot-library (not the OpenFOAM-program) - mostly of use for developers - EXPERIMENTAL") 130 grp.add_option("--traceback-on-error", 131 dest="traceback", 132 default=False, 133 action="store_true", 134 help="Prints a traceback when an error is encountered (for debugging)") 135 grp.add_option("--interactive-debugger", 136 dest="interactiveDebug", 137 default=False, 138 action="store_true", 139 help="In case of an exception start the interactive debugger PDB. Also implies --traceback-on-error") 140 grp.add_option("--dump-application-data", 141 dest="dumpAppData", 142 default=False, 143 action="store_true", 144 help="Print the dictionary with the generated application data after running") 145 grp.add_option("--pickle-application-data", 146 dest="pickleApplicationData", 147 default=None, 148 action="store", 149 type="string", 150 help="""\ 151 Write a pickled version of the application data to a file. If the 152 filename given is 'stdout' then the pickled data is written to 153 stdout. The usual standard output is then captured and added to the 154 application data as an entry 'stdout' (same for 'stderr'). Be careful 155 with these option for commands that generate a lot of output""") 156 157 self.parser.add_option_group(grp) 158 159 self.addOptions() 160 self.parser.parse(nr=nr,exactNr=exactNr) 161 self.opts=self.parser.getOptions() 162 163 if self.opts.interactiveDebug: 164 sys.excepthook=pyFoamExceptionHook 165 self.opts.traceback=True 166 167 if self.opts.psyco: 168 try: 169 import psyco 170 psyco.full() 171 except ImportError: 172 warning("No psyco installed. Continuing without acceleration") 173 174 if self.opts.profilePython or self.opts.profileCPython or self.opts.profileHotshot: 175 if sum([self.opts.profilePython,self.opts.profileCPython,self.opts.profileHotshot])>1: 176 self.error("Profiling with hotshot and regular profiling are mutual exclusive") 177 print "Running profiled" 178 if self.opts.profilePython: 179 import profile 180 elif self.opts.profileCPython: 181 import cProfile as profile 182 else: 183 import hotshot 184 profileData=path.basename(sys.argv[0])+".profile" 185 if self.opts.profilePython or self.opts.profileCPython: 186 profile.runctx('self.run()',None,{'self':self},profileData) 187 print "Reading python profile" 188 import pstats 189 stats=pstats.Stats(profileData) 190 else: 191 profileData+=".hotshot" 192 prof=hotshot.Profile(profileData) 193 prof.runctx('self.run()',{},{'self':self}) 194 print "Writing and reading hotshot profile" 195 prof.close() 196 import hotshot.stats 197 stats=hotshot.stats.load(profileData) 198 stats.strip_dirs() 199 stats.sort_stats('time','calls') 200 stats.print_stats(20) 201 202 self.parser.restoreEnvironment() 203 else: 204 try: 205 if self.opts.pickleApplicationData=="stdout": 206 # Redirect output to memory 207 import StringIO 208 oldStdout=sys.stdout 209 oldStderr=sys.stderr 210 sys.stdout=StringIO.StringIO() 211 sys.stderr=StringIO.StringIO() 212 213 result=self.run() 214 215 # do this at the earliest possible moment 216 self.parser.restoreEnvironment() 217 218 if self.opts.pickleApplicationData=="stdout": 219 # restore stdout 220 self.__appData["stdout"]=sys.stdout.getvalue() 221 self.__appData["stderr"]=sys.stderr.getvalue() 222 sys.stdout=oldStdout 223 sys.stderr=oldStderr 224 225 if self.opts.pickleApplicationData: 226 import cPickle as pickle 227 if self.opts.pickleApplicationData=="stdout": 228 pick=pickle.Pickler(sys.stdout) 229 else: 230 pick=pickle.Pickler(open(self.opts.pickleApplicationData,'w')) 231 pick.dump(self.__appData) 232 del pick 233 if self.opts.dumpAppData: 234 import pprint 235 print "Application data:" 236 printer=pprint.PrettyPrinter() 237 printer.pprint(self.__appData) 238 239 return result 240 except FatalErrorPyFoamException,e: 241 if self.opts.traceback: 242 raise 243 else: 244 self.error(e.descr)
245
246 - def __getitem__(self,key):
247 """Get application data""" 248 try: 249 return self.__appData[key] 250 except KeyError: 251 print "available keys:",self.__appData.keys() 252 raise
253
254 - def __iter__(self):
255 """Iterate over the application data""" 256 for k in self.__appData: 257 yield k
258
259 - def iterkeys(self):
260 return self.__appData.iterkeys()
261
262 - def iteritems(self):
263 return self.__appData.iteritems()
264
265 - def getData(self):
266 """Get the application data""" 267 return deepcopy(self.__appData)
268
269 - def setData(self,data):
270 """Set the application data 271 272 @param data: dictionary whose entries will be added to the 273 application data (possibly overwriting old entries of the same name)""" 274 for k,v in data.iteritems(): 275 self.__appData[k]=deepcopy(v)
276
277 - def ensureGeneralOptions(self):
278 if self.generalOpts==None: 279 self.generalOpts=OptionGroup(self.parser, 280 "General", 281 "General options for the control of OpenFOAM-runs") 282 self.parser.add_option_group(self.generalOpts)
283
284 - def addOptions(self):
285 """ 286 Add options to the parser 287 """ 288 pass
289
290 - def run(self):
291 """ 292 Run the real application 293 """ 294 error("Not a valid application")
295 296
297 - def error(self,*args):
298 """ 299 Prints an error message and exits 300 @param args: Arguments that are to be printed 301 """ 302 print format.error+"Error in",sys.argv[0],":", 303 for a in args: 304 print a, 305 print format.reset 306 sys.exit(-1)
307
308 - def warning(self,*args):
309 """ 310 Prints a warning message 311 @param args: Arguments that are to be printed 312 """ 313 print format.warn+"Warning in",sys.argv[0],":", 314 for a in args: 315 print a, 316 print format.reset
317
318 - def silent(self,*args):
319 """ 320 Don't print a warning message 321 @param args: Arguments that are to be printed 322 """ 323 pass
324
325 - def checkCase(self,name,fatal=True,verbose=True):
326 """ 327 Check whether this is a valid OpenFOAM-case 328 @param name: the directory-bame that is supposed to be the case 329 @param fatal: If this is not a case then the application ends 330 @param verbose: If this is not a case no warning is issued 331 """ 332 if fatal: 333 func=self.error 334 elif verbose: 335 func=self.warning 336 else: 337 func=self.silent 338 339 if not path.exists(name): 340 func("Case",name,"does not exist") 341 return False 342 if not path.isdir(name): 343 func("Case",name,"is not a directory") 344 return False 345 if not path.exists(path.join(name,"system")): 346 func("Case",name,"does not have a 'system' directory") 347 return False 348 if not path.exists(path.join(name,"constant")): 349 func("Case",name,"does not have a 'constant' directory") 350 return False 351 352 return True
353
354 - def addToCaseLog(self,name,*text):
355 """ 356 Add information about the application that was run to the case-log 357 """ 358 359 logline=[NoTouchSolutionDirectory(name)] 360 logline+=["Application:",path.basename(sys.argv[0])]+sys.argv[1:] 361 logline+=[" | with cwd",getcwd()," | "] 362 logline+=text 363 apply(NoTouchSolutionDirectory.addToHistory,logline)
364
365 - def addLocalConfig(self,directory=None):
366 """ 367 Adds a local directory (assuming it is found) 368 """ 369 if directory!=None: 370 configuration().addFile(path.join(directory,"LocalConfigPyFoam"),silent=True)
371