Gaudi Framework, version v21r4

Home   Generated: 7 Sep 2009

genconfuser.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 """
00003 Generate _confDb.py files for ConfigurableUser classes.
00004 """
00005 
00006 import os, sys, time, logging
00007 from pprint import pformat
00008 from GaudiKernel.ConfigurableDb import loadConfigurableDb, cfgDb
00009 
00010 logging.VERBOSE = (logging.INFO + logging.DEBUG) / 2 
00011 logging.addLevelName(logging.VERBOSE, "VERBOSE")
00012 logging.verbose = lambda msg, *args, **kwargs: \
00013     apply(logging.log, (logging.VERBOSE, msg) + args, kwargs)
00014 
00015 def _inheritsfrom(derived, basename):
00016     """
00017     Check if the class name 'basename' is anywhere in the base classes of the
00018     class 'derived'.
00019     If 'derived' _is_ 'basename', returns False.  
00020     """
00021     for b in derived.__bases__:
00022         if b.__name__ == basename:
00023             return True
00024         else:
00025             if _inheritsfrom(b, basename):
00026                 return True
00027     return False
00028 
00029 def getConfigurableUsers(modulename, root):
00030     """
00031     Find in the module 'modulename' all the classes that derive from ConfigurableUser.
00032     Return the list of the names.
00033     """
00034     # hack the sys.path to add the first part of the module name after root
00035     oldpath = list(sys.path)
00036     # hack the sys.path to add the first part of the module name after root
00037     moduleelements = modulename.split('.')
00038     if len(moduleelements) > 1:
00039         sys.path.insert(0,os.sep.join([root] + moduleelements[:-1]))
00040     else:
00041         sys.path.insert(0,root)
00042     logging.verbose("sys.path prepended with %r", sys.path[0])
00043     # this is the name of the submodule to import
00044     shortmodname = moduleelements[-1]
00045     
00046     logging.info("Looking for ConfigurableUser in %r", modulename)
00047     g, l = {}, {}
00048     try:
00049         logging.verbose("importing %s", shortmodname)
00050         exec "import %s as mod" % shortmodname in g, l
00051     finally:
00052         # restore old sys.path
00053         logging.verbose("restoring old sys.path")
00054         sys.path = oldpath
00055     mod = l["mod"]
00056     if "__all__" in dir(mod) and mod.__all__:
00057         all = mod.__all__
00058     else:
00059         all = [ n for n in dir(mod) if not n.startswith("_")]
00060     result = []
00061     for name in all:
00062         cfg = cfgDb.get(name)
00063         if cfg and cfg["module"] != modulename:
00064             # This name comes from another module
00065             logging.verbose("Object %r already found in module %r", name, cfg["module"])
00066             continue
00067         t = getattr(mod, name)
00068         if isinstance(t, type) and  _inheritsfrom(t, "ConfigurableUser"):
00069             result.append(name)
00070     logging.verbose("Found %r", result)
00071     return result
00072 
00073 def main():
00074     from optparse import OptionParser
00075     parser = OptionParser(prog = os.path.basename(sys.argv[0]),
00076                           usage = "%prog [options] <PackageName> [<Module1> ...]")
00077     parser.add_option("-o", "--output", action="store", type="string",
00078                       help="output file for confDb data [default = '../genConf/<PackageName>_user_confDb.py'].")
00079     parser.add_option("-r", "--root", action="store", type="string",
00080                       help="root directory of the python modules [default = '../python'].")
00081     parser.add_option("-v", "--verbose", action="store_true",
00082                       help="print some debugging information")
00083     parser.add_option("--lockerpath", action="store",
00084                       metavar = "DIRNAME",
00085                       help="directory where to find the module 'locker'")
00086     parser.set_defaults(root = os.path.join("..","python"))
00087     
00088     opts, args = parser.parse_args()
00089     
00090     if opts.verbose:
00091         log_level = logging.VERBOSE
00092     else:
00093         log_level = logging.INFO
00094     logging.basicConfig(format = "%(levelname)s: %(message)s",
00095                         stream = sys.stdout,
00096                         level = log_level)
00097 
00098     if len(args) < 1:
00099         parser.error("PackageName is required")
00100     
00101     package_name = args.pop(0)
00102 
00103     usingConvention = False
00104     if not args:
00105         # use the conventional module name <package>.Configuration
00106         args = [package_name + ".Configuration"]
00107         usingConvention = True
00108     
00109     if not opts.output:
00110         outputfile = os.path.join("..", "genConf", package_name + '_user_confDb.py')
00111     else:
00112         outputfile = opts.output
00113     
00114     # The locking ensures that nobody tries to modify the python.zip file while
00115     # we read it.
00116     dbLock = None
00117     if "GAUDI_BUILD_LOCK" in os.environ:
00118         if opts.lockerpath:
00119             sys.path.append(opts.lockerpath)
00120         # Get the LockFile class from the locker module in GaudiPolicy or use a fake
00121         # factory.
00122         try:
00123             from locker import LockFile
00124         except ImportError:
00125             def LockFile(*args, **kwargs):
00126                 return None
00127         # obtain the lock
00128         dbLock = LockFile(os.environ["GAUDI_BUILD_LOCK"], temporary =  True) 
00129     
00130     # We can disable the error on missing configurables only if we can import Gaudi.Configurables
00131     # It must be done at this point because it may conflict with logging.basicConfig
00132     try:
00133         import Gaudi.Configurables
00134         Gaudi.Configurables.ignoreMissingConfigurables = True
00135     except:
00136         pass
00137     # load configurables database to avoid fake duplicates
00138     loadConfigurableDb()
00139     # ensure that local configurables are in the database
00140     try:
00141         # Add the local python directories to the python path to be able to import the local
00142         # configurables
00143         sys.path.insert(0, os.path.join("..", "genConf"))
00144         sys.path.insert(0, os.path.join("..", "python"))
00145         localConfDb = os.path.join("..", "genConf", package_name, package_name + '_confDb.py')
00146         if os.path.exists(localConfDb):
00147             execfile(localConfDb, {}, {})
00148     except:
00149         pass # ignore failures (not important)
00150     del dbLock # Now we can let the others operate on the install area python directory
00151     
00152     # Collecting ConfigurableUser specializations
00153     cus = {}
00154     for mod in args:
00155         try:
00156             lst = getConfigurableUsers(mod, root = opts.root)
00157         except ImportError:
00158             if usingConvention: # the conventional module may not exist
00159                 continue
00160             logging.error("Cannot import module %r", mod)
00161             return 2
00162         if lst:
00163             cus[mod] = lst
00164         elif not usingConvention:
00165             logging.warning("Specified module %r does not contain ConfigurableUser specializations", mod)
00166     
00167     if cus:
00168         logging.info("ConfigurableUser found:\n%s", pformat(cus))
00169         # header
00170         output = """##  -*- python -*-
00171 # db file automatically generated by %s on: %s
00172 ## insulates outside world against anything bad that could happen
00173 ## also prevents global scope pollution
00174 def _fillCfgDb():
00175     from GaudiKernel.Proxy.ConfigurableDb import CfgDb
00176 
00177     # get a handle on the repository of Configurables
00178     cfgDb = CfgDb()
00179 
00180     # populate the repository with informations on Configurables 
00181 """ % (parser.prog, time.asctime())
00182         
00183         for mod in cus:
00184             for cu in cus[mod]:
00185                 output += """
00186     cfgDb.add( configurable = '%s',
00187                package = '%s',
00188                module  = '%s',
00189                lib     = 'None' )""" % (cu, package_name, mod)
00190 
00191         # trailer
00192         output += """
00193 
00194     return #_fillCfgDb
00195 
00196 # fill cfgDb at module import...
00197 try:
00198     _fillCfgDb()
00199     #house cleaning...
00200     del _fillCfgDb
00201 except Exception,err:
00202     print "Py:ConfigurableDb   ERROR Problem with [%%s] content!" %% __name__
00203     print "Py:ConfigurableDb   ERROR",err
00204     print "Py:ConfigurableDb   ERROR   ==> culprit is package [%s] !"
00205 """ % package_name
00206     elif usingConvention:
00207         logging.info("No ConfigurableUser found")
00208         output = "# No ConfigurableUser specialization\n"
00209     else:
00210         logging.error("No ConfigurableUser specialization found")
00211         return 1
00212 
00213     # create the destination directory if not there
00214     output_dir = os.path.dirname(outputfile)
00215     if not os.path.exists(output_dir):
00216         logging.info("Creating directory %r", output_dir)
00217         os.makedirs(output_dir, 0755)
00218     
00219     # write output to file
00220     logging.verbose("Writing confDb data to %r", outputfile)
00221     open(outputfile, "w").write(output)
00222     return 0
00223 
00224 if __name__ == '__main__':
00225     retcode = main()
00226     sys.exit(retcode)

Generated at Mon Sep 7 18:05:42 2009 for Gaudi Framework, version v21r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004