![]() |
|
|
Generated: 8 Jan 2009 |
00001 //$Id: genconf.cpp,v 1.35 2008/10/15 21:51:24 marcocle Exp $ // 00002 00003 #ifdef _WIN32 00004 // Disable a warning in Boost program_options headers: 00005 // inconsistent linkage in program_options/variables_map.hpp 00006 #pragma warning ( disable : 4273 ) 00007 00008 // Avoid conflicts between windows and the message service. 00009 #define NOMSG 00010 #define NOGDI 00011 #endif 00012 00013 // Include files---------------------------------------------------------------- 00014 #include "boost/program_options.hpp" 00015 #include "boost/filesystem/operations.hpp" 00016 #include "boost/filesystem/exception.hpp" 00017 #include "boost/filesystem/convenience.hpp" 00018 #include "boost/algorithm/string/split.hpp" 00019 #include "boost/algorithm/string/classification.hpp" 00020 #include "boost/algorithm/string/trim.hpp" 00021 #include "boost/algorithm/string/case_conv.hpp" 00022 #include "boost/format.hpp" 00023 00024 #include "GaudiKernel/System.h" 00025 #include "GaudiKernel/ISvcLocator.h" 00026 #include "GaudiKernel/IProperty.h" 00027 #include "GaudiKernel/IAppMgrUI.h" 00028 #include "GaudiKernel/IAlgorithm.h" 00029 #include "GaudiKernel/IAlgTool.h" 00030 #include "GaudiKernel/IAuditor.h" 00031 #include "GaudiKernel/IAppMgrUI.h" 00032 #include "GaudiKernel/Service.h" 00033 #include "GaudiKernel/Bootstrap.h" 00034 #include "GaudiKernel/SmartIF.h" 00035 #include "GaudiKernel/HashMap.h" 00036 #include "GaudiKernel/GaudiHandle.h" 00037 00038 #include "Reflex/PluginService.h" 00039 #include "Reflex/Reflex.h" 00040 #include "Reflex/SharedLibrary.h" 00041 00042 #include "RVersion.h" 00043 00044 #include <algorithm> 00045 #include <iostream> 00046 #include <fstream> 00047 #include <sstream> 00048 #include <exception> 00049 #include <ctime> 00050 #include <set> 00051 #include <vector> 00052 00053 00054 #include "DsoUtils.h" 00055 00056 00057 00058 namespace po = boost::program_options; 00059 namespace fs = boost::filesystem; 00060 00061 using namespace std; 00062 using namespace ROOT::Reflex; 00063 00064 // useful typedefs 00065 typedef std::vector<std::string> Strings_t; 00066 typedef std::vector<fs::path> LibPathNames_t; 00067 00068 namespace { 00069 const std::string py_tab = " "; 00070 } 00071 00072 class configGenerator 00073 { 00075 string m_pkgName; 00076 00079 string m_outputDirName; 00080 00082 stringstream m_pyBuf; 00083 00086 bool m_importGaudiHandles; 00087 00092 stringstream m_dbBuf; 00093 00099 GaudiUtils::HashMap<std::string, std::string> m_configurable; 00100 00101 public: 00102 configGenerator( const string& pkgName, 00103 const string& outputDirName ) : 00104 m_pkgName ( pkgName ), 00105 m_outputDirName ( outputDirName ), 00106 m_pyBuf ( ), 00107 m_importGaudiHandles( false ), 00108 m_dbBuf ( ), 00109 m_configurable ( ) 00110 {} 00111 00116 int genConfig( const Strings_t& modules ); 00117 00119 void setConfigurableModule( const std::string& moduleName ) 00120 { 00121 m_configurable[ "Module" ] = moduleName; 00122 } 00123 00125 void setConfigurableDefaultName( const std::string& defaultName ) 00126 { 00127 m_configurable[ "DefaultName" ] = defaultName; 00128 } 00129 00131 void setConfigurableAlgorithm( const std::string& cfgAlgorithm ) 00132 { 00133 m_configurable[ "Algorithm" ] = cfgAlgorithm; 00134 } 00135 00137 void setConfigurableAlgTool( const std::string& cfgAlgTool ) 00138 { 00139 m_configurable[ "AlgTool" ] = cfgAlgTool; 00140 } 00141 00143 void setConfigurableAuditor( const std::string& cfgAuditor ) 00144 { 00145 m_configurable[ "Auditor" ] = cfgAuditor; 00146 } 00147 00149 void setConfigurableService( const std::string& cfgService ) 00150 { 00151 m_configurable[ "Service" ] = cfgService; 00152 m_configurable[ "ApplicationMgr" ] = cfgService; 00153 } 00154 00155 private: 00156 void genComponent( const std::string& libName, 00157 const std::string& componentName, 00158 const std::string& componentType, 00159 const vector<Property*>& properties ); 00160 void genImport( std::ostream& s, const boost::format& frmt,std::string indent); 00161 void genHeader( std::ostream& pyOut, std::ostream& dbOut ); 00162 void genBody( std::ostream& pyOut, 00163 std::ostream& dbOut ) { 00164 pyOut << m_pyBuf.str() << flush; 00165 dbOut << m_dbBuf.str() << flush; 00166 } 00167 void genTrailer( std::ostream& pyOut, 00168 std::ostream& dbOut ); 00169 00171 void pythonizeValue( const Property* prop, 00172 string& pvalue, 00173 string& ptype ); 00174 00176 void pythonizeName( string& name ); 00177 }; 00178 00179 int createAppMgr(); 00180 00181 //--- Command main program----------------------------------------------------- 00182 int main ( int argc, char** argv ) 00183 //----------------------------------------------------------------------------- 00184 { 00185 fs::path::default_name_check(fs::native); 00186 fs::path pwd = fs::initial_path(); 00187 fs::path out; 00188 Strings_t libs; 00189 std::string pkgName; 00190 00191 // declare a group of options that will be allowed only on command line 00192 po::options_description generic("Generic options"); 00193 generic.add_options() 00194 ("help,h", 00195 "produce this help message") 00196 ("package-name,p", 00197 po::value<string>(), 00198 "name of the package for which we create the configurables file") 00199 ("input-libraries,i", 00200 po::value<string>(), 00201 "libraries to extract the component configurables from") 00202 ("input-cfg,c", 00203 po::value<string>(), 00204 "path to the cfg file holding the description of the Configurable base " 00205 "classes, the python module holding the Configurable definitions, etc...") 00206 ("output-dir,o", 00207 po::value<string>()->default_value("../genConf"), 00208 "output directory for genconf files.") 00209 ("debug-level,d", 00210 po::value<int>()->default_value(0), 00211 "debug level") 00212 ("load-library,l", 00213 po::value< Strings_t >()->composing(), 00214 "preloading library") 00215 ; 00216 00217 // declare a group of options that will be allowed both on command line 00218 // _and_ in configuration file 00219 po::options_description config("Configuration"); 00220 config.add_options() 00221 ("configurable-module", 00222 po::value<string>()->default_value("AthenaCommon"), 00223 "Name of the module holding the configurable classes") 00224 ("configurable-default-name", 00225 po::value<string>()->default_value("Configurable.DefaultName"), 00226 "Default name for the configurable instance") 00227 ("configurable-algorithm", 00228 po::value<string>()->default_value("ConfigurableAlgorithm"), 00229 "Name of the configurable base class for Algorithm components") 00230 ("configurable-algtool", 00231 po::value<string>()->default_value("ConfigurableAlgTool"), 00232 "Name of the configurable base class for AlgTool components") 00233 ("configurable-auditor", 00234 po::value<string>()->default_value("ConfigurableAuditor"), 00235 "Name of the configurable base class for Auditor components") 00236 ("configurable-service", 00237 po::value<string>()->default_value("ConfigurableService"), 00238 "Name of the configurable base class for Service components") 00239 ; 00240 00241 po::options_description cmdline_options; 00242 cmdline_options.add(generic).add(config); 00243 00244 po::options_description config_file_options; 00245 config_file_options.add(config); 00246 00247 po::options_description visible("Allowed options"); 00248 visible.add(generic).add(config); 00249 00250 po::variables_map vm; 00251 00252 try { 00253 po::store( po::command_line_parser(argc, argv). 00254 options(cmdline_options).run(), 00255 vm ); 00256 00257 po::notify(vm); 00258 00259 // try to read configuration from the optionnally given configuration file 00260 if( vm.count("input-cfg") ) { 00261 string cfgFileName = vm["input-cfg"].as<string>(); 00262 cfgFileName = fs::complete( fs::path( cfgFileName, 00263 fs::native ) ).string(); 00264 std::ifstream ifs( cfgFileName.c_str() ); 00265 po::store( parse_config_file( ifs, config_file_options ), vm ); 00266 } 00267 00268 po::notify(vm); 00269 } 00270 catch ( po::error& err ) { 00271 cout << "ERR0R: error detected while parsing command options: "<< err.what() << endl; 00272 return EXIT_FAILURE; 00273 } 00274 00275 //--- Process command options ----------------------------------------------- 00276 if( vm.count("help")) { 00277 cout << visible << endl; 00278 return EXIT_FAILURE; 00279 } 00280 00281 if( vm.count("package-name") ) { 00282 pkgName = vm["package-name"].as<string>(); 00283 } 00284 else { 00285 cout << "ERROR: 'package-name' required" << endl; 00286 cout << visible << endl; 00287 return EXIT_FAILURE; 00288 } 00289 00290 if( vm.count("input-libraries") ) { 00291 // re-shape the input arguments: 00292 // - removes spurious spaces, 00293 // - split into tokens. 00294 Strings_t inputLibs; 00295 { 00296 string tmp = vm["input-libraries"].as<string>(); 00297 boost::trim(tmp); 00298 boost::split( inputLibs, tmp, 00299 boost::is_any_of(" "), 00300 boost::token_compress_on ); 00301 } 00302 00303 // 00304 libs.reserve( inputLibs.size() ); 00305 for ( Strings_t::const_iterator iLib = inputLibs.begin(); 00306 iLib != inputLibs.end(); 00307 ++iLib ) { 00308 fs::path libPath = fs::path( *iLib, fs::native ); 00309 std::string lib = libPath.leaf().substr(0, libPath.leaf().find('.') ); 00310 if ( 0 == lib.find("lib") ) { 00311 lib = lib.substr(3); // For *NIX remove "lib" 00312 } 00313 // remove duplicates 00314 if ( !lib.empty() && 00315 std::find( libs.begin(), libs.end(), lib ) == libs.end() ) { 00316 libs.push_back( lib ); 00317 } 00318 } //> end loop over input-libraries 00319 if ( libs.empty() ) { 00320 cout << "ERROR: input component library(ies) required !\n" 00321 << "ERROR: 'input-libraries' argument was [" 00322 << vm["input-libraries"].as<string>() 00323 << "]" 00324 << endl; 00325 return EXIT_FAILURE; 00326 } 00327 } 00328 else { 00329 cout << "ERROR: input component library(ies) required" << endl; 00330 cout << visible << endl; 00331 return EXIT_FAILURE; 00332 } 00333 00334 if( vm.count("output-dir") ) { 00335 out = fs::complete( fs::path( vm["output-dir"].as<string>(), 00336 fs::native ) ); 00337 } 00338 00339 if ( vm.count("debug-level") ) { 00340 PluginService::SetDebug( vm["debug-level"].as<int>() ); 00341 } 00342 00343 if ( vm.count("load-library") ) { 00344 Strings_t lLib_list = vm["load-library"].as< Strings_t >(); 00345 for (Strings_t::const_iterator lLib=lLib_list.begin(); 00346 lLib != lLib_list.end(); 00347 ++lLib) { 00348 // load done through ROOT::Reflex helper class 00349 SharedLibrary tmplib(*lLib) ; 00350 tmplib.Load() ; 00351 } 00352 } 00353 00354 00355 if ( !fs::exists( out ) ) { 00356 try { 00357 fs::create_directory(out); 00358 } 00359 catch ( fs::filesystem_error err ) { 00360 cout << "ERR0R: error creating directory: "<< err.what() << endl; 00361 return EXIT_FAILURE; 00362 } 00363 } 00364 00365 cout << ":::::: libraries : [ "; 00366 copy( libs.begin(), libs.end(), ostream_iterator<string>(cout, " ") ); 00367 cout << "] ::::::" << endl; 00368 00369 configGenerator py( pkgName, out.string() ); 00370 py.setConfigurableModule (vm["configurable-module"].as<string>()); 00371 py.setConfigurableDefaultName(vm["configurable-default-name"].as<string>()); 00372 py.setConfigurableAlgorithm (vm["configurable-algorithm"].as<string>()); 00373 py.setConfigurableAlgTool (vm["configurable-algtool"].as<string>()); 00374 py.setConfigurableAuditor (vm["configurable-auditor"].as<string>()); 00375 py.setConfigurableService (vm["configurable-service"].as<string>()); 00376 00377 int sc = EXIT_FAILURE; 00378 try { 00379 sc = py.genConfig( libs ); 00380 } 00381 catch ( exception& e ) { 00382 cout << "ERROR: Could not generate Configurable(s) !\n" 00383 << "ERROR: Got exception: " << e.what() << endl; 00384 return EXIT_FAILURE; 00385 } 00386 00387 if ( EXIT_SUCCESS == sc ) { 00388 // create an empty __init__.py file in the output dir 00389 fstream initPy( ( out / fs::path( "__init__.py" ) ).string().c_str(), 00390 std::ios_base::out|std::ios_base::trunc ); 00391 initPy << "## Hook for " << pkgName << " genConf module\n" << flush; 00392 } 00393 00394 cout << ":::::: libraries : [ "; 00395 copy( libs.begin(), libs.end(), ostream_iterator<string>(cout, " ") ); 00396 cout << "] :::::: [DONE]" << endl; 00397 00398 return sc; 00399 } 00400 00403 inline std::string getId(const Member & m) { 00404 return (m.Properties().HasProperty("id") && (m.Properties().PropertyValue("id").TypeInfo() == typeid(std::string))) ? 00405 m.Properties().PropertyAsString("id") : 00406 m.Properties().PropertyAsString("name") ; 00407 } 00408 00409 template <class T> 00410 IProperty *makeInstance(const Member &member, const vector<void*> &args) 00411 { 00412 Object dummy; 00413 T* obj; 00414 #if ROOT_VERSION_CODE < ROOT_VERSION(5,21,6) 00415 obj = static_cast<T*>(member.Invoke(dummy,args).Address()); 00416 #else 00417 member.Invoke(dummy,obj,args); 00418 #endif 00419 return dynamic_cast<IProperty*>(obj); 00420 } 00421 00422 00423 //----------------------------------------------------------------------------- 00424 int configGenerator::genConfig( const Strings_t& libs ) 00425 //----------------------------------------------------------------------------- 00426 { 00427 //--- Disable checking StatusCode ------------------------------------------- 00428 StatusCode::disableChecking(); 00429 00430 const Strings_t::const_iterator endLib = libs.end(); 00431 00432 const std::string gaudiSvc = "GaudiSvc"; 00433 const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib ); 00434 00435 //--- Instantiate ApplicationMgr -------------------------------------------- 00436 if ( !isGaudiSvc && createAppMgr() ) { 00437 cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl; 00438 return EXIT_FAILURE; 00439 } 00440 00441 //--- Iterate over component factories -------------------------------------- 00442 Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS); 00443 if ( !factories ) { 00444 cout << "ERROR: No PluginSvc factory namespace could be found" << endl; 00445 return EXIT_FAILURE; 00446 } 00447 00448 ISvcLocator* svcLoc = Gaudi::svcLocator(); 00449 IService* dummySvc = new Service( "DummySvc", svcLoc ); 00450 dummySvc->addRef(); 00451 00452 bool allGood = true; 00453 00454 // iterate over all the requested libraries 00455 for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) { 00456 00457 std::cout << ":::: processing library: " << *iLib << "..." << std::endl; 00458 00459 // reset state 00460 m_importGaudiHandles = false; 00461 m_pyBuf.str(""); 00462 m_dbBuf.str(""); 00463 00464 // Scan the pluginSvc namespace and store the "background" of already 00465 // alived components, so we can extract our signal later on 00466 set<string> bkgNames; 00467 if ( !isGaudiSvc ) { 00468 for ( Member_Iterator it = factories.FunctionMember_Begin(); 00469 it != factories.FunctionMember_End(); ++it ) { 00470 string ident = getId(*it); 00471 if ( PluginService::Debug() > 0 ) { 00472 cout << "::: " << ident << endl; 00473 } 00474 bkgNames.insert( ident ); 00475 } 00476 } 00477 const set<string>::const_iterator bkgNamesEnd = bkgNames.end(); 00478 00479 //--- Load component library ---------------------------------------------- 00480 System::ImageHandle handle; 00481 unsigned long err = System::loadDynamicLib( *iLib, &handle ); 00482 if ( err != 1 ) { 00483 cout << "ERROR: " << System::getLastErrorString() << endl; 00484 allGood = false; 00485 continue; 00486 } 00487 00488 for ( Member_Iterator it = factories.FunctionMember_Begin(); 00489 it != factories.FunctionMember_End(); 00490 ++it ) { 00491 const string ident = getId(*it); 00492 if ( bkgNames.find(ident) != bkgNamesEnd ) { 00493 if ( PluginService::Debug() > 0 ) { 00494 cout << "\t==> skipping [" << ident << "]..." << endl; 00495 } 00496 continue; 00497 } 00498 00499 // Atlas contributed code (patch #1247) 00500 // Skip the generation of configurables if the component does not come 00501 // from the same library we are processing (i.e. we found a symbol that 00502 // is coming from a library loaded by the linker). 00503 // Windows implementation is empty. 00504 if ( !DsoUtils::inDso( *it, DsoUtils::libNativeName(*iLib) ) ) { 00505 cout << "WARNING: library [" << *iLib << "] requested factory " 00506 << "from another library [" 00507 << DsoUtils::dsoName(*it) << "]" 00508 << " ==> [" << ident << "] !!" 00509 << endl; 00510 continue; 00511 } 00512 00513 const string rtype = it->TypeOf().ReturnType().Name(); 00514 string type; 00515 bool known = true; 00516 if ( ident == "ApplicationMgr" ) type = "ApplicationMgr"; 00517 else if ( rtype == "IInterface*" ) type = "IInterface"; 00518 else if ( rtype == "IAlgorithm*" ) type = "Algorithm"; 00519 else if ( rtype == "IService*" ) type = "Service"; 00520 else if ( rtype == "IAlgTool*" ) type = "AlgTool"; 00521 else if ( rtype == "IAuditor*" ) type = "Auditor"; 00522 else if ( rtype == "IConverter*" ) type = "Converter"; 00523 else if ( rtype == "DataObject*" ) type = "DataObject"; 00524 else type = "Unknown", known = false; 00525 string name = ident; 00526 // handle possible problems with templated components 00527 boost::trim(name); 00528 00529 cout << " - component: " << name << endl; 00530 00531 if ( type == "IInterface" ) { 00534 continue; 00535 } 00536 00537 if ( type == "Converter" || type == "DataObject" ) { 00539 continue; 00540 } 00541 00542 //if ( type == "ApplicationMgr" ) { 00545 //} 00546 00547 if ( !known ) { 00548 cout << "WARNING: Unknown (return) type [" << rtype << "] !!\n" 00549 << "WARNING: component [" << ident << "] is skipped !" 00550 << endl; 00551 allGood = false; 00552 continue; 00553 } 00554 00555 string cname = "DefaultName"; 00556 vector<void*> args; 00557 args.reserve( 3 ); 00558 if ( type == "AlgTool" ) { 00559 args.resize( 3 ); 00560 args[0] = &cname; 00561 args[1] = &type; 00562 args[2] = dummySvc; 00563 } 00564 else { 00565 args.resize( 2 ); 00566 args[0] = &cname; 00567 args[1] = svcLoc; 00568 } 00569 IProperty* prop = 0; 00570 try { 00571 if ( type == "Algorithm" ) { 00572 prop = makeInstance<IAlgorithm>(*it,args); 00573 } 00574 else if ( type == "Service") { 00575 prop = makeInstance<IService>(*it,args); 00576 } 00577 else if ( type == "AlgTool") { 00578 prop = makeInstance<IAlgTool>(*it,args); 00579 } 00580 else if ( type == "Auditor") { 00581 prop = makeInstance<IAuditor>(*it,args); 00582 } 00583 else if ( type == "ApplicationMgr") { 00584 //svcLoc->queryInterface(IProperty::interfaceID(), pp_cast<void>(&prop)); 00585 svcLoc->queryInterface(IProperty::interfaceID(), (void**)(&prop)); 00586 } 00587 else { 00588 prop = makeInstance<IInterface>(*it,args); 00589 } 00590 } 00591 catch ( exception& e ) { 00592 cout << "ERROR: Error instantiating " << name 00593 << " from " << *iLib << endl; 00594 cout << "ERROR: Got exception: " << e.what() << endl; 00595 allGood = false; 00596 continue; 00597 } 00598 catch ( ... ) { 00599 cout << "ERROR: Error instantiating " << name 00600 << " from " << *iLib << endl; 00601 allGood = false; 00602 continue; 00603 } 00604 if( prop ) { 00605 genComponent( *iLib, name, type, prop->getProperties() ); 00606 prop->release(); 00607 } else { 00608 cout << "ERROR: could not cast IInterface* object to an IProperty* !\n" 00609 << "ERROR: return type from PluginSvc is [" << rtype << "]...\n" 00610 << "ERROR: NO Configurable will be generated for [" 00611 << name << "] !" 00612 << endl; 00613 allGood = false; 00614 } 00615 } //> end loop over factories 00616 00620 const std::string pyName = ( fs::path(m_outputDirName) / 00621 fs::path(*iLib+"Conf.py") ).string(); 00622 const std::string dbName = ( fs::path(m_outputDirName) / 00623 fs::path(*iLib+"_confDb.py") ).string(); 00624 00625 std::fstream py( pyName.c_str(), 00626 std::ios_base::out|std::ios_base::trunc ); 00627 std::fstream db( dbName.c_str(), 00628 std::ios_base::out|std::ios_base::trunc ); 00629 00630 genHeader ( py, db ); 00631 genBody ( py, db ); 00632 genTrailer( py, db ); 00633 00634 } //> end loop over libraries 00635 00636 dummySvc->release(); 00637 dummySvc = 0; 00638 00639 return allGood ? EXIT_SUCCESS : EXIT_FAILURE; 00640 } 00641 00642 void configGenerator::genImport( std::ostream& s, 00643 const boost::format& frmt, 00644 std::string indent = ""){ 00645 00646 std::string::size_type pos = 0, nxtpos = 0; 00647 std::string mod; 00648 00649 while ( std::string::npos != pos ){ 00650 // find end of module name 00651 nxtpos = m_configurable["Module"].find_first_of(',',pos); 00652 00653 // Prepare import string 00654 mod = m_configurable["Module"].substr(pos,nxtpos-pos); 00655 std::ostringstream import; 00656 import << boost::format(frmt) % mod; 00657 00658 // append a normal import or a try/excpet enclosed one depending 00659 // on availability of a fall-back bodule (next in the list) 00660 if ( std::string::npos == nxtpos ) { 00661 // last possible module 00662 s << indent << import.str() << "\n" << flush; 00663 pos = std::string::npos; 00664 } else { 00665 // we have a fallback for this 00666 s << indent << "try:\n" 00667 << indent << py_tab << import.str() << "\n" 00668 << indent << "except ImportError:\n" 00669 << flush; 00670 pos = nxtpos+1; 00671 } 00672 // increase indentation level for next iteration 00673 indent += py_tab; 00674 } 00675 } 00676 00677 //----------------------------------------------------------------------------- 00678 void configGenerator::genHeader( std::ostream& py, 00679 std::ostream& db ) 00680 //----------------------------------------------------------------------------- 00681 { 00682 // python file part 00683 time_t rawtime; 00684 time( &rawtime ); 00685 py << "#" << ctime(&rawtime) //<< "\n" 00686 << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n"; 00687 if ( m_importGaudiHandles ) { 00688 py << "from GaudiKernel.GaudiHandles import *\n"; 00689 } 00690 00691 genImport(py,boost::format("from %1%.Configurable import *")); 00692 00693 // db file part 00694 db << "## -*- python -*- \n" 00695 << "# db file automatically generated by genconf on: " 00696 << ctime(&rawtime); // << "\n"; 00697 db << "## insulates outside world against anything bad that could happen\n" 00698 << "## also prevents global scope pollution\n" 00699 << "def _fillCfgDb():\n"; 00700 genImport(db,boost::format("from %1%.ConfigurableDb import CfgDb"),py_tab); 00701 00702 db << "\n" 00703 << py_tab << "# get a handle on the repository of Configurables\n" 00704 << py_tab << "cfgDb = CfgDb()\n" 00705 << "\n" 00706 << py_tab << "# populate the repository with informations on Configurables \n" 00707 << "\n" 00708 << flush; 00709 } 00710 //----------------------------------------------------------------------------- 00711 void configGenerator::genTrailer( std::ostream& /*py*/, 00712 std::ostream& db ) 00713 //----------------------------------------------------------------------------- 00714 { 00715 // db file part 00716 db << py_tab << "return #_fillCfgDb\n" 00717 << "# fill cfgDb at module import...\n" 00718 << "try:\n" 00719 << py_tab << "_fillCfgDb()\n" 00720 << py_tab << "#house cleaning...\n" 00721 << py_tab << "del _fillCfgDb\n" 00722 << "except Exception,err:\n" 00723 << py_tab << "print \"Py:ConfigurableDb ERROR Problem with [%s] content!" 00724 << "\" % __name__\n" 00725 << py_tab << "print \"Py:ConfigurableDb ERROR\",err\n" 00726 << py_tab << "print \"Py:ConfigurableDb ERROR ==> culprit is package [" 00727 << m_pkgName << "] !\"\n" 00728 << std::flush; 00729 } 00730 00731 //----------------------------------------------------------------------------- 00732 void configGenerator::genComponent( const std::string& libName, 00733 const std::string& componentName, 00734 const std::string& componentType, 00735 const vector<Property*>& properties ) 00736 //----------------------------------------------------------------------------- 00737 { 00738 string cname = componentName; 00739 pythonizeName(cname); 00740 00741 typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t; 00742 PropertyDoc_t propDoc; 00743 00744 m_pyBuf << "\n"; 00745 m_pyBuf << "class " << cname 00746 << "( " << m_configurable[componentType] << " ) :" 00747 << "\n"; 00748 m_pyBuf << " __slots__ = { \n"; 00749 for ( vector<Property*>::const_iterator it = properties.begin() ; 00750 it != properties.end(); ++it ) { 00751 const string pname = (*it)->name(); 00752 string pvalue, ptype; 00753 pythonizeValue( (*it), pvalue, ptype ); 00754 m_pyBuf << " '" << pname << "' : " << pvalue <<", # " << ptype << "\n"; 00755 00756 if ( (*it)->documentation() != "none" ) { 00757 propDoc[pname] = (*it)->documentation(); 00758 } 00759 00760 } 00761 m_pyBuf << " }\n"; 00762 m_pyBuf << " _propertyDocDct = { \n"; 00763 for ( PropertyDoc_t::const_iterator iProp = propDoc.begin(); 00764 iProp != propDoc.end(); 00765 ++iProp ) { 00766 m_pyBuf << std::setw(5) 00767 << "'" << iProp->first << "' : " 00768 << "\"\"\" " << iProp->second << " \"\"\",\n"; 00769 } 00770 m_pyBuf << " }\n"; 00771 00772 m_pyBuf 00773 << " def __init__(self, name = " << m_configurable["DefaultName"] 00774 << ", **kwargs):\n" 00775 << " super(" << cname << ", self).__init__(name)\n" 00776 << " for n,v in kwargs.items():\n" 00777 << " setattr(self, n, v)\n" 00778 << " def getDlls( self ):\n" 00779 << " return '" << libName << "'\n" 00780 << " def getType( self ):\n" 00781 << " return '" << componentName << "'\n" 00782 << " pass # class " << cname << "\n" 00783 << flush; 00784 00785 // name of the auto-generated module 00786 const string pyName = ( fs::path(m_outputDirName) / 00787 fs::path(libName+"Conf.py") ).string(); 00788 const string modName = fs::basename( fs::path( pyName ).leaf() ); 00789 00790 // now the db part 00791 m_dbBuf 00792 << py_tab << "cfgDb.add( configurable = '" << cname << "',\n" 00793 << py_tab << " package = '" << m_pkgName << "',\n" 00794 << py_tab << " module = '" << m_pkgName << "." << modName << "',\n" 00795 << py_tab << " lib = '" << libName << "' )\n" 00796 << flush; 00797 00798 } 00799 //----------------------------------------------------------------------------- 00800 void configGenerator::pythonizeName( string& name ) 00801 //----------------------------------------------------------------------------- 00802 { 00803 static string in("<>&*,: ()."); 00804 static string out("__rp__s___"); 00805 for ( string::iterator i = name.begin(); i != name.end(); ++i ) { 00806 if ( in.find(*i) != string::npos ) *i = out[in.find(*i)]; 00807 } 00808 } 00809 00810 //----------------------------------------------------------------------------- 00811 void configGenerator::pythonizeValue( const Property* p, 00812 string& pvalue, string& ptype ) 00813 //----------------------------------------------------------------------------- 00814 { 00815 const std::string cvalue = p->toString(); 00816 const type_info& ti = *p->type_info(); 00817 if ( ti == typeid(bool) ) { 00818 pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" ) 00819 ? "False" 00820 : "True"; 00821 ptype = "bool"; 00822 } 00823 else if ( ti == typeid(char) || ti == typeid(signed char) 00824 || ti == typeid(unsigned char) || 00825 ti == typeid(short) || ti == typeid(unsigned short) || 00826 ti == typeid(int) || ti == typeid(unsigned int) || 00827 ti == typeid(long) || ti == typeid(unsigned long) ) { 00828 pvalue = cvalue; 00829 ptype = "int"; 00830 } 00831 else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) { 00832 pvalue = cvalue + "L"; 00833 ptype = "long"; 00834 } 00835 else if ( ti == typeid(float) || ti == typeid(double) ) { 00836 // forces python to handle this as a float: put a dot in there... 00837 pvalue = boost::to_lower_copy(cvalue); 00838 if ( pvalue == "nan" ) { 00839 pvalue = "float('nan')"; 00840 std::cout << "WARNING: default value for [" 00841 << p->name() << "] is NaN !!" 00842 << std::endl; 00843 } else if ( std::string::npos == pvalue.find(".") && 00844 std::string::npos == pvalue.find("e") ) { 00845 pvalue = cvalue + ".0"; 00846 } 00847 ptype = "float"; 00848 } 00849 else if ( ti == typeid(string) ) { 00850 00851 pvalue = "'"+cvalue+"'"; 00852 ptype = "str"; 00853 } 00854 else if ( ti == typeid(GaudiHandleBase) ) { 00855 m_importGaudiHandles = true; 00856 const GaudiHandleProperty& hdl 00857 = dynamic_cast<const GaudiHandleProperty&>(*p); 00858 const GaudiHandleBase& base = hdl.value(); 00859 00860 pvalue = base.pythonRepr(); 00861 ptype = "GaudiHandle"; 00862 } 00863 else if ( ti == typeid(GaudiHandleArrayBase) ) { 00864 m_importGaudiHandles = true; 00865 const GaudiHandleArrayProperty& hdl 00866 = dynamic_cast<const GaudiHandleArrayProperty&>(*p); 00867 const GaudiHandleArrayBase& base = hdl.value(); 00868 00869 pvalue = base.pythonRepr(); 00870 ptype = "GaudiHandleArray"; 00871 } 00872 else { 00873 pvalue = cvalue; 00874 ptype = "list"; 00875 } 00876 } 00877 00878 //----------------------------------------------------------------------------- 00879 int createAppMgr() 00880 //----------------------------------------------------------------------------- 00881 { 00882 IInterface* iface = Gaudi::createApplicationMgr(); 00883 SmartIF<IProperty> propMgr ( IID_IProperty, iface ); 00884 SmartIF<IAppMgrUI> appUI ( IID_IAppMgrUI, iface ); 00885 00886 if ( propMgr.isValid() && appUI.isValid() ) { 00887 propMgr->setProperty( "JobOptionsType", "NONE" ); // No joboptions 00888 propMgr->setProperty( "AppName", ""); // No initial printout message 00889 propMgr->setProperty( "OutputLevel", "7"); // No other printout messages 00890 appUI->configure(); 00891 return EXIT_SUCCESS; 00892 } 00893 else { 00894 return EXIT_FAILURE; 00895 } 00896 }