rcUtil.py

Go to the documentation of this file.
00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2005
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 __facility__ = "Online"
00011 __abstract__ = "GLAST LAT script engine related utility methods"
00012 __author__   = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = "2005/07/23 00:08:27"
00014 __updated__  = "$Date: 2005/09/22 00:29:31 $"
00015 __version__  = "$Revision: 1.8 $"
00016 __release__  = "$Name: HEAD $"
00017 __credits__  = "SLAC"
00018 
00019 import LICOS.copyright_SLAC
00020 
00021 import imp
00022 import os
00023 import sys
00024 import logging as log
00025 import string
00026 from   types import ModuleType
00027 from   FSM import FSM
00028 
00029 class Reloader:
00030   """!\brief Reloader class.
00031 
00032   """
00033   DONT_RELOAD_LIST = ['scipy', 'weave', 'qwt', 'xml', 'pyexpat', 'win32',
00034                       'ROOT', 'libPyROOT']
00035 
00036   def __init__(self):
00037     """!\brief Reloader constructor.
00038 
00039     """
00040     self.appinit = {}
00041 
00042   def getNewModules(self, keepem):
00043     """!\brief Retrieve the new modules imported during the loading of the test.
00044 
00045     \param keepem List of modules which should be excluded from the reloading.
00046     """
00047     modules = {}
00048     for i, m in sys.modules.items():
00049       if (i not in keepem) and \
00050           (type(m) == ModuleType):
00051           modules[i] = m
00052     return modules
00053 
00054   def clearAppModules(self, dontReloadList, showUnloadedModules):
00055     """!\brief Unload modules that were loaded during the last test run.
00056 
00057     \param dontReloadList      List of module names which should not be unloaded
00058     \param showUnloadedModules Flag that indicates whether a debug log should
00059                                be printed for each module that gets unloaded
00060     """
00061     if self.appinit == {}:
00062       appfinish = {}
00063     else:
00064       appfinish = self.getNewModules(self.appinit)
00065     for i in self.filterModules(appfinish, dontReloadList):
00066       if i in sys.modules:
00067         if showUnloadedModules:
00068           log.debug("Unloading module %s %s" % (i, sys.modules[i].__file__))
00069         del sys.modules[i]
00070     self.appinit = sys.modules.copy()
00071 
00072   def filterModules(self, modules, dontReloadList):
00073     """!\brief Retrieve the list of modules that should be
00074               unloaded.
00075 
00076     \param modules        List of modules to be unloaded before filtering
00077     \param dontReloadList List of module names which should not be unloaded
00078     """
00079     dontReload = dontReloadList + Reloader.DONT_RELOAD_LIST
00080     mods = []
00081     for (moduleName, module) in modules.items():
00082       for modulePrefix in dontReload:
00083         if moduleName.startswith(modulePrefix):
00084           break
00085         if '__file__' not in dir(module):
00086           break
00087         if os.path.splitext(module.__file__)[1].lower() in ('.pyd','.dll'):
00088           break
00089         if os.path.normpath(os.path.normcase(module.__file__)).startswith(os.path.normpath(os.path.normcase(sys.prefix))):
00090           break
00091       else:
00092         mods.append(moduleName)
00093     return mods
00094 
00095 reloadModules = Reloader()
00096 
00097 def importModule(appName, reload=1, dontReloadList=[], showUnloadedModules=0):
00098   """!\brief Import a script engine application or suite.
00099 
00100   \param appName        Name of the module or pathname of the python script
00101   \param reload         1 = Reload all modules that have been loaded since
00102                             the Script Engine started (default)
00103                         0 = Do not reload modules (used if a suite is being loaded)
00104   \param dontReloadList Optional parameter which specifies the additional list
00105                         of module prefixes that should not be reloaded. If this
00106                         parameter is missing then the default list
00107                         (Reloader.DONT_RELOAD_LIST) is used, if it is specified
00108                         then it gets appended to the default list.
00109 
00110   \return The name of the module and the resolved pathname
00111   """
00112   # First check if a module name is specified, if so try to resolve its source.
00113   (appPath, appFile) = os.path.split(appName)
00114   (appBase, appExt)  = os.path.splitext(appFile)
00115   if appExt == '':
00116     try:
00117       if appPath == '':
00118         (f, path, desc) = imp.find_module(appBase)
00119       else:
00120         (f, path, desc) = imp.find_module(appBase, [appPath])
00121       (appPath, appFile) = os.path.split(path)
00122       (appBase, appExt)  = os.path.splitext(appFile)
00123     except ImportError, e:
00124       raise e
00125 
00126   _suffixes = {}
00127   for ext, mode, typ in imp.get_suffixes():
00128     _suffixes[ext] = (ext, mode, typ)
00129   _infoMap =  {
00130                 '.py' : ('.py','r',1),
00131                 '.pyc': ('.pyc','rb',2),
00132                 '.pyo': ('.pyo','rb',2)
00133               }
00134 
00135 
00136   # Temporarily change the directory in case the application
00137   # needs to load additional modules from the same directory.
00138   curDir = os.getcwd()
00139   if appPath != '': os.chdir(appPath)
00140 
00141   # Handle relative paths, by resolving the path again after current directory is changed.
00142   appPath = os.getcwd()
00143   append = False
00144   if appPath not in sys.path:
00145     sys.path.append(appPath)
00146     append = True
00147   appName = os.path.join(appPath, appFile)
00148 
00149   pycFile = os.path.join(appPath, appBase + '.pyc')
00150   pyoFile = os.path.join(appPath, appBase + '.pyo')
00151   if appExt == '.py':
00152     if os.path.exists(pyoFile) and os.path.getmtime(pyoFile) >= os.path.getmtime(appName):
00153         filename = pyoFile
00154         appExt = '.pyo'
00155     elif _suffixes.has_key('.pyo'):
00156         filename = appName
00157     elif os.path.exists(pycFile) and os.path.getmtime(pycFile) >= os.path.getmtime(appName):
00158       filename = pycFile
00159       appExt = '.pyc'
00160     else:
00161       filename = appName
00162   elif appExt == '.pyc':
00163     if os.path.exists(pyoFile) and os.path.getmtime(pyoFile) >= os.path.getmtime(appName):
00164       filename = pyoFile
00165       appExt = '.pyo'
00166     else:
00167       filename = appName
00168   elif appExt == '.pyo':
00169     filename = appName
00170   else:
00171     msg = 'Invalid module extension: %s' % appName
00172     raise RuntimeError, msg
00173   info = _infoMap[appExt]
00174   f = file(filename, info[1])
00175 
00176   try:
00177     # Clear the modules that was imported during the loading and
00178     # execution of the previous script.
00179     if reload: reloadModules.clearAppModules(dontReloadList, showUnloadedModules)
00180     module = imp.load_module(appBase, f, filename, info)
00181   finally:
00182     f.close()
00183     if append:
00184       sys.path.remove(appPath)
00185     if os.path.exists(curDir):
00186       os.chdir(curDir)
00187   return (module, filename)
00188 
00189 def getMainClass(module):
00190   """!\brief Retrieve the main class of an application or suite.
00191 
00192   Find out if the class inherits from FSM otherwise it is not the main class.
00193   If multiple main classes exist in one module then the one farthest away
00194   from FSM in the inheritance chain is used.
00195 
00196   \param module Application or suite module
00197 
00198   \return Main class or None
00199   """
00200   candidates = {}
00201   for objStr in dir(module):
00202     obj = getattr(module, objStr)
00203     if '__class__' in dir(obj) and getattr(obj,'__mro__',None) is not None:
00204       if FSM in obj.__mro__ and list(obj.__mro__).index(FSM) >= 2:
00205         candidates[obj] = list(obj.__mro__).index(FSM)
00206   if len(candidates) > 0:
00207     mainClass = None
00208     index     = 0
00209     for (obj, fsmIndex) in candidates.items():
00210       # We want the class that is farthest away from FSM in the
00211       # inheritence chain
00212       if fsmIndex > index:
00213         mainClass = obj
00214         index     = fsmIndex
00215     return mainClass
00216 
00217 def scriptRun(app):
00218   """!\brief Run the test script or suite.
00219 
00220   \return Status of the last transition executed
00221   """
00222   for transition in app.getRunSequence():
00223     status = app.process(transition)
00224     if status is not None:
00225       return status
00226 
00227 def scriptLoad(script, common, reload=1, *args, **kwargs):
00228   """!\brief Load the script.
00229 
00230   \param common ScriptEngineCommon instance
00231   \param reload Whether the reloading should be applied to the script.
00232                 If reload=1, preference value is used, otherwise
00233                 reloading is disabled
00234   \param args   Positional arguments
00235   \param kwargs Keyword arguments
00236   """
00237   if common.options().noreload is not None:
00238     dontReloadList = common.getDBN()["_dontReload"]
00239   else:
00240     dontReloadList = []
00241   prefs = common.preferences()
00242   if prefs['dontreload'].strip() != "":
00243     dontReloadPrefs = map(string.strip, prefs['dontreload'].split(','))
00244   else:
00245     dontReloadPrefs = []
00246   dontReloadList += dontReloadPrefs
00247 
00248   # Unless it is overridden by setting reload=0, use the preferences value
00249   if reload == 1:
00250     reload = not prefs["disablereload"]
00251   (module, filename) = importModule(appName=script,
00252                                     reload=reload,
00253                                     dontReloadList=dontReloadList,
00254                                     showUnloadedModules=prefs["showunloaded"] )
00255 
00256   appClass = getMainClass(module)
00257 
00258   if appClass is None:
00259     raise ImportError, "Application's base class does not inherit from FSM"
00260   else:
00261     return (module, filename, appClass(common, *args, **kwargs))

Generated on Thu Apr 27 20:52:43 2006 for LICOS L02-01-00 by doxygen 1.4.6-NO