Gaudi Framework, version v20r4

Generated: 8 Jan 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.set_defaults(root = os.path.join("..","python"))
00084     
00085     opts, args = parser.parse_args()
00086     
00087     if opts.verbose:
00088         log_level = logging.VERBOSE
00089     else:
00090         log_level = logging.INFO
00091     logging.basicConfig(format = "%(levelname)s: %(message)s",
00092                         stream = sys.stdout,
00093                         level = log_level)
00094 
00095     if len(args) < 1:
00096         parser.error("PackageName is required")
00097     
00098     package_name = args.pop(0)
00099 
00100     usingConvention = False
00101     if not args:
00102         # use the conventional module name <package>.Configuration
00103         args = [package_name + ".Configuration"]
00104         usingConvention = True
00105     
00106     if not opts.output:
00107         outputfile = os.path.join("..", "genConf", package_name + '_user_confDb.py')
00108     else:
00109         outputfile = opts.output
00110     
00111     # load configurables database to avoid fake duplicates
00112     loadConfigurableDb()
00113     # Collecting ConfigurableUser specializations
00114     cus = {}
00115     for mod in args:
00116         try:
00117             lst = getConfigurableUsers(mod, root = opts.root)
00118         except ImportError:
00119             if usingConvention: # the conventional module may not exist
00120                 continue
00121             logging.error("Cannot import module %r", mod)
00122             return 2
00123         if lst:
00124             cus[mod] = lst
00125         elif not usingConvention:
00126             logging.warning("Specified module %r does not contain ConfigurableUser specializations", mod)
00127     
00128     if cus:
00129         logging.info("ConfigurableUser found:\n%s", pformat(cus))
00130         # header
00131         output = """##  -*- python -*-
00132 # db file automatically generated by %s on: %s
00133 ## insulates outside world against anything bad that could happen
00134 ## also prevents global scope pollution
00135 def _fillCfgDb():
00136     from GaudiKernel.Proxy.ConfigurableDb import CfgDb
00137 
00138     # get a handle on the repository of Configurables
00139     cfgDb = CfgDb()
00140 
00141     # populate the repository with informations on Configurables 
00142 """ % (parser.prog, time.asctime())
00143         
00144         for mod in cus:
00145             for cu in cus[mod]:
00146                 output += """
00147     cfgDb.add( configurable = '%s',
00148                package = '%s',
00149                module  = '%s',
00150                lib     = 'None' )""" % (cu, package_name, mod)
00151 
00152         # trailer
00153         output += """
00154 
00155     return #_fillCfgDb
00156 
00157 # fill cfgDb at module import...
00158 try:
00159     _fillCfgDb()
00160     #house cleaning...
00161     del _fillCfgDb
00162 except Exception,err:
00163     print "Py:ConfigurableDb   ERROR Problem with [%%s] content!" %% __name__
00164     print "Py:ConfigurableDb   ERROR",err
00165     print "Py:ConfigurableDb   ERROR   ==> culprit is package [%s] !"
00166 """ % package_name
00167     elif usingConvention:
00168         logging.info("No ConfigurableUser found")
00169         output = "# No ConfigurableUser specialization\n"
00170     else:
00171         logging.error("No ConfigurableUser specialization found")
00172         return 1
00173 
00174     # create the destination directory if not there
00175     output_dir = os.path.dirname(outputfile)
00176     if not os.path.exists(output_dir):
00177         logging.info("Creating directory %r", output_dir)
00178         os.makedirs(output_dir, 0755)
00179     
00180     # write output to file
00181     logging.verbose("Writing confDb data to %r", outputfile)
00182     open(outputfile, "w").write(output)
00183     return 0
00184 
00185 if __name__ == '__main__':
00186     retcode = main()
00187     sys.exit(retcode)

Generated at Thu Jan 8 17:44:21 2009 for Gaudi Framework, version v20r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004