4 #pragma warning ( disable : 4273 )
14 #pragma warning(disable:279)
16 #if !defined(_WIN32) && !defined(_MSC_VER)
21 #include "boost/program_options.hpp"
23 #if defined(__ICC) && !defined(_WIN32) && (_MSC_VER == 0)
28 #include "boost/filesystem/operations.hpp"
29 #include "boost/filesystem/exception.hpp"
30 #include "boost/filesystem/convenience.hpp"
31 #include "boost/algorithm/string/split.hpp"
32 #include "boost/algorithm/string/classification.hpp"
33 #include "boost/algorithm/string/trim.hpp"
34 #include "boost/algorithm/string/case_conv.hpp"
35 #include "boost/algorithm/string/replace.hpp"
36 #include "boost/format.hpp"
37 #include "boost/regex.hpp"
72 namespace po = boost::program_options;
73 namespace fs = boost::filesystem;
80 typedef std::vector<std::string>
Strings_t;
84 const std::string py_tab =
" ";
88 const boost::regex pythonIdentifier(
"^[a-zA-Z_][a-zA-Z0-9_]*$");
122 const string& outputDirName ) :
123 m_pkgName ( pkgName ),
124 m_outputDirName ( outputDirName ),
126 m_importGaudiHandles( false ),
135 int genConfig(
const Strings_t& modules,
const string& userModule );
144 void setConfigurableDefaultName(
const std::string& defaultName )
146 m_configurable[
"DefaultName" ] = defaultName;
150 void setConfigurableAlgorithm(
const std::string& cfgAlgorithm )
152 m_configurable[
"Algorithm" ] = cfgAlgorithm;
156 void setConfigurableAlgTool(
const std::string& cfgAlgTool )
158 m_configurable[
"AlgTool" ] = cfgAlgTool;
162 void setConfigurableAuditor(
const std::string& cfgAuditor )
164 m_configurable[
"Auditor" ] = cfgAuditor;
168 void setConfigurableService(
const std::string& cfgService )
170 m_configurable[
"Service" ] = cfgService;
171 m_configurable[
"ApplicationMgr" ] = cfgService;
175 int genComponent(
const std::string& libName,
176 const std::string& componentName,
177 const std::string& componentType,
178 const vector<Property*>& properties );
180 void genHeader( std::ostream& pyOut, std::ostream& dbOut );
181 void genBody( std::ostream& pyOut,
182 std::ostream& dbOut ) {
183 pyOut << m_pyBuf.str() << flush;
184 dbOut << m_dbBuf.str() << flush;
186 void genTrailer( std::ostream& pyOut,
187 std::ostream& dbOut );
190 void pythonizeValue(
const Property* prop,
195 void pythonizeName(
string& name );
208 std::string userModule;
211 po::options_description
generic(
"Generic options");
212 generic.add_options()
214 "produce this help message")
217 "name of the package for which we create the configurables file")
218 (
"input-libraries,i",
220 "libraries to extract the component configurables from")
223 "path to the cfg file holding the description of the Configurable base "
224 "classes, the python module holding the Configurable definitions, etc...")
226 po::value<string>()->default_value(
"../genConf"),
227 "output directory for genconf files.")
229 po::value<int>()->default_value(0),
232 po::value< Strings_t >()->composing(),
233 "preloading library")
236 "user-defined module to be imported by the genConf-generated one")
238 "do not generate the (empty) __init__.py")
243 po::options_description
config(
"Configuration");
245 (
"configurable-module",
246 po::value<string>()->default_value(
"AthenaCommon"),
247 "Name of the module holding the configurable classes")
248 (
"configurable-default-name",
249 po::value<string>()->default_value(
"Configurable.DefaultName"),
250 "Default name for the configurable instance")
251 (
"configurable-algorithm",
252 po::value<string>()->default_value(
"ConfigurableAlgorithm"),
253 "Name of the configurable base class for Algorithm components")
254 (
"configurable-algtool",
255 po::value<string>()->default_value(
"ConfigurableAlgTool"),
256 "Name of the configurable base class for AlgTool components")
257 (
"configurable-auditor",
258 po::value<string>()->default_value(
"ConfigurableAuditor"),
259 "Name of the configurable base class for Auditor components")
260 (
"configurable-service",
261 po::value<string>()->default_value(
"ConfigurableService"),
262 "Name of the configurable base class for Service components")
265 po::options_description cmdline_options;
266 cmdline_options.add(
generic).add(config);
268 po::options_description config_file_options;
269 config_file_options.add(config);
271 po::options_description visible(
"Allowed options");
272 visible.add(
generic).add(config);
274 po::variables_map vm;
277 po::store( po::command_line_parser(argc, argv).
278 options(cmdline_options).run(),
284 if( vm.count(
"input-cfg") ) {
285 string cfgFileName = vm[
"input-cfg"].as<
string>();
286 cfgFileName = fs::system_complete(
fs::path( cfgFileName ) ).string();
287 std::ifstream ifs( cfgFileName.c_str() );
288 po::store( parse_config_file( ifs, config_file_options ), vm );
293 catch ( po::error& err ) {
294 cout <<
"ERROR: error detected while parsing command options: "<< err.what() << endl;
299 if( vm.count(
"help")) {
300 cout << visible << endl;
304 if( vm.count(
"package-name") ) {
305 pkgName = vm[
"package-name"].as<
string>();
308 cout <<
"ERROR: 'package-name' required" << endl;
309 cout << visible << endl;
313 if( vm.count(
"user-module") ) {
314 userModule = vm[
"user-module"].as<
string>();
315 cout <<
"INFO: will import user module " << userModule << endl;
318 if( vm.count(
"input-libraries") ) {
324 string tmp = vm[
"input-libraries"].as<
string>();
326 boost::split( inputLibs, tmp,
327 boost::is_any_of(
" "),
328 boost::token_compress_on );
332 libs.reserve( inputLibs.size() );
333 for ( Strings_t::const_iterator iLib = inputLibs.begin();
334 iLib != inputLibs.end();
336 std::string lib =
fs::path(*iLib).stem().string();
337 if ( 0 == lib.find(
"lib") ) {
342 std::find( libs.begin(), libs.end(), lib ) == libs.end() ) {
343 libs.push_back( lib );
346 if ( libs.empty() ) {
347 cout <<
"ERROR: input component library(ies) required !\n"
348 <<
"ERROR: 'input-libraries' argument was ["
349 << vm[
"input-libraries"].as<
string>()
356 cout <<
"ERROR: input component library(ies) required" << endl;
357 cout << visible << endl;
361 if( vm.count(
"output-dir") ) {
362 out = fs::system_complete(
fs::path( vm[
"output-dir"].as<string>() ) );
365 if ( vm.count(
"debug-level") ) {
369 if ( vm.count(
"load-library") ) {
371 for (Strings_t::const_iterator lLib=lLib_list.begin();
372 lLib != lLib_list.end();
378 cout <<
"WARNING: failed to load: "<< *lLib << endl;
384 if ( !fs::exists( out ) ) {
386 fs::create_directory(out);
388 catch ( fs::filesystem_error &err ) {
389 cout <<
"ERROR: error creating directory: "<< err.what() << endl;
394 cout <<
":::::: libraries : [ ";
395 copy( libs.begin(), libs.end(), ostream_iterator<string>(cout,
" ") );
396 cout <<
"] ::::::" << endl;
400 py.setConfigurableDefaultName(vm[
"configurable-default-name"].as<string>());
401 py.setConfigurableAlgorithm (vm[
"configurable-algorithm"].as<string>());
402 py.setConfigurableAlgTool (vm[
"configurable-algtool"].as<string>());
403 py.setConfigurableAuditor (vm[
"configurable-auditor"].as<string>());
404 py.setConfigurableService (vm[
"configurable-service"].as<string>());
406 int sc = EXIT_FAILURE;
408 sc = py.genConfig( libs, userModule );
410 catch ( exception& e ) {
411 cout <<
"ERROR: Could not generate Configurable(s) !\n"
412 <<
"ERROR: Got exception: " << e.what() << endl;
416 if ( EXIT_SUCCESS == sc && ! vm.count(
"no-init")) {
418 fstream initPy( ( out /
fs::path(
"__init__.py" ) ).
string().c_str(),
419 std::ios_base::out|std::ios_base::trunc );
420 initPy <<
"## Hook for " << pkgName <<
" genConf module\n" << flush;
423 cout <<
":::::: libraries : [ ";
424 copy( libs.begin(), libs.end(), ostream_iterator<string>(cout,
" ") );
425 cout <<
"] :::::: [DONE]" << endl;
437 const Strings_t::const_iterator endLib = libs.end();
439 const std::string gaudiSvc =
"GaudiCoreSvc";
440 const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );
444 cout <<
"ERROR: ApplicationMgr can not be created. Check environment" << endl;
449 using Gaudi::PluginService::Details::Registry;
450 Registry&
registry = Registry::instance();
452 std::set<std::string> bkgNames = registry.loadedFactories();
461 for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {
463 std::cout <<
":::: processing library: " << *iLib <<
"..." << std::endl;
466 m_importGaudiHandles =
false;
479 std::set<std::string>
factories = registry.loadedFactories();
481 for ( std::set<std::string>::iterator it = factories.begin();
482 it != factories.end(); ++it ) {
483 const string ident = *it;
484 if ( bkgNames.find(ident) != bkgNames.end() ) {
486 cout <<
"\t==> skipping [" << ident <<
"]..." << endl;
491 const Registry::FactoryInfo info = registry.getInfo(*it);
492 const string rtype = info.rtype;
495 if (info.properties.find(
"ReflexName") != info.properties.end())
503 cout <<
"WARNING: library [" << *iLib <<
"] exposes factory ["
504 << ident <<
"] which is declared in ["
511 if ( ident ==
"ApplicationMgr" ) type =
"ApplicationMgr";
512 else if ( rtype ==
typeid(
IInterface*).name() ) type =
"IInterface";
513 else if ( rtype ==
typeid(
IAlgorithm*).name() ) type =
"Algorithm";
514 else if ( rtype ==
typeid(
IService* ).name() ) type =
"Service";
515 else if ( rtype ==
typeid(
IAlgTool* ).name() ) type =
"AlgTool";
516 else if ( rtype ==
typeid(
IAuditor* ).name() ) type =
"Auditor";
517 else if ( rtype ==
typeid(
IConverter*).name() ) type =
"Converter";
518 else if ( rtype ==
typeid(
DataObject*).name() ) type =
"DataObject";
519 else type =
"Unknown", known =
false;
524 if ( type ==
"IInterface" ) {
530 if ( type ==
"Converter" || type ==
"DataObject" ) {
536 cout <<
"WARNING: Unknown (return) type [" << rtype <<
"] !!\n"
537 <<
"WARNING: component [" << ident <<
"] is skipped !"
543 cout <<
" - component: " << info.className <<
" (";
544 if (info.className != name)
545 cout << name <<
": ";
546 cout << type <<
")" << endl;
548 string cname =
"DefaultName";
551 if ( type ==
"Algorithm" ) {
554 else if ( type ==
"Service") {
557 else if ( type ==
"AlgTool") {
558 prop =
SmartIF<IAlgTool>(AlgTool::Factory::create(ident, cname, type, dummySvc));
562 else if ( type ==
"Auditor") {
565 else if ( type ==
"ApplicationMgr") {
572 catch ( exception& e ) {
573 cout <<
"ERROR: Error instantiating " << name
574 <<
" from " << *iLib << endl;
575 cout <<
"ERROR: Got exception: " << e.what() << endl;
580 cout <<
"ERROR: Error instantiating " << name
581 <<
" from " << *iLib << endl;
586 if (genComponent( *iLib, name, type, prop->getProperties() )) {
591 cout <<
"ERROR: could not cast IInterface* object to an IProperty* !\n"
592 <<
"ERROR: return type from PluginSvc is [" << rtype <<
"]...\n"
593 <<
"ERROR: NO Configurable will be generated for ["
603 const std::string pyName = (
fs::path(m_outputDirName) /
604 fs::path(*iLib+
"Conf.py") ).
string();
605 const std::string dbName = (
fs::path(m_outputDirName) /
606 fs::path(*iLib+
"_confDb.py") ).
string();
608 std::fstream py( pyName.c_str(),
609 std::ios_base::out|std::ios_base::trunc );
610 std::fstream db( dbName.c_str(),
611 std::ios_base::out|std::ios_base::trunc );
613 genHeader ( py, db );
614 if (!userModule.empty())
615 py <<
"from " << userModule <<
" import *" <<endl;
617 genTrailer( py, db );
624 return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
631 std::string::size_type pos = 0, nxtpos = 0;
634 while ( std::string::npos != pos ){
636 nxtpos = m_configurable[
"Module"].find_first_of(
',',pos);
639 mod = m_configurable[
"Module"].substr(pos,nxtpos-pos);
640 std::ostringstream
import;
645 if ( std::string::npos == nxtpos ) {
647 s <<
indent <<
import.str() <<
"\n" << flush;
648 pos = std::string::npos;
652 <<
indent << py_tab <<
import.str() <<
"\n"
653 <<
indent <<
"except ImportError:\n"
668 std::string now = Gaudi::Time::current().
format(
true);
670 <<
"\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
671 if ( m_importGaudiHandles ) {
672 py <<
"from GaudiKernel.GaudiHandles import *\n";
675 genImport(py,
boost::format(
"from %1%.Configurable import *"));
678 db <<
"## -*- python -*- \n"
679 <<
"# db file automatically generated by genconf on: "
681 db <<
"## insulates outside world against anything bad that could happen\n"
682 <<
"## also prevents global scope pollution\n"
683 <<
"def _fillCfgDb():\n";
684 genImport(db,
boost::format(
"from %1%.ConfigurableDb import CfgDb"),py_tab);
687 << py_tab <<
"# get a handle on the repository of Configurables\n"
688 << py_tab <<
"cfgDb = CfgDb()\n"
690 << py_tab <<
"# populate the repository with informations on Configurables \n"
700 db << py_tab <<
"return #_fillCfgDb\n"
701 <<
"# fill cfgDb at module import...\n"
703 << py_tab <<
"_fillCfgDb()\n"
704 << py_tab <<
"#house cleaning...\n"
705 << py_tab <<
"del _fillCfgDb\n"
706 <<
"except Exception,err:\n"
707 << py_tab <<
"print \"Py:ConfigurableDb ERROR Problem with [%s] content!"
709 << py_tab <<
"print \"Py:ConfigurableDb ERROR\",err\n"
710 << py_tab <<
"print \"Py:ConfigurableDb ERROR ==> culprit is package ["
711 << m_pkgName <<
"] !\"\n"
718 const std::string& componentName,
719 const std::string& componentType,
720 const vector<Property*>& properties )
723 string cname = componentName;
724 pythonizeName(cname);
727 PropertyDoc_t propDoc;
730 m_pyBuf <<
"class " << cname
731 <<
"( " << m_configurable[componentType] <<
" ) :"
733 m_pyBuf <<
" __slots__ = { \n";
734 for ( vector<Property*>::const_iterator it = properties.begin() ;
735 it != properties.end(); ++it ) {
737 const string pname = (*it)->name();
739 if (!boost::regex_match(pname, pythonIdentifier)) {
740 std::cout <<
"ERROR: invalid property name \"" << pname
741 <<
"\" in component " << cname
742 <<
" (invalid Python identifier)" << std::endl;
744 m_pyBuf <<
" #ERROR-invalid identifier '" << pname <<
"'\n"
749 string pvalue, ptype;
750 pythonizeValue( (*it), pvalue, ptype );
751 m_pyBuf <<
" '" << pname <<
"' : " << pvalue <<
", # " << ptype <<
"\n";
753 if ( (*it)->documentation() !=
"none" ) {
754 propDoc[
pname] = (*it)->documentation();
759 m_pyBuf <<
" _propertyDocDct = { \n";
760 for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
761 iProp != propDoc.end();
763 m_pyBuf << std::setw(5)
764 <<
"'" << iProp->first <<
"' : "
765 <<
"\"\"\" " << iProp->second <<
" \"\"\",\n";
770 <<
" def __init__(self, name = " << m_configurable[
"DefaultName"]
772 <<
" super(" << cname <<
", self).__init__(name)\n"
773 <<
" for n,v in kwargs.items():\n"
774 <<
" setattr(self, n, v)\n"
775 <<
" def getDlls( self ):\n"
776 <<
" return '" << libName <<
"'\n"
777 <<
" def getType( self ):\n"
778 <<
" return '" << componentName <<
"'\n"
779 <<
" pass # class " << cname <<
"\n"
783 const string pyName = (
fs::path(m_outputDirName) /
784 fs::path(libName+
"Conf.py") ).
string();
789 << py_tab <<
"cfgDb.add( configurable = '" << cname <<
"',\n"
790 << py_tab <<
" package = '" << m_pkgName <<
"',\n"
791 << py_tab <<
" module = '" << m_pkgName <<
"." << modName <<
"',\n"
792 << py_tab <<
" lib = '" << libName <<
"' )\n"
801 static string in(
"<>&*,: ().");
802 static string out(
"__rp__s___");
803 boost::algorithm::replace_all(name,
", ",
",");
804 for ( string::iterator
i = name.begin();
i != name.end(); ++
i ) {
805 if ( in.find(*
i) != string::npos ) *
i = out[in.find(*
i)];
811 string& pvalue,
string& ptype )
814 const std::string cvalue = p->
toString();
816 if ( ti ==
typeid(
bool) ) {
817 pvalue = ( cvalue ==
"0" || cvalue ==
"False" || cvalue ==
"false" )
822 else if ( ti ==
typeid(
char) || ti ==
typeid(
signed char)
823 || ti ==
typeid(
unsigned char) ||
824 ti ==
typeid(short) || ti ==
typeid(
unsigned short) ||
825 ti ==
typeid(int) || ti ==
typeid(
unsigned int) ||
826 ti ==
typeid(long) || ti ==
typeid(
unsigned long) ) {
830 else if ( ti ==
typeid(
long long) || ti ==
typeid(
unsigned long long) ) {
831 pvalue = cvalue +
"L";
834 else if ( ti ==
typeid(
float) || ti ==
typeid(double) ) {
836 pvalue = boost::to_lower_copy(cvalue);
837 if ( pvalue ==
"nan" ) {
838 pvalue =
"float('nan')";
839 std::cout <<
"WARNING: default value for ["
840 << p->
name() <<
"] is NaN !!"
842 }
else if ( std::string::npos == pvalue.find(
".") &&
843 std::string::npos == pvalue.find(
"e") ) {
844 pvalue = cvalue +
".0";
848 else if ( ti ==
typeid(
string) ) {
850 pvalue =
"'"+cvalue+
"'";
854 m_importGaudiHandles =
true;
860 ptype =
"GaudiHandle";
863 m_importGaudiHandles =
true;
869 ptype =
"GaudiHandleArray";
872 std::ostringstream v_str;
873 v_str.setf(std::ios::fixed);
875 pvalue = v_str.str();
889 propMgr->setProperty(
"JobOptionsType",
"NONE" );
890 propMgr->setProperty(
"AppName",
"");
891 propMgr->setProperty(
"OutputLevel",
"7");