| # 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)