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/format.hpp"
36 #include "boost/regex.hpp"
54 #include "Reflex/PluginService.h"
55 #include "Reflex/Reflex.h"
56 #include "Reflex/SharedLibrary.h"
73 namespace po = boost::program_options;
74 namespace fs = boost::filesystem;
77 using namespace ROOT::Reflex;
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 );
146 m_configurable[
"DefaultName" ] = defaultName;
152 m_configurable[
"Algorithm" ] = cfgAlgorithm;
158 m_configurable[
"AlgTool" ] = cfgAlgTool;
164 m_configurable[
"Auditor" ] = cfgAuditor;
170 m_configurable[
"Service" ] = cfgService;
171 m_configurable[
"ApplicationMgr" ] = cfgService;
183 pyOut << m_pyBuf.str() <<
flush;
184 dbOut << m_dbBuf.str() <<
flush;
190 void pythonizeValue(
const Property* prop,
195 void pythonizeName(
string& name );
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")
241 po::options_description
config(
"Configuration");
243 (
"configurable-module",
244 po::value<string>()->default_value(
"AthenaCommon"),
245 "Name of the module holding the configurable classes")
246 (
"configurable-default-name",
247 po::value<string>()->default_value(
"Configurable.DefaultName"),
248 "Default name for the configurable instance")
249 (
"configurable-algorithm",
250 po::value<string>()->default_value(
"ConfigurableAlgorithm"),
251 "Name of the configurable base class for Algorithm components")
252 (
"configurable-algtool",
253 po::value<string>()->default_value(
"ConfigurableAlgTool"),
254 "Name of the configurable base class for AlgTool components")
255 (
"configurable-auditor",
256 po::value<string>()->default_value(
"ConfigurableAuditor"),
257 "Name of the configurable base class for Auditor components")
258 (
"configurable-service",
259 po::value<string>()->default_value(
"ConfigurableService"),
260 "Name of the configurable base class for Service components")
263 po::options_description cmdline_options;
264 cmdline_options.add(
generic).add(config);
266 po::options_description config_file_options;
267 config_file_options.add(config);
269 po::options_description visible(
"Allowed options");
270 visible.add(
generic).add(config);
272 po::variables_map vm;
275 po::store( po::command_line_parser(argc, argv).
276 options(cmdline_options).run(),
282 if( vm.count(
"input-cfg") ) {
283 string cfgFileName = vm[
"input-cfg"].as<
string>();
284 cfgFileName = fs::system_complete(
fs::path( cfgFileName ) ).string();
286 po::store( parse_config_file( ifs, config_file_options ), vm );
291 catch ( po::error& err ) {
292 cout <<
"ERR0R: error detected while parsing command options: "<< err.what() <<
endl;
297 if( vm.count(
"help")) {
302 if( vm.count(
"package-name") ) {
303 pkgName = vm[
"package-name"].as<
string>();
306 cout <<
"ERROR: 'package-name' required" <<
endl;
311 if( vm.count(
"user-module") ) {
312 userModule = vm[
"user-module"].as<
string>();
313 cout <<
"INFO: will import user module " << userModule <<
endl;
316 if( vm.count(
"input-libraries") ) {
322 string tmp = vm[
"input-libraries"].as<
string>();
324 boost::split( inputLibs, tmp,
325 boost::is_any_of(
" "),
326 boost::token_compress_on );
332 iLib != inputLibs.
end();
335 if ( 0 == lib.find(
"lib") ) {
344 if ( libs.
empty() ) {
345 cout <<
"ERROR: input component library(ies) required !\n"
346 <<
"ERROR: 'input-libraries' argument was ["
347 << vm[
"input-libraries"].as<
string>()
354 cout <<
"ERROR: input component library(ies) required" <<
endl;
359 if( vm.count(
"output-dir") ) {
360 out = fs::system_complete(
fs::path( vm[
"output-dir"].as<string>() ) );
363 if ( vm.count(
"debug-level") ) {
364 PluginService::SetDebug( vm[
"debug-level"].as<int>() );
367 if ( vm.count(
"load-library") ) {
370 lLib != lLib_list.
end();
373 SharedLibrary tmplib(*lLib) ;
379 if ( !fs::exists( out ) ) {
381 fs::create_directory(out);
383 catch ( fs::filesystem_error &err ) {
384 cout <<
"ERR0R: error creating directory: "<< err.what() <<
endl;
389 cout <<
":::::: libraries : [ ";
391 cout <<
"] ::::::" <<
endl;
395 py.setConfigurableDefaultName(vm[
"configurable-default-name"].as<string>());
396 py.setConfigurableAlgorithm (vm[
"configurable-algorithm"].as<string>());
397 py.setConfigurableAlgTool (vm[
"configurable-algtool"].as<string>());
398 py.setConfigurableAuditor (vm[
"configurable-auditor"].as<string>());
399 py.setConfigurableService (vm[
"configurable-service"].as<string>());
403 sc = py.genConfig( libs, userModule );
406 cout <<
"ERROR: Could not generate Configurable(s) !\n"
407 <<
"ERROR: Got exception: " << e.
what() <<
endl;
415 initPy <<
"## Hook for " << pkgName <<
" genConf module\n" <<
flush;
418 cout <<
":::::: libraries : [ ";
420 cout <<
"] :::::: [DONE]" <<
endl;
428 return (m.Properties().HasProperty(
"id") && (m.Properties().PropertyValue(
"id").TypeInfo() ==
typeid(
std::string))) ?
429 m.Properties().PropertyAsString(
"id") :
430 m.Properties().PropertyAsString(
"name") ;
438 #if ROOT_VERSION_CODE < ROOT_VERSION(5,21,6)
439 obj =
static_cast<T*
>(member.Invoke(dummy,args).Address());
441 member.Invoke(dummy,obj,args);
457 const bool isGaudiSvc = (
std::find( libs.
begin(), endLib, gaudiSvc ) != endLib );
461 cout <<
"ERROR: ApplicationMgr can not be created. Check environment" <<
endl;
466 Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS);
468 cout <<
"ERROR: No PluginSvc factory namespace could be found" <<
endl;
484 m_importGaudiHandles =
false;
492 for ( Member_Iterator it = factories.FunctionMember_Begin();
493 it != factories.FunctionMember_End(); ++it ) {
494 string ident =
getId(*it);
495 if ( PluginService::Debug() > 0 ) {
512 for ( Member_Iterator it = factories.FunctionMember_Begin();
513 it != factories.FunctionMember_End();
515 const string ident =
getId(*it);
516 if ( bkgNames.
find(ident) != bkgNamesEnd ) {
517 if ( PluginService::Debug() > 0 ) {
518 cout <<
"\t==> skipping [" << ident <<
"]..." <<
endl;
529 cout <<
"WARNING: library [" << *iLib <<
"] requested factory "
530 <<
"from another library ["
532 <<
" ==> [" << ident <<
"] !!"
537 const string rtype = it->TypeOf().ReturnType().Name();
540 if ( ident ==
"ApplicationMgr" ) type =
"ApplicationMgr";
541 else if ( rtype ==
"IInterface*" ) type =
"IInterface";
542 else if ( rtype ==
"IAlgorithm*" ) type =
"Algorithm";
543 else if ( rtype ==
"IService*" ) type =
"Service";
544 else if ( rtype ==
"IAlgTool*" ) type =
"AlgTool";
545 else if ( rtype ==
"IAuditor*" ) type =
"Auditor";
546 else if ( rtype ==
"IConverter*" ) type =
"Converter";
547 else if ( rtype ==
"DataObject*" ) type =
"DataObject";
548 else type =
"Unknown", known =
false;
553 cout <<
" - component: " << name <<
endl;
555 if ( type ==
"IInterface" ) {
561 if ( type ==
"Converter" || type ==
"DataObject" ) {
572 cout <<
"WARNING: Unknown (return) type [" << rtype <<
"] !!\n"
573 <<
"WARNING: component [" << ident <<
"] is skipped !"
579 string cname =
"DefaultName";
582 if ( type ==
"AlgTool" ) {
595 if ( type ==
"Algorithm" ) {
596 prop = makeInstance<IAlgorithm>(*it,
args);
598 else if ( type ==
"Service") {
599 prop = makeInstance<IService>(*it,
args);
601 else if ( type ==
"AlgTool") {
602 prop = makeInstance<IAlgTool>(*it,
args);
604 else if ( type ==
"Auditor") {
605 prop = makeInstance<IAuditor>(*it,
args);
607 else if ( type ==
"ApplicationMgr") {
612 prop = makeInstance<IInterface>(*it,
args);
616 cout <<
"ERROR: Error instantiating " << name
617 <<
" from " << *iLib <<
endl;
623 cout <<
"ERROR: Error instantiating " << name
624 <<
" from " << *iLib <<
endl;
629 if (genComponent( *iLib, name, type, prop->
getProperties() )) {
634 cout <<
"ERROR: could not cast IInterface* object to an IProperty* !\n"
635 <<
"ERROR: return type from PluginSvc is [" << rtype <<
"]...\n"
636 <<
"ERROR: NO Configurable will be generated for ["
647 fs::path(*iLib+
"Conf.py") ).
string();
649 fs::path(*iLib+
"_confDb.py") ).
string();
656 genHeader ( py, db );
657 if (!userModule.empty())
658 py <<
"from " << userModule <<
" import *" <<
endl;
660 genTrailer( py, db );
677 while ( std::string::npos != pos ){
679 nxtpos = m_configurable[
"Module"].find_first_of(
',',pos);
682 mod = m_configurable[
"Module"].substr(pos,nxtpos-pos);
688 if ( std::string::npos == nxtpos ) {
690 s << indent <<
import.str() <<
"\n" <<
flush;
691 pos = std::string::npos;
694 s << indent <<
"try:\n"
695 << indent << py_tab <<
import.str() <<
"\n"
696 << indent <<
"except ImportError:\n"
713 <<
"\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
714 if ( m_importGaudiHandles ) {
715 py <<
"from GaudiKernel.GaudiHandles import *\n";
718 genImport(py,
boost::format(
"from %1%.Configurable import *"));
721 db <<
"## -*- python -*- \n"
722 <<
"# db file automatically generated by genconf on: "
724 db <<
"## insulates outside world against anything bad that could happen\n"
725 <<
"## also prevents global scope pollution\n"
726 <<
"def _fillCfgDb():\n";
727 genImport(db,
boost::format(
"from %1%.ConfigurableDb import CfgDb"),py_tab);
730 << py_tab <<
"# get a handle on the repository of Configurables\n"
731 << py_tab <<
"cfgDb = CfgDb()\n"
733 << py_tab <<
"# populate the repository with informations on Configurables \n"
743 db << py_tab <<
"return #_fillCfgDb\n"
744 <<
"# fill cfgDb at module import...\n"
746 << py_tab <<
"_fillCfgDb()\n"
747 << py_tab <<
"#house cleaning...\n"
748 << py_tab <<
"del _fillCfgDb\n"
749 <<
"except Exception,err:\n"
750 << py_tab <<
"print \"Py:ConfigurableDb ERROR Problem with [%s] content!"
752 << py_tab <<
"print \"Py:ConfigurableDb ERROR\",err\n"
753 << py_tab <<
"print \"Py:ConfigurableDb ERROR ==> culprit is package ["
754 << m_pkgName <<
"] !\"\n"
766 string cname = componentName;
767 pythonizeName(cname);
770 PropertyDoc_t propDoc;
773 m_pyBuf <<
"class " << cname
774 <<
"( " << m_configurable[componentType] <<
" ) :"
776 m_pyBuf <<
" __slots__ = { \n";
778 it != properties.
end(); ++it ) {
780 const string pname = (*it)->name();
783 std::cout <<
"ERROR: invalid property name \"" << pname
784 <<
"\" in component " << cname
785 <<
" (invalid Python identifier)" <<
std::endl;
787 m_pyBuf <<
" #ERROR-invalid identifier '" << pname <<
"'\n"
792 string pvalue, ptype;
793 pythonizeValue( (*it), pvalue, ptype );
794 m_pyBuf <<
" '" << pname <<
"' : " << pvalue <<
", # " << ptype <<
"\n";
796 if ( (*it)->documentation() !=
"none" ) {
797 propDoc[
pname] = (*it)->documentation();
802 m_pyBuf <<
" _propertyDocDct = { \n";
803 for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
804 iProp != propDoc.end();
807 <<
"'" << iProp->first <<
"' : "
808 <<
"\"\"\" " << iProp->second <<
" \"\"\",\n";
813 <<
" def __init__(self, name = " << m_configurable[
"DefaultName"]
815 <<
" super(" << cname <<
", self).__init__(name)\n"
816 <<
" for n,v in kwargs.items():\n"
817 <<
" setattr(self, n, v)\n"
818 <<
" def getDlls( self ):\n"
819 <<
" return '" << libName <<
"'\n"
820 <<
" def getType( self ):\n"
821 <<
" return '" << componentName <<
"'\n"
822 <<
" pass # class " << cname <<
"\n"
826 const string pyName = (
fs::path(m_outputDirName) /
827 fs::path(libName+
"Conf.py") ).
string();
832 << py_tab <<
"cfgDb.add( configurable = '" << cname <<
"',\n"
833 << py_tab <<
" package = '" << m_pkgName <<
"',\n"
834 << py_tab <<
" module = '" << m_pkgName <<
"." << modName <<
"',\n"
835 << py_tab <<
" lib = '" << libName <<
"' )\n"
844 static string in(
"<>&*,: ().");
845 static string out(
"__rp__s___");
847 if ( in.find(*
i) != string::npos ) *
i = out[in.find(*
i)];
853 string& pvalue,
string& ptype )
858 if ( ti ==
typeid(
bool) ) {
859 pvalue = ( cvalue ==
"0" || cvalue ==
"False" || cvalue ==
"false" )
864 else if ( ti ==
typeid(
char) || ti ==
typeid(
signed char)
865 || ti ==
typeid(
unsigned char) ||
866 ti ==
typeid(short) || ti ==
typeid(
unsigned short) ||
867 ti ==
typeid(
int) || ti ==
typeid(
unsigned int) ||
868 ti ==
typeid(long) || ti ==
typeid(
unsigned long) ) {
872 else if ( ti ==
typeid(
long long) || ti ==
typeid(
unsigned long long) ) {
873 pvalue = cvalue +
"L";
876 else if ( ti ==
typeid(
float) || ti ==
typeid(double) ) {
878 pvalue = boost::to_lower_copy(cvalue);
879 if ( pvalue ==
"nan" ) {
880 pvalue =
"float('nan')";
881 std::cout <<
"WARNING: default value for ["
882 << p->
name() <<
"] is NaN !!"
884 }
else if ( std::string::npos == pvalue.find(
".") &&
885 std::string::npos == pvalue.find(
"e") ) {
886 pvalue = cvalue +
".0";
890 else if ( ti ==
typeid(
string) ) {
892 pvalue =
"'"+cvalue+
"'";
896 m_importGaudiHandles =
true;
902 ptype =
"GaudiHandle";
905 m_importGaudiHandles =
true;
911 ptype =
"GaudiHandleArray";
915 v_str.
setf(std::ios::fixed);
917 pvalue = v_str.str();
931 propMgr->setProperty(
"JobOptionsType",
"NONE" );
932 propMgr->setProperty(
"AppName",
"");
933 propMgr->setProperty(
"OutputLevel",
"7");