![]() |
|
|
Generated: 18 Jul 2008 |
00001 //$Id: genconf.cpp,v 1.33 2008/04/03 17:56:40 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 00399 //----------------------------------------------------------------------------- 00400 int configGenerator::genConfig( const Strings_t& libs ) 00401 //----------------------------------------------------------------------------- 00402 { 00403 //--- Disable checking StatusCode ------------------------------------------- 00404 StatusCode::disableChecking(); 00405 00406 const Strings_t::const_iterator endLib = libs.end(); 00407 00408 const std::string gaudiSvc = "GaudiSvc"; 00409 const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib ); 00410 00411 //--- Instantiate ApplicationMgr -------------------------------------------- 00412 if ( !isGaudiSvc && createAppMgr() ) { 00413 cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl; 00414 return EXIT_FAILURE; 00415 } 00416 00417 //--- Iterate over component factories -------------------------------------- 00418 Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS); 00419 if ( !factories ) { 00420 cout << "ERROR: No PluginSvc factory namespace could be found" << endl; 00421 return EXIT_FAILURE; 00422 } 00423 00424 ISvcLocator* svcLoc = Gaudi::svcLocator(); 00425 IService* dummySvc = new Service( "DummySvc", svcLoc ); 00426 dummySvc->addRef(); 00427 00428 bool allGood = true; 00429 00430 // iterate over all the requested libraries 00431 for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) { 00432 00433 std::cout << ":::: processing library: " << *iLib << "..." << std::endl; 00434 00435 // reset state 00436 m_importGaudiHandles = false; 00437 m_pyBuf.str(""); 00438 m_dbBuf.str(""); 00439 00440 // Scan the pluginSvc namespace and store the "background" of already 00441 // alived components, so we can extract our signal later on 00442 set<string> bkgNames; 00443 if ( !isGaudiSvc ) { 00444 for ( Member_Iterator it = factories.FunctionMember_Begin(); 00445 it != factories.FunctionMember_End(); ++it ) { 00446 string ident = it->Properties().PropertyAsString("name"); 00447 if ( PluginService::Debug() > 0 ) { 00448 cout << "::: " << ident << endl; 00449 } 00450 bkgNames.insert( ident ); 00451 } 00452 } 00453 const set<string>::const_iterator bkgNamesEnd = bkgNames.end(); 00454 00455 //--- Load component library ---------------------------------------------- 00456 System::ImageHandle handle; 00457 unsigned long err = System::loadDynamicLib( *iLib, &handle ); 00458 if ( err != 1 ) { 00459 cout << "ERROR: " << System::getLastErrorString() << endl; 00460 allGood = false; 00461 continue; 00462 } 00463 00464 for ( Member_Iterator it = factories.FunctionMember_Begin(); 00465 it != factories.FunctionMember_End(); 00466 ++it ) { 00467 const string ident = it->Properties().PropertyAsString("name"); 00468 if ( bkgNames.find(ident) != bkgNamesEnd ) { 00469 if ( PluginService::Debug() > 0 ) { 00470 cout << "\t==> skipping [" << ident << "]..." << endl; 00471 } 00472 continue; 00473 } 00474 00475 // Atlas contributed code (patch #1247) 00476 // Skip the generation of configurables if the component does not come 00477 // from the same library we are processing (i.e. we found a symbol that 00478 // is coming from a library loaded by the linker). 00479 // Windows implementation is empty. 00480 if ( !DsoUtils::inDso( *it, DsoUtils::libNativeName(*iLib) ) ) { 00481 cout << "WARNING: library [" << *iLib << "] requested factory " 00482 << "from another library [" 00483 << DsoUtils::dsoName(*it) << "]" 00484 << " ==> [" << ident << "] !!" 00485 << endl; 00486 continue; 00487 } 00488 00489 const string rtype = it->TypeOf().ReturnType().Name(); 00490 string type; 00491 bool known = true; 00492 if ( ident == "ApplicationMgr" ) type = "ApplicationMgr"; 00493 else if ( rtype == "IInterface*" ) type = "IInterface"; 00494 else if ( rtype == "IAlgorithm*" ) type = "Algorithm"; 00495 else if ( rtype == "IService*" ) type = "Service"; 00496 else if ( rtype == "IAlgTool*" ) type = "AlgTool"; 00497 else if ( rtype == "IAuditor*" ) type = "Auditor"; 00498 else if ( rtype == "IConverter*" ) type = "Converter"; 00499 else if ( rtype == "DataObject*" ) type = "DataObject"; 00500 else type = "Unknown", known = false; 00501 string name = ident; 00502 // handle possible problems with templated components 00503 boost::trim(name); 00504 00505 cout << " - component: " << name << endl; 00506 00507 if ( type == "IInterface" ) { 00510 continue; 00511 } 00512 00513 if ( type == "Converter" || type == "DataObject" ) { 00515 continue; 00516 } 00517 00518 //if ( type == "ApplicationMgr" ) { 00521 //} 00522 00523 if ( !known ) { 00524 cout << "WARNING: Unknown (return) type [" << rtype << "] !!\n" 00525 << "WARNING: component [" << ident << "] is skipped !" 00526 << endl; 00527 allGood = false; 00528 continue; 00529 } 00530 00531 string cname = "DefaultName"; 00532 Object dummy; 00533 vector<void*> args; 00534 args.reserve( 3 ); 00535 if ( type == "AlgTool" ) { 00536 args.resize( 3 ); 00537 args[0] = &cname; 00538 args[1] = &type; 00539 args[2] = dummySvc; 00540 } 00541 else { 00542 args.resize( 2 ); 00543 args[0] = &cname; 00544 args[1] = svcLoc; 00545 } 00546 IProperty* prop = 0; 00547 try { 00548 if ( type == "Algorithm" ) { 00549 IAlgorithm* obj = static_cast<IAlgorithm*>(it->Invoke(dummy,args).Address()); 00550 prop = dynamic_cast<IProperty*>(obj); 00551 } 00552 else if ( type == "Service") { 00553 IService* obj = static_cast<IService*>(it->Invoke(dummy,args).Address()); 00554 prop = dynamic_cast<IProperty*>(obj); 00555 } 00556 else if ( type == "AlgTool") { 00557 IAlgTool* obj = static_cast<IAlgTool*>(it->Invoke(dummy,args).Address()); 00558 prop = dynamic_cast<IProperty*>(obj); 00559 } 00560 else if ( type == "Auditor") { 00561 IAuditor* obj = static_cast<IAuditor*>(it->Invoke(dummy,args).Address()); 00562 prop = dynamic_cast<IProperty*>(obj); 00563 } 00564 else if ( type == "ApplicationMgr") { 00565 //svcLoc->queryInterface(IProperty::interfaceID(), pp_cast<void>(&prop)); 00566 svcLoc->queryInterface(IProperty::interfaceID(), (void**)(&prop)); 00567 } 00568 else { 00569 IInterface* obj = static_cast<IInterface*>(it->Invoke(dummy,args).Address()); 00570 prop = dynamic_cast<IProperty*>(obj); 00571 } 00572 } 00573 catch ( exception& e ) { 00574 cout << "ERROR: Error instantiating " << name 00575 << " from " << *iLib << endl; 00576 cout << "ERROR: Got exception: " << e.what() << endl; 00577 allGood = false; 00578 continue; 00579 } 00580 catch ( ... ) { 00581 cout << "ERROR: Error instantiating " << name 00582 << " from " << *iLib << endl; 00583 allGood = false; 00584 continue; 00585 } 00586 if( prop ) { 00587 genComponent( *iLib, name, type, prop->getProperties() ); 00588 prop->release(); 00589 } else { 00590 cout << "ERROR: could not cast IInterface* object to an IProperty* !\n" 00591 << "ERROR: return type from PluginSvc is [" << rtype << "]...\n" 00592 << "ERROR: NO Configurable will be generated for [" 00593 << name << "] !" 00594 << endl; 00595 allGood = false; 00596 } 00597 } //> end loop over factories 00598 00602 const std::string pyName = ( fs::path(m_outputDirName) / 00603 fs::path(*iLib+"Conf.py") ).string(); 00604 const std::string dbName = ( fs::path(m_outputDirName) / 00605 fs::path(*iLib+"_confDb.py") ).string(); 00606 00607 std::fstream py( pyName.c_str(), 00608 std::ios_base::out|std::ios_base::trunc ); 00609 std::fstream db( dbName.c_str(), 00610 std::ios_base::out|std::ios_base::trunc ); 00611 00612 genHeader ( py, db ); 00613 genBody ( py, db ); 00614 genTrailer( py, db ); 00615 00616 } //> end loop over libraries 00617 00618 dummySvc->release(); 00619 dummySvc = 0; 00620 00621 return allGood ? EXIT_SUCCESS : EXIT_FAILURE; 00622 } 00623 00624 void configGenerator::genImport( std::ostream& s, 00625 const boost::format& frmt, 00626 std::string indent = ""){ 00627 00628 std::string::size_type pos = 0, nxtpos = 0; 00629 std::string mod; 00630 00631 while ( std::string::npos != pos ){ 00632 // find end of module name 00633 nxtpos = m_configurable["Module"].find_first_of(',',pos); 00634 00635 // Prepare import string 00636 mod = m_configurable["Module"].substr(pos,nxtpos-pos); 00637 std::ostringstream import; 00638 import << boost::format(frmt) % mod; 00639 00640 // append a normal import or a try/excpet enclosed one depending 00641 // on availability of a fall-back bodule (next in the list) 00642 if ( std::string::npos == nxtpos ) { 00643 // last possible module 00644 s << indent << import.str() << "\n" << flush; 00645 pos = std::string::npos; 00646 } else { 00647 // we have a fallback for this 00648 s << indent << "try:\n" 00649 << indent << py_tab << import.str() << "\n" 00650 << indent << "except ImportError:\n" 00651 << flush; 00652 pos = nxtpos+1; 00653 } 00654 // increase indentation level for next iteration 00655 indent += py_tab; 00656 } 00657 } 00658 00659 //----------------------------------------------------------------------------- 00660 void configGenerator::genHeader( std::ostream& py, 00661 std::ostream& db ) 00662 //----------------------------------------------------------------------------- 00663 { 00664 // python file part 00665 time_t rawtime; 00666 time( &rawtime ); 00667 py << "#" << ctime(&rawtime) //<< "\n" 00668 << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n"; 00669 if ( m_importGaudiHandles ) { 00670 py << "from GaudiKernel.GaudiHandles import *\n"; 00671 } 00672 00673 genImport(py,boost::format("from %1%.Configurable import *")); 00674 00675 // db file part 00676 db << "## -*- python -*- \n" 00677 << "# db file automatically generated by genconf on: " 00678 << ctime(&rawtime); // << "\n"; 00679 db << "## insulates outside world against anything bad that could happen\n" 00680 << "## also prevents global scope pollution\n" 00681 << "def _fillCfgDb():\n"; 00682 genImport(db,boost::format("from %1%.ConfigurableDb import CfgDb"),py_tab); 00683 00684 db << "\n" 00685 << py_tab << "# get a handle on the repository of Configurables\n" 00686 << py_tab << "cfgDb = CfgDb()\n" 00687 << "\n" 00688 << py_tab << "# populate the repository with informations on Configurables \n" 00689 << "\n" 00690 << flush; 00691 } 00692 //----------------------------------------------------------------------------- 00693 void configGenerator::genTrailer( std::ostream& /*py*/, 00694 std::ostream& db ) 00695 //----------------------------------------------------------------------------- 00696 { 00697 // db file part 00698 db << py_tab << "return #_fillCfgDb\n" 00699 << "# fill cfgDb at module import...\n" 00700 << "try:\n" 00701 << py_tab << "_fillCfgDb()\n" 00702 << py_tab << "#house cleaning...\n" 00703 << py_tab << "del _fillCfgDb\n" 00704 << "except Exception,err:\n" 00705 << py_tab << "print \"Py:ConfigurableDb ERROR Problem with [%s] content!" 00706 << "\" % __name__\n" 00707 << py_tab << "print \"Py:ConfigurableDb ERROR\",err\n" 00708 << py_tab << "print \"Py:ConfigurableDb ERROR ==> culprit is package [" 00709 << m_pkgName << "] !\"\n" 00710 << std::flush; 00711 } 00712 00713 //----------------------------------------------------------------------------- 00714 void configGenerator::genComponent( const std::string& libName, 00715 const std::string& componentName, 00716 const std::string& componentType, 00717 const vector<Property*>& properties ) 00718 //----------------------------------------------------------------------------- 00719 { 00720 string cname = componentName; 00721 pythonizeName(cname); 00722 00723 typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t; 00724 PropertyDoc_t propDoc; 00725 00726 m_pyBuf << "\n"; 00727 m_pyBuf << "class " << cname 00728 << "( " << m_configurable[componentType] << " ) :" 00729 << "\n"; 00730 m_pyBuf << " __slots__ = { \n"; 00731 for ( vector<Property*>::const_iterator it = properties.begin() ; 00732 it != properties.end(); ++it ) { 00733 const string pname = (*it)->name(); 00734 string pvalue, ptype; 00735 pythonizeValue( (*it), pvalue, ptype ); 00736 m_pyBuf << " '" << pname << "' : " << pvalue <<", # " << ptype << "\n"; 00737 00738 if ( (*it)->documentation() != "none" ) { 00739 propDoc[pname] = (*it)->documentation(); 00740 } 00741 00742 } 00743 m_pyBuf << " }\n"; 00744 m_pyBuf << " _propertyDocDct = { \n"; 00745 for ( PropertyDoc_t::const_iterator iProp = propDoc.begin(); 00746 iProp != propDoc.end(); 00747 ++iProp ) { 00748 m_pyBuf << std::setw(5) 00749 << "'" << iProp->first << "' : " 00750 << "\"\"\" " << iProp->second << " \"\"\",\n"; 00751 } 00752 m_pyBuf << " }\n"; 00753 00754 m_pyBuf 00755 << " def __init__(self, name = " << m_configurable["DefaultName"] 00756 << ", **kwargs):\n" 00757 << " super(" << cname << ", self).__init__(name)\n" 00758 << " for n,v in kwargs.items():\n" 00759 << " setattr(self, n, v)\n" 00760 << " def getDlls( self ):\n" 00761 << " return '" << libName << "'\n" 00762 << " def getType( self ):\n" 00763 << " return '" << componentName << "'\n" 00764 << " pass # class " << cname << "\n" 00765 << flush; 00766 00767 // name of the auto-generated module 00768 const string pyName = ( fs::path(m_outputDirName) / 00769 fs::path(libName+"Conf.py") ).string(); 00770 const string modName = fs::basename( fs::path( pyName ).leaf() ); 00771 00772 // now the db part 00773 m_dbBuf 00774 << py_tab << "cfgDb.add( configurable = '" << cname << "',\n" 00775 << py_tab << " package = '" << m_pkgName << "',\n" 00776 << py_tab << " module = '" << m_pkgName << "." << modName << "',\n" 00777 << py_tab << " lib = '" << libName << "' )\n" 00778 << flush; 00779 00780 } 00781 //----------------------------------------------------------------------------- 00782 void configGenerator::pythonizeName( string& name ) 00783 //----------------------------------------------------------------------------- 00784 { 00785 static string in("<>&*,: ()."); 00786 static string out("__rp__s___"); 00787 for ( string::iterator i = name.begin(); i != name.end(); ++i ) { 00788 if ( in.find(*i) != string::npos ) *i = out[in.find(*i)]; 00789 } 00790 } 00791 00792 //----------------------------------------------------------------------------- 00793 void configGenerator::pythonizeValue( const Property* p, 00794 string& pvalue, string& ptype ) 00795 //----------------------------------------------------------------------------- 00796 { 00797 const std::string cvalue = p->toString(); 00798 const type_info& ti = *p->type_info(); 00799 if ( ti == typeid(bool) ) { 00800 pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" ) 00801 ? "False" 00802 : "True"; 00803 ptype = "bool"; 00804 } 00805 else if ( ti == typeid(char) || ti == typeid(signed char) 00806 || ti == typeid(unsigned char) || 00807 ti == typeid(short) || ti == typeid(unsigned short) || 00808 ti == typeid(int) || ti == typeid(unsigned int) || 00809 ti == typeid(long) || ti == typeid(unsigned long) ) { 00810 pvalue = cvalue; 00811 ptype = "int"; 00812 } 00813 else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) { 00814 pvalue = cvalue + "L"; 00815 ptype = "long"; 00816 } 00817 else if ( ti == typeid(float) || ti == typeid(double) ) { 00818 // forces python to handle this as a float: put a dot in there... 00819 pvalue = boost::to_lower_copy(cvalue); 00820 if ( pvalue == "nan" ) { 00821 pvalue = "float('nan')"; 00822 std::cout << "WARNING: default value for [" 00823 << p->name() << "] is NaN !!" 00824 << std::endl; 00825 } else if ( std::string::npos == pvalue.find(".") && 00826 std::string::npos == pvalue.find("e") ) { 00827 pvalue = cvalue + ".0"; 00828 } 00829 ptype = "float"; 00830 } 00831 else if ( ti == typeid(string) ) { 00832 00833 pvalue = "'"+cvalue+"'"; 00834 ptype = "str"; 00835 } 00836 else if ( ti == typeid(GaudiHandleBase) ) { 00837 m_importGaudiHandles = true; 00838 const GaudiHandleProperty& hdl 00839 = dynamic_cast<const GaudiHandleProperty&>(*p); 00840 const GaudiHandleBase& base = hdl.value(); 00841 00842 pvalue = base.pythonRepr(); 00843 ptype = "GaudiHandle"; 00844 } 00845 else if ( ti == typeid(GaudiHandleArrayBase) ) { 00846 m_importGaudiHandles = true; 00847 const GaudiHandleArrayProperty& hdl 00848 = dynamic_cast<const GaudiHandleArrayProperty&>(*p); 00849 const GaudiHandleArrayBase& base = hdl.value(); 00850 00851 pvalue = base.pythonRepr(); 00852 ptype = "GaudiHandleArray"; 00853 } 00854 else { 00855 pvalue = cvalue; 00856 ptype = "list"; 00857 } 00858 } 00859 00860 //----------------------------------------------------------------------------- 00861 int createAppMgr() 00862 //----------------------------------------------------------------------------- 00863 { 00864 IInterface* iface = Gaudi::createApplicationMgr(); 00865 SmartIF<IProperty> propMgr ( IID_IProperty, iface ); 00866 SmartIF<IAppMgrUI> appUI ( IID_IAppMgrUI, iface ); 00867 00868 if ( propMgr.isValid() && appUI.isValid() ) { 00869 propMgr->setProperty( "JobOptionsType", "NONE" ); // No joboptions 00870 propMgr->setProperty( "AppName", ""); // No initial printout message 00871 propMgr->setProperty( "OutputLevel", "7"); // No other printout messages 00872 appUI->configure(); 00873 return EXIT_SUCCESS; 00874 } 00875 else { 00876 return EXIT_FAILURE; 00877 } 00878 }