Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011
Public Member Functions | Private Member Functions | Private Attributes

configGenerator Class Reference

Collaboration diagram for configGenerator:
Collaboration graph
[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 753 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 443 of file genconf.cpp.

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

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

  const std::string gaudiSvc = "GaudiSvc";
  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 699 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 663 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 731 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 834 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 845 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

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.

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.

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.

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.

buffer of auto-generated configurables

Definition at line 101 of file genconf.cpp.


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:25:16 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004