| # Gaudi Framework, version v22r4 |

Home |  | Generated: Fri Sep 2 2011

# 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     if not opts.output:
    00123         outputfile = os.path.join("..", "genConf", package_name + '_user_confDb.py')
    00124     else:
    00125         outputfile = opts.output
    00126
    00127     # The locking ensures that nobody tries to modify the python.zip file while
    00128     # we read it.
    00129     dbLock = None
    00130     if "GAUDI_BUILD_LOCK" in os.environ:
    00131         if opts.lockerpath:
    00132             sys.path.append(opts.lockerpath)
    00133         # Get the LockFile class from the locker module in GaudiPolicy or use a fake
    00134         # factory.
    00135         try:
    00136             from locker import LockFile
    00137         except ImportError:
    00138             def LockFile(*args, **kwargs):
    00139                 return None
    00140         # obtain the lock
    00141         dbLock = LockFile(os.environ["GAUDI_BUILD_LOCK"], temporary =  True)
    00142
    00143     # We can disable the error on missing configurables only if we can import Gaudi.Configurables
    00144     # It must be done at this point because it may conflict with logging.basicConfig
    00145     try:
    00146         import Gaudi.Configurables
    00147         Gaudi.Configurables.ignoreMissingConfigurables = True
    00148     except:
    00149         pass
    00150     # load configurables database to avoid fake duplicates
    00151     loadConfigurableDb()
    00152     # ensure that local configurables are in the database
    00153     try:
    00154         # Add the local python directories to the python path to be able to import the local
    00155         # configurables
    00156         sys.path.insert(0, os.path.join("..", "genConf"))
    00157         sys.path.insert(0, os.path.join("..", "python"))
    00158         localConfDb = os.path.join("..", "genConf", package_name, package_name + '_confDb.py')
    00159         if os.path.exists(localConfDb):
    00160             execfile(localConfDb, {}, {})
    00161     except:
    00162         pass # ignore failures (not important)
    00163     del dbLock # Now we can let the others operate on the install area python directory
    00164
    00165     # Collecting ConfigurableUser specializations
    00166     cus = {}
    00167     for mod in args:
    00168         lst = None
    00169         try:
    00170             lst = getConfigurableUsers(mod, root = opts.root, mayNotExist = usingConvention)
    00171         except ImportError:
    00172             import traceback
    00173             logging.error("Cannot import module %r:\n%s", mod,
    00174                           traceback.format_exc().rstrip()) # I remove the trailing '\n'
    00175             return 2
    00176         if lst:
    00177             cus[mod] = lst
    00178             # Add the configurables to the database as fake entries to avoid duplicates
    00179             for m in lst:
    00180                 cfgDb.add(configurable = m,
    00181                           package = 'None',
    00182                           module  = 'None',
    00183                           lib     = 'None')
    00184         elif not usingConvention:
    00185             logging.warning("Specified module %r does not contain ConfigurableUser specializations", mod)
    00186
    00187     if cus:
    00188         logging.info("ConfigurableUser found:\n%s", pformat(cus))
    00189         # header
    00190         output = """##  -*- python -*-
    00191 # db file automatically generated by %s on: %s
    00192 ## insulates outside world against anything bad that could happen
    00193 ## also prevents global scope pollution
    00194 def _fillCfgDb():
    00195     from GaudiKernel.Proxy.ConfigurableDb import CfgDb
    00196
    00197     # get a handle on the repository of Configurables
    00198     cfgDb = CfgDb()
    00199
    00200     # populate the repository with informations on Configurables
    00201 """ % (parser.prog, time.asctime())
    00202
    00203         for mod in cus:
    00204             for cu in cus[mod]:
    00205                 output += """
    00206     cfgDb.add( configurable = '%s',
    00207                package = '%s',
    00208                module  = '%s',
    00209                lib     = 'None' )""" % (cu, package_name, mod)
    00210
    00211         # trailer
    00212         output += """
    00213
    00214     return #_fillCfgDb
    00215
    00216 # fill cfgDb at module import...
    00217 try:
    00218     _fillCfgDb()
    00219     #house cleaning...
    00220     del _fillCfgDb
    00221 except Exception,err:
    00222     print "Py:ConfigurableDb   ERROR Problem with [%%s] content!" %% __name__
    00223     print "Py:ConfigurableDb   ERROR",err
    00224     print "Py:ConfigurableDb   ERROR   ==> culprit is package [%s] !"
    00225 """ % package_name
    00226     elif usingConvention:
    00227         logging.info("No ConfigurableUser found")
    00228         output = "# No ConfigurableUser specialization\n"
    00229     else:
    00230         logging.error("No ConfigurableUser specialization found")
    00231         return 1
    00232
    00233     # create the destination directory if not there
    00234     output_dir = os.path.dirname(outputfile)
    00235     if not os.path.exists(output_dir):
    00236         logging.info("Creating directory %r", output_dir)
    00237         os.makedirs(output_dir, 0755)
    00238
    00239     # write output to file
    00240     logging.verbose("Writing confDb data to %r", outputfile)
    00241     open(outputfile, "w").write(output)
    00242     return 0
    00243
    00244 if __name__ == '__main__':
    00245     retcode = main()
    00246     sys.exit(retcode)

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