| # Gaudi Framework, version v23r0 |

Home |  | Generated: Mon Jan 30 2012

Public Member Functions | Private Member Functions | Private Attributes

# configGenerator Class Reference

Collaboration diagram for configGenerator:
[legend]

List of all members.

## Public Member Functions
| configGenerator (const string &pkgName, const string &outputDirName)
int | genConfig (const Strings_t &modules)
| main entry point of this class: iterate over all the modules (ie: library names) for each module extract component informations eventually generate the header/body/trailer python file and "Db" file
void | setConfigurableModule (const std::string &moduleName)
| customize the Module name where configurable base classes are defined
void | setConfigurableDefaultName (const std::string &defaultName)
| customize the default name for configurable instances
void | setConfigurableAlgorithm (const std::string &cfgAlgorithm)
| customize the configurable base class for Algorithm component
void | setConfigurableAlgTool (const std::string &cfgAlgTool)
| customize the configurable base class for AlgTool component
void | setConfigurableAuditor (const std::string &cfgAuditor)
| customize the configurable base class for AlgTool component
void | setConfigurableService (const std::string &cfgService)
| customize the configurable base class for Service component
## Private Member Functions
int | genComponent (const std::string &libName, const std::string &componentName, const std::string &componentType, const vector< Property * > &properties)
void | genImport (std::ostream &s, const boost::format &frmt, std::string indent)
void | genHeader (std::ostream &pyOut, std::ostream &dbOut)
void | genBody (std::ostream &pyOut, std::ostream &dbOut)
void | genTrailer (std::ostream &pyOut, std::ostream &dbOut)
void | pythonizeValue (const Property *prop, string &pvalue, string &ptype)
| handle the "marshalling" of Properties
void | pythonizeName (string &name)
| Translates a valid C++ typename into a valid python one.
## Private Attributes
string | m_pkgName
| name of the package we are processing
string | m_outputDirName
| absolute path to the directory where genconf will store auto-generated files (Configurables and ConfigurableDb)
stringstream | m_pyBuf
| buffer of auto-generated configurables
bool | m_importGaudiHandles
| switch to decide if the generated configurables need to import GaudiHandles (ie: if one of the components has a XyzHandle<T>)
stringstream | m_dbBuf
| buffer of generated configurables informations for the "Db" file The "Db" file is holding informations about the generated configurables This file is later one used by the PropertyProxy.py to locate Configurables and know their default values, host module,...
GaudiUtils::HashMap < std::string, std::string > | m_configurable
| Configurable customization.

## Detailed Description

Definition at line 91 of file genconf.cpp.

## Constructor & Destructor Documentation

configGenerator::configGenerator | ( | const string & | pkgName,
|  | const string & | outputDirName
| ) |  | `[inline]`

Definition at line 121 of file genconf.cpp.

                                                     :
        m_pkgName           ( pkgName ),
        m_outputDirName     ( outputDirName ),
        m_pyBuf             ( ),
        m_importGaudiHandles( false ),
        m_dbBuf             ( ),
        m_configurable      ( )
      {}

## Member Function Documentation

void configGenerator::genBody | ( | std::ostream & | pyOut,
|  | std::ostream & | dbOut
| ) |  | `[inline, private]`

Definition at line 181 of file genconf.cpp.

                                        {
        pyOut << m_pyBuf.str() << flush;
        dbOut << m_dbBuf.str() << flush;
      }

int configGenerator::genComponent | ( | const std::string & | libName,
|  | const std::string & | componentName,
|  | const std::string & | componentType,
|  | const vector< Property * > & | properties
| ) |  | `[private]`

Definition at line 749 of file genconf.cpp.

    {
      string cname = componentName;
      pythonizeName(cname);

      typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t;
      PropertyDoc_t propDoc;

      m_pyBuf << "\n";
      m_pyBuf << "class " << cname
              << "( " << m_configurable[componentType] << " ) :"
              << "\n";
      m_pyBuf << "  __slots__ = { \n";
      for ( vector<Property*>::const_iterator it = properties.begin() ;
            it != properties.end(); ++it ) {

        const string pname  = (*it)->name();
        // Validate property name (it must be a valid Python identifier)
        if (!boost::regex_match(pname, pythonIdentifier)) {
          std::cout << "ERROR: invalid property name \"" << pname
                    << "\" in component " << cname
                    << " (invalid Python identifier)" << std::endl;
          // try to make the buffer at least more or less valid python code.
          m_pyBuf << " #ERROR-invalid identifier '" << pname << "'\n"
                  << "  }\n";
          return 1;
        }

        string pvalue, ptype;
        pythonizeValue( (*it), pvalue, ptype );
        m_pyBuf << "    '" << pname << "' : " << pvalue <<", # " << ptype << "\n";

        if ( (*it)->documentation() != "none" ) {
          propDoc[pname] = (*it)->documentation();
        }

      }
      m_pyBuf << "  }\n";
      m_pyBuf << "  _propertyDocDct = { \n";
      for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
            iProp != propDoc.end();
            ++iProp ) {
        m_pyBuf << std::setw(5)
                << "'"       << iProp->first  << "' : "
                << "\"\"\" "  << iProp->second << " \"\"\",\n";
      }
      m_pyBuf << "  }\n";

      m_pyBuf
        << "  def __init__(self, name = " << m_configurable["DefaultName"]
                                          << ", **kwargs):\n"
        << "      super(" << cname << ", self).__init__(name)\n"
        << "      for n,v in kwargs.items():\n"
        << "         setattr(self, n, v)\n"
        << "  def getDlls( self ):\n"
        << "      return '" << libName << "'\n"
        << "  def getType( self ):\n"
        << "      return '" << componentName  << "'\n"
        << "  pass # class " << cname << "\n"
        << flush;

      // name of the auto-generated module
      const string pyName = ( fs::path(m_outputDirName) /
                              fs::path(libName+"Conf.py") ).string();
      const string modName = fs::basename( fs::path( pyName ).leaf() );

      // now the db part
      m_dbBuf
        << py_tab << "cfgDb.add( configurable = '" << cname << "',\n"
        << py_tab << "           package = '" << m_pkgName << "',\n"
        << py_tab << "           module  = '" << m_pkgName << "." << modName << "',\n"
        << py_tab << "           lib     = '" << libName << "' )\n"
        << flush;

      return 0;
    }

int configGenerator::genConfig | ( | const Strings_t & | modules ) |

main entry point of this class:

- iterate over all the modules (ie: library names)
- for each module extract component informations
- eventually generate the header/body/trailer python file and "Db" file

not enough information... skip it

no Properties, so don't bother create Configurables...

: no Configurable for this component. yet... continue;

write-out files for this library

Definition at line 439 of file genconf.cpp.

    {
      //--- Disable checking StatusCode -------------------------------------------
      StatusCode::disableChecking();

      const Strings_t::const_iterator endLib = libs.end();

      const std::string gaudiSvc = "GaudiCoreSvc";
      const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );

      //--- Instantiate ApplicationMgr --------------------------------------------
      if ( !isGaudiSvc && createAppMgr() ) {
        cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl;
        return EXIT_FAILURE;
      }

      //--- Iterate over component factories --------------------------------------
      Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS);
      if ( !factories ) {
        cout << "ERROR: No PluginSvc factory namespace could be found" << endl;
        return EXIT_FAILURE;
      }

      ISvcLocator* svcLoc = Gaudi::svcLocator();
      IInterface*  dummySvc = new Service( "DummySvc", svcLoc );
      dummySvc->addRef();

      bool allGood = true;

      // iterate over all the requested libraries
      for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {

        std::cout << ":::: processing library: " << *iLib << "..." << std::endl;

        // reset state
        m_importGaudiHandles = false;
        m_pyBuf.str("");
        m_dbBuf.str("");

        // Scan the pluginSvc namespace and store the "background" of already
        // alive components, so we can extract our signal later on
        set<string> bkgNames;
        if ( !isGaudiSvc ) {
          for ( Member_Iterator it = factories.FunctionMember_Begin();
                it != factories.FunctionMember_End(); ++it ) {
            string ident = getId(*it);
            if ( PluginService::Debug() > 0 ) {
              cout << "::: " << ident << endl;
            }
            bkgNames.insert( ident );
          }
        }
        const set<string>::const_iterator bkgNamesEnd = bkgNames.end();

        //--- Load component library ----------------------------------------------
        System::ImageHandle handle;
        unsigned long err = System::loadDynamicLib( *iLib, &handle );
        if ( err != 1 ) {
          cout << "ERROR: " << System::getLastErrorString() << endl;
          allGood = false;
          continue;
        }

        for ( Member_Iterator it = factories.FunctionMember_Begin();
              it != factories.FunctionMember_End();
              ++it ) {
          const string ident = getId(*it);
          if ( bkgNames.find(ident) != bkgNamesEnd ) {
            if ( PluginService::Debug() > 0 ) {
              cout << "\t==> skipping [" << ident << "]..." << endl;
            }
            continue;
          }

          // Atlas contributed code (patch #1247)
          // Skip the generation of configurables if the component does not come
          // from the same library we are processing (i.e. we found a symbol that
          // is coming from a library loaded by the linker).
          // Windows implementation is empty.
          if ( !DsoUtils::inDso( *it, DsoUtils::libNativeName(*iLib) ) ) {
            cout << "WARNING: library [" << *iLib << "] requested factory "
            << "from another library ["
            << DsoUtils::dsoName(*it) << "]"
            << " ==> [" << ident << "] !!"
            << endl;
            continue;
          }

          const string rtype = it->TypeOf().ReturnType().Name();
          string type;
          bool known = true;
          if      ( ident == "ApplicationMgr" ) type = "ApplicationMgr";
          else if ( rtype == "IInterface*" )    type = "IInterface";
          else if ( rtype == "IAlgorithm*" )    type = "Algorithm";
          else if ( rtype == "IService*" )      type = "Service";
          else if ( rtype == "IAlgTool*" )      type = "AlgTool";
          else if ( rtype == "IAuditor*" )      type = "Auditor";
          else if ( rtype == "IConverter*" )    type = "Converter";
          else if ( rtype == "DataObject*" )    type = "DataObject";
          else                                  type = "Unknown", known = false;
          string name = ident;
          // handle possible problems with templated components
          boost::trim(name);

          cout << " - component: " << name << endl;

          if ( type == "IInterface" ) {
            continue;
          }

          if ( type == "Converter" || type == "DataObject" ) {
            continue;
          }

          //if ( type == "ApplicationMgr" ) {
          //}

          if ( !known ) {
            cout << "WARNING: Unknown (return) type [" << rtype << "] !!\n"
                 << "WARNING: component [" << ident << "] is skipped !"
                 << endl;
            allGood = false;
            continue;
          }

          string cname = "DefaultName";
          vector<void*>  args;
          args.reserve( 3 );
          if ( type == "AlgTool" ) {
            args.resize( 3 );
            args[0] = &cname;
            args[1] = &type;
            args[2] = dummySvc;
          }
          else {
            args.resize( 2 );
            args[0] = &cname;
            args[1] = svcLoc;
          }
          IProperty* prop = 0;
          try {
            if ( type == "Algorithm" ) {
              prop = makeInstance<IAlgorithm>(*it,args);
            }
            else if ( type == "Service") {
              prop = makeInstance<IService>(*it,args);
            }
            else if ( type == "AlgTool") {
              prop = makeInstance<IAlgTool>(*it,args);
            }
            else if ( type == "Auditor") {
              prop = makeInstance<IAuditor>(*it,args);
            }
            else if ( type == "ApplicationMgr") {
              //svcLoc->queryInterface(IProperty::interfaceID(), pp_cast<void>(&prop));
              svcLoc->queryInterface(IProperty::interfaceID(), (void**)(&prop));
            }
            else {
              prop = makeInstance<IInterface>(*it,args);
            }
          }
          catch ( exception& e ) {
            cout << "ERROR: Error instantiating " << name
                 << " from " << *iLib << endl;
            cout << "ERROR: Got exception: " << e.what() << endl;
            allGood = false;
            continue;
          }
          catch ( ... ) {
            cout << "ERROR: Error instantiating " << name
                 << " from " << *iLib << endl;
            allGood = false;
            continue;
          }
          if( prop ) {
            if (genComponent( *iLib, name, type, prop->getProperties() )) {
              allGood = false;
            }
            prop->release();
          } else {
            cout << "ERROR: could not cast IInterface* object to an IProperty* !\n"
                 << "ERROR: return type from PluginSvc is [" << rtype << "]...\n"
                 << "ERROR: NO Configurable will be generated for ["
                 << name << "] !"
                 << endl;
            allGood = false;
          }
        } //> end loop over factories

        const std::string pyName = ( fs::path(m_outputDirName) /
                      fs::path(*iLib+"Conf.py") ).string();
        const std::string dbName = ( fs::path(m_outputDirName) /
                      fs::path(*iLib+"_confDb.py") ).string();

        std::fstream py( pyName.c_str(),
                  std::ios_base::out|std::ios_base::trunc );
        std::fstream db( dbName.c_str(),
                  std::ios_base::out|std::ios_base::trunc );

        genHeader ( py, db );
        genBody   ( py, db );
        genTrailer( py, db );

      } //> end loop over libraries

      dummySvc->release();
      dummySvc = 0;

      return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
    }

void configGenerator::genHeader | ( | std::ostream & | pyOut,
|  | std::ostream & | dbOut
| ) |  | `[private]`

Definition at line 695 of file genconf.cpp.

    {
      // python file part
      std::string now = Gaudi::Time::current().format(true);
      py << "#" << now //<< "\n"
         << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
      if ( m_importGaudiHandles ) {
        py << "from GaudiKernel.GaudiHandles import *\n";
      }

      genImport(py,boost::format("from %1%.Configurable import *"));

      // db file part
      db << "##  -*- python -*-  \n"
         << "# db file automatically generated by genconf on: "
         << now; // << "\n";
      db << "## insulates outside world against anything bad that could happen\n"
         << "## also prevents global scope pollution\n"
         << "def _fillCfgDb():\n";
      genImport(db,boost::format("from %1%.ConfigurableDb import CfgDb"),py_tab);

      db << "\n"
         << py_tab << "# get a handle on the repository of Configurables\n"
         << py_tab << "cfgDb = CfgDb()\n"
         << "\n"
         << py_tab << "# populate the repository with informations on Configurables \n"
         << "\n"
         << flush;
    }

void configGenerator::genImport | ( | std::ostream & | s,
|  | const boost::format & | frmt,
|  | std::string | indent = `""`
| ) |  | `[private]`

Definition at line 659 of file genconf.cpp.

                                                           {

      std::string::size_type pos = 0, nxtpos = 0;
      std::string mod;

      while ( std::string::npos != pos ){
        // find end of module name
        nxtpos = m_configurable["Module"].find_first_of(',',pos);

        // Prepare import string
        mod = m_configurable["Module"].substr(pos,nxtpos-pos);
        std::ostringstream import;
        import << boost::format(frmt) % mod;

        // append a normal import or a try/except enclosed one depending
        // on availability of a fall-back module (next in the list)
        if ( std::string::npos == nxtpos ) {
          // last possible module
          s << indent << import.str() << "\n" << flush;
          pos = std::string::npos;
        } else {
          // we have a fallback for this
          s << indent << "try:\n"
            << indent << py_tab << import.str() << "\n"
            << indent << "except ImportError:\n"
            << flush;
          pos = nxtpos+1;
        }
        // increase indentation level for next iteration
        indent += py_tab;
      }
    }

void configGenerator::genTrailer | ( | std::ostream & | pyOut,
|  | std::ostream & | dbOut
| ) |  | `[private]`

Definition at line 727 of file genconf.cpp.

    {
      // db file part
      db << py_tab << "return #_fillCfgDb\n"
         << "# fill cfgDb at module import...\n"
         << "try:\n"
         << py_tab << "_fillCfgDb()\n"
         << py_tab << "#house cleaning...\n"
         << py_tab << "del _fillCfgDb\n"
         << "except Exception,err:\n"
         << py_tab << "print \"Py:ConfigurableDb   ERROR Problem with [%s] content!"
                   << "\" % __name__\n"
         << py_tab << "print \"Py:ConfigurableDb   ERROR\",err\n"
         << py_tab << "print \"Py:ConfigurableDb   ERROR   ==> culprit is package ["
                   << m_pkgName << "] !\"\n"
         << std::flush;
    }

void configGenerator::pythonizeName | ( | string & | name ) | `[private]`

Translates a valid C++ typename into a valid python one.

Definition at line 830 of file genconf.cpp.

    {
      static string  in("<>&*,: ().");
      static string out("__rp__s___");
      for ( string::iterator i = name.begin(); i != name.end(); ++i ) {
        if ( in.find(*i) != string::npos ) *i = out[in.find(*i)];
      }
    }

void configGenerator::pythonizeValue | ( | const Property * | prop,
|  | string & | pvalue,
|  | string & | ptype
| ) |  | `[private]`

handle the "marshalling" of Properties

Definition at line 841 of file genconf.cpp.

    {
      const std::string cvalue = p->toString();
      const type_info& ti = *p->type_info();
      if ( ti == typeid(bool) ) {
        pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" )
               ? "False"
               : "True";
        ptype  = "bool";
      }
      else if ( ti == typeid(char)  || ti == typeid(signed char)
                || ti == typeid(unsigned char)  ||
                ti == typeid(short) || ti == typeid(unsigned short) ||
                ti == typeid(int)   || ti == typeid(unsigned int)   ||
                ti == typeid(long)  || ti == typeid(unsigned long) ) {
        pvalue = cvalue;
        ptype  = "int";
      }
      else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) {
        pvalue = cvalue + "L";
        ptype  = "long";
      }
      else if ( ti == typeid(float) || ti == typeid(double) ) {
        // forces python to handle this as a float: put a dot in there...
        pvalue = boost::to_lower_copy(cvalue);
        if ( pvalue == "nan" ) {
          pvalue = "float('nan')";
          std::cout << "WARNING: default value for ["
                    << p->name() << "] is NaN !!"
                    << std::endl;
        } else if ( std::string::npos == pvalue.find(".") &&
                    std::string::npos == pvalue.find("e")  ) {
          pvalue = cvalue + ".0";
        }
        ptype  = "float";
      }
      else if ( ti == typeid(string) ) {

        pvalue = "'"+cvalue+"'";
        ptype  = "str";
      }
      else if ( ti == typeid(GaudiHandleBase) ) {
        m_importGaudiHandles = true;
        const GaudiHandleProperty& hdl
          = dynamic_cast<const GaudiHandleProperty&>(*p);
        const GaudiHandleBase&     base = hdl.value();

        pvalue = base.pythonRepr();
        ptype  = "GaudiHandle";
      }
      else if ( ti == typeid(GaudiHandleArrayBase) ) {
        m_importGaudiHandles = true;
        const GaudiHandleArrayProperty& hdl
          = dynamic_cast<const GaudiHandleArrayProperty&>(*p);
        const GaudiHandleArrayBase&     base = hdl.value();

        pvalue = base.pythonRepr();
        ptype  = "GaudiHandleArray";
      }
      else {
        std::ostringstream v_str;
        v_str.setf(std::ios::fixed); // to correctly display floats
        p->toStream(v_str);
        pvalue = v_str.str();
        ptype  = "list";
      }
    }

void configGenerator::setConfigurableAlgorithm | ( | const std::string & | cfgAlgorithm ) | `[inline]`

customize the configurable base class for Algorithm component

Definition at line 150 of file genconf.cpp.

      {
        m_configurable[ "Algorithm" ] = cfgAlgorithm;
      }

void configGenerator::setConfigurableAlgTool | ( | const std::string & | cfgAlgTool ) | `[inline]`

customize the configurable base class for AlgTool component

Definition at line 156 of file genconf.cpp.

      {
        m_configurable[ "AlgTool" ] = cfgAlgTool;
      }

void configGenerator::setConfigurableAuditor | ( | const std::string & | cfgAuditor ) | `[inline]`

customize the configurable base class for AlgTool component

Definition at line 162 of file genconf.cpp.

      {
        m_configurable[ "Auditor" ] = cfgAuditor;
      }

void configGenerator::setConfigurableDefaultName | ( | const std::string & | defaultName ) | `[inline]`

customize the default name for configurable instances

Definition at line 144 of file genconf.cpp.

      {
        m_configurable[ "DefaultName" ] = defaultName;
      }

void configGenerator::setConfigurableModule | ( | const std::string & | moduleName ) | `[inline]`

customize the Module name where configurable base classes are defined

Definition at line 138 of file genconf.cpp.

      {
        m_configurable[ "Module" ] = moduleName;
      }

void configGenerator::setConfigurableService | ( | const std::string & | cfgService ) | `[inline]`

customize the configurable base class for Service component

Definition at line 168 of file genconf.cpp.

      {
        m_configurable[ "Service" ] = cfgService;
        m_configurable[ "ApplicationMgr" ] = cfgService;
      }

## Member Data Documentation

GaudiUtils::HashMap<std::string, std::string> configGenerator::m_configurable`[private]`

Configurable customization.

Contains customization for:

- Name of the module where configurable base classes are defined
- Name of the configurable base class for the Algorithm component
- Name of the configurable base class for the AlgTool component
- Name of the configurable base class for the Service component

Definition at line 118 of file genconf.cpp.

stringstream configGenerator::m_dbBuf`[private]`

buffer of generated configurables informations for the "Db" file The "Db" file is holding informations about the generated configurables This file is later one used by the PropertyProxy.py to locate Configurables and know their default values, host module,...

Definition at line 111 of file genconf.cpp.

bool configGenerator::m_importGaudiHandles`[private]`

switch to decide if the generated configurables need to import GaudiHandles (ie: if one of the components has a XyzHandle<T>)

Definition at line 105 of file genconf.cpp.

string configGenerator::m_outputDirName`[private]`

absolute path to the directory where genconf will store auto-generated files (Configurables and ConfigurableDb)

Definition at line 98 of file genconf.cpp.

string configGenerator::m_pkgName`[private]`

name of the package we are processing

Definition at line 94 of file genconf.cpp.

stringstream configGenerator::m_pyBuf`[private]`

buffer of auto-generated configurables

Definition at line 101 of file genconf.cpp.

The documentation for this class was generated from the following file:

- /afs/cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v23r0/GaudiKernel/src/Util/genconf.cpp

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines