00001
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
00035 oldpath = list(sys.path)
00036
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
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
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
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
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
00115
00116 dbLock = None
00117 if "GAUDI_BUILD_LOCK" in os.environ:
00118 if opts.lockerpath:
00119 sys.path.append(opts.lockerpath)
00120
00121
00122 try:
00123 from locker import LockFile
00124 except ImportError:
00125 def LockFile(*args, **kwargs):
00126 return None
00127
00128 dbLock = LockFile(os.environ["GAUDI_BUILD_LOCK"], temporary = True)
00129
00130
00131
00132 try:
00133 import Gaudi.Configurables
00134 Gaudi.Configurables.ignoreMissingConfigurables = True
00135 except:
00136 pass
00137
00138 loadConfigurableDb()
00139
00140 try:
00141
00142
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
00150 del dbLock
00151
00152
00153 cus = {}
00154 for mod in args:
00155 try:
00156 lst = getConfigurableUsers(mod, root = opts.root)
00157 except ImportError:
00158 if usingConvention:
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
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
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
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
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)