Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

genconf.cpp

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

Generated at Thu Jun 28 2012 23:27:25 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004