| # Gaudi Framework, version v23r0 |

Home |  | Generated: Mon Jan 30 2012

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

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines