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