![]() |
|
|
Generated: 8 Jan 2009 |
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)