genconf.cpp
Go to the documentation of this file.
1 #ifdef _WIN32
2 // Disable a warning in Boost program_options headers:
3 // inconsistent linkage in program_options/variables_map.hpp
4 #pragma warning ( disable : 4273 )
5 
6 // Avoid conflicts between windows and the message service.
7 #define NOMSG
8 #define NOGDI
9 #endif
10 
11 #ifdef __ICC
12 // disable icc warning #279: controlling expression is constant
13 // ... a lot of noise produced by the boost/filesystem/operations.hpp
14 #pragma warning(disable:279)
15 // Avoid icc remark #193: zero used for undefined preprocessing identifier "_MSC_VER"
16 #if !defined(_WIN32) && !defined(_MSC_VER)
17 #define _MSC_VER 0
18 #endif
19 #endif
20 
21 #include "boost/program_options.hpp"
22 // the hack for remark #193 is needed only for program_options and breaks regex.
23 #if defined(__ICC) && !defined(_WIN32) && (_MSC_VER == 0)
24 #undef _MSC_VER
25 #endif
26 
27 // Include files----------------------------------------------------------------
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"
38 
39 #include <boost/log/core.hpp>
40 #include <boost/log/trivial.hpp>
41 #include <boost/log/expressions.hpp>
42 #include <boost/log/utility/setup/console.hpp>
43 #include <boost/log/utility/setup/common_attributes.hpp>
44 
45 #include "GaudiKernel/System.h"
46 #include "GaudiKernel/ISvcLocator.h"
47 #include "GaudiKernel/IProperty.h"
48 #include "GaudiKernel/IAppMgrUI.h"
49 #include "GaudiKernel/IAlgorithm.h"
50 #include "GaudiKernel/IAlgTool.h"
51 #include "GaudiKernel/IAuditor.h"
52 #include "GaudiKernel/IAppMgrUI.h"
53 #include "GaudiKernel/Service.h"
54 #include "GaudiKernel/Bootstrap.h"
55 #include "GaudiKernel/SmartIF.h"
56 #include "GaudiKernel/HashMap.h"
57 #include "GaudiKernel/GaudiHandle.h"
58 #include "GaudiKernel/DataObjectDescriptor.h"
59 
60 #include "GaudiKernel/Auditor.h"
61 #include "GaudiKernel/Service.h"
62 #include "GaudiKernel/AlgTool.h"
63 #include "GaudiKernel/Algorithm.h"
64 
65 #include "GaudiKernel/Time.h"
66 
67 #include <Gaudi/PluginService.h>
68 
69 #include <algorithm>
70 #include <iostream>
71 #include <fstream>
72 #include <sstream>
73 #include <exception>
74 #include <set>
75 #include <vector>
76 
77 #include "DsoUtils.h"
78 
79 namespace po = boost::program_options;
80 namespace fs = boost::filesystem;
81 
82 #define LOG_ERROR BOOST_LOG_TRIVIAL(error)
83 #define LOG_WARNING BOOST_LOG_TRIVIAL(warning)
84 #define LOG_INFO BOOST_LOG_TRIVIAL(info)
85 #define LOG_DEBUG BOOST_LOG_TRIVIAL(debug)
86 
87 using namespace std;
88 
89 class IConverter;
90 
91 // useful typedefs
92 typedef std::vector<std::string> Strings_t;
93 typedef std::vector<fs::path> LibPathNames_t;
94 
95 namespace {
96  const std::string py_tab = " ";
97 
100  const boost::regex pythonIdentifier("^[a-zA-Z_][a-zA-Z0-9_]*$");
101 }
102 
104 {
106  string m_pkgName;
107 
111 
113  stringstream m_pyBuf;
114 
118 
120 
125  stringstream m_dbBuf;
126 
133 
134 public:
135  configGenerator( const string& pkgName,
136  const string& outputDirName ) :
137  m_pkgName ( pkgName ),
138  m_outputDirName ( outputDirName ),
139  m_pyBuf ( ),
140  m_importGaudiHandles( false ),
141  m_importDataObjectDescriptors( false ),
142  m_dbBuf ( ),
143  m_configurable ( )
144  {}
145 
150  int genConfig( const Strings_t& modules, const string& userModule );
151 
153  void setConfigurableModule( const std::string& moduleName )
154  {
155  m_configurable[ "Module" ] = moduleName;
156  }
157 
159  void setConfigurableDefaultName( const std::string& defaultName )
160  {
161  m_configurable[ "DefaultName" ] = defaultName;
162  }
163 
165  void setConfigurableAlgorithm( const std::string& cfgAlgorithm )
166  {
167  m_configurable[ "Algorithm" ] = cfgAlgorithm;
168  }
169 
171  void setConfigurableAlgTool( const std::string& cfgAlgTool )
172  {
173  m_configurable[ "AlgTool" ] = cfgAlgTool;
174  }
175 
177  void setConfigurableAuditor( const std::string& cfgAuditor )
178  {
179  m_configurable[ "Auditor" ] = cfgAuditor;
180  }
181 
183  void setConfigurableService( const std::string& cfgService )
184  {
185  m_configurable[ "Service" ] = cfgService;
186  m_configurable[ "ApplicationMgr" ] = cfgService;
187  }
188 
189 private:
190  int genComponent( const std::string& libName,
191  const std::string& componentName,
192  const std::string& componentType,
193  const vector<Property*>& properties );
194  void genImport( std::ostream& s, const boost::format& frmt,std::string indent);
195  void genHeader( std::ostream& pyOut, std::ostream& dbOut );
196  void genBody( std::ostream& pyOut,
197  std::ostream& dbOut ) {
198  pyOut << m_pyBuf.str() << flush;
199  dbOut << m_dbBuf.str() << flush;
200  }
201  void genTrailer( std::ostream& pyOut,
202  std::ostream& dbOut );
203 
205  void pythonizeValue( const Property* prop,
206  string& pvalue,
207  string& ptype );
208 
210  void pythonizeName( string& name );
211 };
212 
213 int createAppMgr();
214 
215 void init_logging(boost::log::trivial::severity_level level)
216 {
217  namespace logging = boost::log;
218  namespace keywords = boost::log::keywords;
219  namespace expr = boost::log::expressions;
220 
221  logging::add_console_log
222  (
223  std::cout,
224  keywords::format = (
225  expr::stream
226  << "[" << std::setw(7) << std::left
227  << logging::trivial::severity
228  << "] " << expr::smessage
229  )
230  );
231 
232  logging::core::get()->set_filter
233  (
234  logging::trivial::severity >= level
235  );
236 
237 }
238 
239 
240 //--- Command main program-----------------------------------------------------
241 int main ( int argc, char** argv )
242 //-----------------------------------------------------------------------------
243 {
244  init_logging((System::isEnvSet("VERBOSE") && !System::getEnv("VERBOSE").empty())
245  ? boost::log::trivial::info
246  : boost::log::trivial::warning);
247 
248  fs::path pwd = fs::initial_path();
249  fs::path out;
250  Strings_t libs;
251  std::string pkgName;
252  std::string userModule;
253 
254  // declare a group of options that will be allowed only on command line
255  po::options_description generic("Generic options");
256  generic.add_options()
257  ("help,h",
258  "produce this help message")
259  ("package-name,p",
260  po::value<string>(),
261  "name of the package for which we create the configurables file")
262  ("input-libraries,i",
263  po::value<string>(),
264  "libraries to extract the component configurables from")
265  ("input-cfg,c",
266  po::value<string>(),
267  "path to the cfg file holding the description of the Configurable base "
268  "classes, the python module holding the Configurable definitions, etc...")
269  ("output-dir,o",
270  po::value<string>()->default_value("../genConf"),
271  "output directory for genconf files.")
272  ("debug-level,d",
273  po::value<int>()->default_value(0),
274  "debug level")
275  ("load-library,l",
276  po::value< Strings_t >()->composing(),
277  "preloading library")
278  ("user-module,m",
279  po::value<string>(),
280  "user-defined module to be imported by the genConf-generated one")
281  ("no-init",
282  "do not generate the (empty) __init__.py")
283  ;
284 
285  // declare a group of options that will be allowed both on command line
286  // _and_ in configuration file
287  po::options_description config("Configuration");
288  config.add_options()
289  ("configurable-module",
290  po::value<string>()->default_value("AthenaCommon"),
291  "Name of the module holding the configurable classes")
292  ("configurable-default-name",
293  po::value<string>()->default_value("Configurable.DefaultName"),
294  "Default name for the configurable instance")
295  ("configurable-algorithm",
296  po::value<string>()->default_value("ConfigurableAlgorithm"),
297  "Name of the configurable base class for Algorithm components")
298  ("configurable-algtool",
299  po::value<string>()->default_value("ConfigurableAlgTool"),
300  "Name of the configurable base class for AlgTool components")
301  ("configurable-auditor",
302  po::value<string>()->default_value("ConfigurableAuditor"),
303  "Name of the configurable base class for Auditor components")
304  ("configurable-service",
305  po::value<string>()->default_value("ConfigurableService"),
306  "Name of the configurable base class for Service components")
307  ;
308 
309  po::options_description cmdline_options;
310  cmdline_options.add(generic).add(config);
311 
312  po::options_description config_file_options;
313  config_file_options.add(config);
314 
315  po::options_description visible("Allowed options");
316  visible.add(generic).add(config);
317 
318  po::variables_map vm;
319 
320  try {
321  po::store( po::command_line_parser(argc, argv).
322  options(cmdline_options).run(),
323  vm );
324 
325  po::notify(vm);
326 
327  // try to read configuration from the optionally given configuration file
328  if( vm.count("input-cfg") ) {
329  string cfgFileName = vm["input-cfg"].as<string>();
330  cfgFileName = fs::system_complete( fs::path( cfgFileName ) ).string();
331  std::ifstream ifs( cfgFileName );
332  po::store( parse_config_file( ifs, config_file_options ), vm );
333  }
334 
335  po::notify(vm);
336  }
337  catch ( po::error& err ) {
338  LOG_ERROR
339  << "error detected while parsing command options: "
340  << err.what();
341  return EXIT_FAILURE;
342  }
343 
344  //--- Process command options -----------------------------------------------
345  if( vm.count("help")) {
346  cout << visible << endl;
347  return EXIT_FAILURE;
348  }
349 
350  if( vm.count("package-name") ) {
351  pkgName = vm["package-name"].as<string>();
352  }
353  else {
354  LOG_ERROR << "'package-name' required";
355  cout << visible << endl;
356  return EXIT_FAILURE;
357  }
358 
359  if( vm.count("user-module") ) {
360  userModule = vm["user-module"].as<string>();
361  LOG_INFO << "INFO: will import user module " << userModule;
362  }
363 
364  if( vm.count("input-libraries") ) {
365  // re-shape the input arguments:
366  // - removes spurious spaces,
367  // - split into tokens.
368  Strings_t inputLibs;
369  {
370  string tmp = vm["input-libraries"].as<string>();
371  boost::trim(tmp);
372  boost::split( inputLibs, tmp,
373  boost::is_any_of(" "),
374  boost::token_compress_on );
375  }
376 
377  //
378  libs.reserve( inputLibs.size() );
379  for ( Strings_t::const_iterator iLib = inputLibs.begin();
380  iLib != inputLibs.end();
381  ++iLib ) {
382  std::string lib = fs::path(*iLib).stem().string();
383  if ( 0 == lib.find("lib") ) {
384  lib = lib.substr(3); // For *NIX remove "lib"
385  }
386  // remove duplicates
387  if ( !lib.empty() &&
388  std::find( libs.begin(), libs.end(), lib ) == libs.end() ) {
389  libs.push_back( lib );
390  }
391  } //> end loop over input-libraries
392  if ( libs.empty() ) {
393  LOG_ERROR << "input component library(ies) required !\n";
394  LOG_ERROR << "'input-libraries' argument was ["
395  << vm["input-libraries"].as<string>()
396  << "]";
397  return EXIT_FAILURE;
398  }
399  }
400  else {
401  LOG_ERROR << "input component library(ies) required";
402  cout << visible << endl;
403  return EXIT_FAILURE;
404  }
405 
406  if( vm.count("output-dir") ) {
407  out = fs::system_complete( fs::path( vm["output-dir"].as<string>() ) );
408  }
409 
410  if ( vm.count("debug-level") ) {
411  Gaudi::PluginService::SetDebug( vm["debug-level"].as<int>() );
412  }
413 
414  if ( vm.count("load-library") ) {
415  Strings_t lLib_list = vm["load-library"].as< Strings_t >();
416  for (Strings_t::const_iterator lLib=lLib_list.begin();
417  lLib != lLib_list.end();
418  ++lLib) {
419  // load done through Gaudi helper class
420  System::ImageHandle tmp; // we ignore the library handle
421  unsigned long err = System::loadDynamicLib(*lLib, &tmp);
422  if (err != 1) {
423  LOG_WARNING << "failed to load: "<< *lLib;
424  }
425  }
426  }
427 
428 
429  if ( !fs::exists( out ) ) {
430  try {
431  fs::create_directory(out);
432  }
433  catch ( fs::filesystem_error &err ) {
434  LOG_ERROR << "error creating directory: "<< err.what();
435  return EXIT_FAILURE;
436  }
437  }
438 
439  {
440  std::ostringstream msg;
441  msg << ":::::: libraries : [ ";
442  copy( libs.begin(), libs.end(), ostream_iterator<string>(msg, " ") );
443  msg << "] ::::::";
444  LOG_INFO << msg.str();
445  }
446 
447  configGenerator py( pkgName, out.string() );
448  py.setConfigurableModule (vm["configurable-module"].as<string>());
449  py.setConfigurableDefaultName(vm["configurable-default-name"].as<string>());
450  py.setConfigurableAlgorithm (vm["configurable-algorithm"].as<string>());
451  py.setConfigurableAlgTool (vm["configurable-algtool"].as<string>());
452  py.setConfigurableAuditor (vm["configurable-auditor"].as<string>());
453  py.setConfigurableService (vm["configurable-service"].as<string>());
454 
455  int sc = EXIT_FAILURE;
456  try {
457  sc = py.genConfig( libs, userModule );
458  }
459  catch ( exception& e ) {
460  cout << "ERROR: Could not generate Configurable(s) !\n"
461  << "ERROR: Got exception: " << e.what() << endl;
462  return EXIT_FAILURE;
463  }
464 
465  if ( EXIT_SUCCESS == sc && ! vm.count("no-init")) {
466  // create an empty __init__.py file in the output dir
467  fstream initPy( ( out / fs::path( "__init__.py" ) ).string(),
468  std::ios_base::out|std::ios_base::trunc );
469  initPy << "## Hook for " << pkgName << " genConf module\n" << flush;
470  }
471 
472  {
473  std::ostringstream msg;
474  msg << ":::::: libraries : [ ";
475  copy( libs.begin(), libs.end(), ostream_iterator<string>(msg, " ") );
476  msg << "] :::::: [DONE]";
477  LOG_INFO << msg.str();
478  }
479  return sc;
480 }
481 
482 //-----------------------------------------------------------------------------
483 int configGenerator::genConfig( const Strings_t& libs, const string& userModule )
484 //-----------------------------------------------------------------------------
485 {
486  //--- Disable checking StatusCode -------------------------------------------
488 
489  const Strings_t::const_iterator endLib = libs.end();
490 
491  const std::string gaudiSvc = "GaudiCoreSvc";
492  const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );
493 
494  //--- Instantiate ApplicationMgr --------------------------------------------
495  if ( !isGaudiSvc && createAppMgr() ) {
496  cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl;
497  return EXIT_FAILURE;
498  }
499 
500  //--- Iterate over component factories --------------------------------------
502  Registry& registry = Registry::instance();
503 
504  std::set<std::string> bkgNames = registry.loadedFactories();
505 
506  ISvcLocator* svcLoc = Gaudi::svcLocator();
507  IInterface* dummySvc = new Service( "DummySvc", svcLoc );
508  dummySvc->addRef();
509 
510  bool allGood = true;
511 
512  // iterate over all the requested libraries
513  for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {
514 
515  LOG_INFO << ":::: processing library: " << *iLib << "...";
516 
517  // reset state
518  m_importGaudiHandles = false;
519  m_importDataObjectDescriptors = false;
520  m_pyBuf.str("");
521  m_dbBuf.str("");
522 
523  //--- Load component library ----------------------------------------------
524  System::ImageHandle handle;
525  unsigned long err = System::loadDynamicLib( *iLib, &handle );
526  if ( err != 1 ) {
528  allGood = false;
529  continue;
530  }
531 
532  std::set<std::string> factories = registry.loadedFactories();
533 
534  for ( std::set<std::string>::iterator it = factories.begin();
535  it != factories.end(); ++it ) {
536  const string ident = *it;
537  if ( bkgNames.find(ident) != bkgNames.end() ) {
539  LOG_INFO << "\t==> skipping [" << ident << "]...";
540  }
541  continue;
542  }
543 
544  const Registry::FactoryInfo info = registry.getInfo(*it);
545  const string rtype = info.rtype;
546 
547  // do not generate configurables for the Reflex-compatible aliases
548  if (info.properties.find("ReflexName") != info.properties.end())
549  continue;
550 
551  // Atlas contributed code (patch #1247)
552  // Skip the generation of configurables if the component does not come
553  // from the same library we are processing (i.e. we found a symbol that
554  // is coming from a library loaded by the linker).
555  if ( !DsoUtils::inDso( info.ptr, DsoUtils::libNativeName(*iLib) ) ) {
556  LOG_WARNING << "library [" << *iLib << "] exposes factory ["
557  << ident << "] which is declared in ["
558  << DsoUtils::dsoName(info.ptr) << "] !!";
559  continue;
560  }
561 
562  string type;
563  bool known = true;
564  if ( ident == "ApplicationMgr" ) type = "ApplicationMgr";
565  else if ( rtype == typeid(IInterface*).name() ) type = "IInterface";
566  else if ( rtype == typeid(IAlgorithm*).name() ) type = "Algorithm";
567  else if ( rtype == typeid(IService* ).name() ) type = "Service";
568  else if ( rtype == typeid(IAlgTool* ).name() ) type = "AlgTool";
569  else if ( rtype == typeid(IAuditor* ).name() ) type = "Auditor";
570  else if ( rtype == typeid(IConverter*).name() ) type = "Converter";
571  else if ( rtype == typeid(DataObject*).name() ) type = "DataObject";
572  else type = "Unknown", known = false;
573  string name = ident;
574  // handle possible problems with templated components
575  boost::trim(name);
576 
577  if ( type == "IInterface" ) {
580  continue;
581  }
582 
583  if ( type == "Converter" || type == "DataObject" ) {
585  continue;
586  }
587 
588  if ( !known ) {
589  LOG_WARNING << "Unknown (return) type [" << System::typeinfoName(rtype.c_str()) << "] !!"
590  << " Component [" << ident << "] is skipped !";
591  continue;
592  }
593 
594  LOG_INFO << " - component: " << info.className
595  << " (" << (info.className != name ? (name + ": ")
596  : std::string())
597  << type << ")";
598 
599  string cname = "DefaultName";
600  SmartIF<IProperty> prop;
601  try {
602  if ( type == "Algorithm" ) {
603  prop = SmartIF<IAlgorithm>(Algorithm::Factory::create(ident, cname, svcLoc));
604  }
605  else if ( type == "Service") {
606  prop = SmartIF<IService>(Service::Factory::create(ident, cname, svcLoc));
607  }
608  else if ( type == "AlgTool") {
609  prop = SmartIF<IAlgTool>(AlgTool::Factory::create(ident, cname, type, dummySvc));
610  // FIXME: AlgTool base class increase artificially by 1 the refcount.
611  prop->release();
612  }
613  else if ( type == "Auditor") {
614  prop = SmartIF<IAuditor>(Auditor::Factory::create(ident, cname, svcLoc));
615  }
616  else if ( type == "ApplicationMgr") {
617  prop = SmartIF<ISvcLocator>(svcLoc);
618  }
619  else {
620  continue; // unknown
621  }
622  }
623  catch ( exception& e ) {
624  LOG_ERROR << "Error instantiating " << name
625  << " from " << *iLib;
626  LOG_ERROR << "Got exception: " << e.what();
627  allGood = false;
628  continue;
629  }
630  catch ( ... ) {
631  LOG_ERROR << "Error instantiating " << name
632  << " from " << *iLib;
633  allGood = false;
634  continue;
635  }
636  if( prop ) {
637  if (genComponent( *iLib, name, type, prop->getProperties() )) {
638  allGood = false;
639  }
640  prop.reset();
641  } else {
642  LOG_ERROR << "could not cast IInterface* object to an IProperty* !";
643  LOG_ERROR << "return type from PluginSvc is [" << rtype << "]...";
644  LOG_ERROR << "NO Configurable will be generated for ["
645  << name << "] !";
646  allGood = false;
647  }
648  } //> end loop over factories
649 
653  const std::string pyName = ( fs::path(m_outputDirName) /
654  fs::path(*iLib+"Conf.py") ).string();
655  const std::string dbName = ( fs::path(m_outputDirName) /
656  fs::path(*iLib+".confdb") ).string();
657 
658  std::fstream py( pyName, std::ios_base::out|std::ios_base::trunc );
659  std::fstream db( dbName, std::ios_base::out|std::ios_base::trunc );
660 
661  genHeader ( py, db );
662  if (!userModule.empty())
663  py << "from " << userModule << " import *" <<endl;
664  genBody ( py, db );
665  genTrailer( py, db );
666 
667  } //> end loop over libraries
668 
669  dummySvc->release();
670  dummySvc = 0;
671 
672  return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
673 }
674 
675 void configGenerator::genImport( std::ostream& s,
676  const boost::format& frmt,
677  std::string indent = ""){
678 
679  std::string::size_type pos = 0, nxtpos = 0;
680  std::string mod;
681 
682  while ( std::string::npos != pos ){
683  // find end of module name
684  nxtpos = m_configurable["Module"].find_first_of(',',pos);
685 
686  // Prepare import string
687  mod = m_configurable["Module"].substr(pos,nxtpos-pos);
688  std::ostringstream import;
689  import << boost::format(frmt) % mod;
690 
691  // append a normal import or a try/except enclosed one depending
692  // on availability of a fall-back module (next in the list)
693  if ( std::string::npos == nxtpos ) {
694  // last possible module
695  s << indent << import.str() << "\n" << flush;
696  pos = std::string::npos;
697  } else {
698  // we have a fallback for this
699  s << indent << "try:\n"
700  << indent << py_tab << import.str() << "\n"
701  << indent << "except ImportError:\n"
702  << flush;
703  pos = nxtpos+1;
704  }
705  // increase indentation level for next iteration
706  indent += py_tab;
707  }
708 }
709 
710 //-----------------------------------------------------------------------------
711 void configGenerator::genHeader( std::ostream& py,
712  std::ostream& db )
713 //-----------------------------------------------------------------------------
714 {
715  // python file part
716  std::string now = Gaudi::Time::current().format(true);
717  py << "#" << now //<< "\n"
718  << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
719  if ( m_importGaudiHandles ) {
720  py << "from GaudiKernel.GaudiHandles import *\n";
721  }
722 
723  if ( m_importDataObjectDescriptors ) {
724  py << "from GaudiKernel.DataObjectDescriptor import *\n";
725  }
726 
727  genImport(py,boost::format("from %1%.Configurable import *"));
728 
729  // db file part
730  db << "## -*- ascii -*- \n"
731  << "# db file automatically generated by genconf on: "
732  << now
733  << "\n"
734  << flush;
735 }
736 //-----------------------------------------------------------------------------
737 void configGenerator::genTrailer( std::ostream& /*py*/,
738  std::ostream& db )
739 //-----------------------------------------------------------------------------
740 {
741  // db file part
742  db << "## " << m_pkgName << "\n"
743  << std::flush;
744 }
745 
746 //-----------------------------------------------------------------------------
747 int
748 configGenerator::genComponent( const std::string& libName,
749  const std::string& componentName,
750  const std::string& componentType,
751  const vector<Property*>& properties )
752 //-----------------------------------------------------------------------------
753 {
754  string cname = componentName;
755  pythonizeName(cname);
756 
757  typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t;
758  PropertyDoc_t propDoc;
759 
760  m_pyBuf << "\n";
761  m_pyBuf << "class " << cname
762  << "( " << m_configurable[componentType] << " ) :"
763  << "\n";
764  m_pyBuf << " __slots__ = { \n";
765  for ( vector<Property*>::const_iterator it = properties.begin() ;
766  it != properties.end(); ++it ) {
767 
768  const string pname = (*it)->name();
769  // Validate property name (it must be a valid Python identifier)
770  if (!boost::regex_match(pname, pythonIdentifier)) {
771  std::cout << "ERROR: invalid property name \"" << pname
772  << "\" in component " << cname
773  << " (invalid Python identifier)" << std::endl;
774  // try to make the buffer at least more or less valid python code.
775  m_pyBuf << " #ERROR-invalid identifier '" << pname << "'\n"
776  << " }\n";
777  return 1;
778  }
779 
780  string pvalue, ptype;
781  pythonizeValue( (*it), pvalue, ptype );
782  m_pyBuf << " '" << pname << "' : " << pvalue <<", # " << ptype << "\n";
783 
784  if ( (*it)->documentation() != "none" ) {
785  propDoc[pname] = (*it)->documentation();
786  }
787 
788  }
789  m_pyBuf << " }\n";
790  m_pyBuf << " _propertyDocDct = { \n";
791  for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
792  iProp != propDoc.end();
793  ++iProp ) {
794  m_pyBuf << std::setw(5)
795  << "'" << iProp->first << "' : "
796  << "\"\"\" " << iProp->second << " \"\"\",\n";
797  }
798  m_pyBuf << " }\n";
799 
800  m_pyBuf
801  << " def __init__(self, name = " << m_configurable["DefaultName"]
802  << ", **kwargs):\n"
803  << " super(" << cname << ", self).__init__(name)\n"
804  << " for n,v in kwargs.items():\n"
805  << " setattr(self, n, v)\n"
806  << " def getDlls( self ):\n"
807  << " return '" << libName << "'\n"
808  << " def getType( self ):\n"
809  << " return '" << componentName << "'\n"
810  << " pass # class " << cname << "\n"
811  << flush;
812 
813  // name of the auto-generated module
814  const string pyName = ( fs::path(m_outputDirName) /
815  fs::path(libName+"Conf.py") ).string();
816  const string modName = fs::basename( fs::path( pyName ).leaf() );
817 
818  // now the db part
819  m_dbBuf
820  << m_pkgName << "." << modName << " "
821  << libName << " " << cname
822  << "\n"
823  << flush;
824 
825  return 0;
826 }
827 //-----------------------------------------------------------------------------
829 //-----------------------------------------------------------------------------
830 {
831  static string in("<>&*,: ().");
832  static string out("__rp__s___");
833  boost::algorithm::replace_all(name, ", ", ",");
834  for ( string::iterator i = name.begin(); i != name.end(); ++i ) {
835  if ( in.find(*i) != string::npos ) *i = out[in.find(*i)];
836  }
837 }
838 
839 //-----------------------------------------------------------------------------
841  string& pvalue, string& ptype )
842 //-----------------------------------------------------------------------------
843 {
844  const std::string cvalue = p->toString();
845  const type_info& ti = *p->type_info();
846  if ( ti == typeid(bool) ) {
847  pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" )
848  ? "False"
849  : "True";
850  ptype = "bool";
851  }
852  else if ( ti == typeid(char) || ti == typeid(signed char)
853  || ti == typeid(unsigned char) ||
854  ti == typeid(short) || ti == typeid(unsigned short) ||
855  ti == typeid(int) || ti == typeid(unsigned int) ||
856  ti == typeid(long) || ti == typeid(unsigned long) ) {
857  pvalue = cvalue;
858  ptype = "int";
859  }
860  else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) {
861  pvalue = cvalue + "L";
862  ptype = "long";
863  }
864  else if ( ti == typeid(float) || ti == typeid(double) ) {
865  // forces python to handle this as a float: put a dot in there...
866  pvalue = boost::to_lower_copy(cvalue);
867  if ( pvalue == "nan" ) {
868  pvalue = "float('nan')";
869  std::cout << "WARNING: default value for ["
870  << p->name() << "] is NaN !!"
871  << std::endl;
872  } else if ( std::string::npos == pvalue.find(".") &&
873  std::string::npos == pvalue.find("e") ) {
874  pvalue = cvalue + ".0";
875  }
876  ptype = "float";
877  }
878  else if ( ti == typeid(string) ) {
879 
880  pvalue = "'"+cvalue+"'";
881  ptype = "str";
882  }
883  else if ( ti == typeid(GaudiHandleBase) ) {
884  m_importGaudiHandles = true;
885  const GaudiHandleProperty& hdl
886  = dynamic_cast<const GaudiHandleProperty&>(*p);
887  const GaudiHandleBase& base = hdl.value();
888 
889  pvalue = base.pythonRepr();
890  ptype = "GaudiHandle";
891  }
892  else if ( ti == typeid(GaudiHandleArrayBase) ) {
893  m_importGaudiHandles = true;
894  const GaudiHandleArrayProperty& hdl
895  = dynamic_cast<const GaudiHandleArrayProperty&>(*p);
896  const GaudiHandleArrayBase& base = hdl.value();
897 
898  pvalue = base.pythonRepr();
899  ptype = "GaudiHandleArray";
900  }
901  else if ( ti == typeid(DataObjectDescriptor) ) {
902  m_importDataObjectDescriptors = true;
904  = dynamic_cast<const DataObjectDescriptorProperty&>(*p);
905  const DataObjectDescriptor& base = hdl.value();
906 
907  pvalue = base.pythonRepr();
908  ptype = "DataDescriptor";
909  }
910  else if ( ti == typeid(DataObjectDescriptorCollection) ) {
911  m_importDataObjectDescriptors = true;
913  = dynamic_cast<const DataObjectDescriptorCollectionProperty&>(*p);
914  const DataObjectDescriptorCollection& base = hdl.value();
915 
916  pvalue = base.pythonRepr();
917  ptype = "DataDescriptorCollection";
918  }
919  else {
920  std::ostringstream v_str;
921  v_str.setf(std::ios::fixed); // to correctly display floats
922  p->toStream(v_str);
923  pvalue = v_str.str();
924  ptype = "list";
925  }
926 }
927 
928 #include "GaudiKernel/IMessageSvc.h"
929 //-----------------------------------------------------------------------------
931 //-----------------------------------------------------------------------------
932 {
934  SmartIF<IAppMgrUI> appUI ( iface );
935  auto propMgr = appUI.as<IProperty>();
936 
937  if ( !propMgr || !appUI ) return EXIT_FAILURE;
938  propMgr->setProperty( "JobOptionsType", "NONE" ); // No job options
939  propMgr->setProperty( "AppName", ""); // No initial printout message
940  propMgr->setProperty( "OutputLevel", "7"); // No other printout messages
941  appUI->configure();
943  msgSvc->setProperty("setWarning", "['DefaultName', 'PropertyMgr']");
944  msgSvc->setProperty("Format", "%T %0W%M");
945  return EXIT_SUCCESS;
946 }
const GaudiHandleArrayBase & value() const
Definition: Property.h:892
int genConfig(const Strings_t &modules, const string &userModule)
main entry point of this class:
Definition: genconf.cpp:483
virtual std::string pythonRepr() const
Python representation of handle, i.e.
Definition: GaudiHandle.cpp:56
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
The data converters are responsible to translate data from one representation into another...
Definition: IConverter.h:57
virtual const std::vector< Property * > & getProperties() const =0
Get list of properties.
virtual std::string toString() const =0
value -> string
std::vector< std::string > Strings_t
Definition: genconf.cpp:89
const std::string & name() const
property name
Definition: Property.h:45
-*- C++ -*- /////////////////////////////
int genComponent(const std::string &libName, const std::string &componentName, const std::string &componentType, const vector< Property * > &properties)
Definition: genconf.cpp:748
void pythonizeValue(const Property *prop, string &pvalue, string &ptype)
handle the "marshalling" of Properties
Definition: genconf.cpp:840
static Time current(void)
Returns the current time.
Definition: Time.cpp:113
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:297
void pythonizeName(string &name)
Translates a valid C++ typename into a valid python one.
Definition: genconf.cpp:828
list path
Definition: __init__.py:15
#define LOG_ERROR
Definition: genconf.cpp:82
void setConfigurableDefaultName(const std::string &defaultName)
customize the default name for configurable instances
Definition: genconf.cpp:159
virtual const DataObjectDescriptor & value() const
STL namespace.
const DataObjectDescriptorCollection & value() const
GAUDIPS_API Logger & logger()
Return the current logger instance.
std::vector< fs::path > LibPathNames_t
Definition: genconf.cpp:93
GAUDI_API const std::string & moduleName()
Get the name of the (executable/DLL) file without file-type.
Definition: ModuleInfo.cpp:54
void setConfigurableAlgTool(const std::string &cfgAlgTool)
customize the configurable base class for AlgTool component
Definition: genconf.cpp:171
void * ImageHandle
Definition of an image handle.
Definition: ModuleInfo.h:30
const std::string pythonRepr() const
GaudiUtils::HashMap< std::string, std::string > m_configurable
Configurable customization.
Definition: genconf.cpp:132
stringstream m_pyBuf
buffer of auto-generated configurables
Definition: genconf.cpp:113
void setConfigurableModule(const std::string &moduleName)
customize the Module name where configurable base classes are defined
Definition: genconf.cpp:153
list argv
Definition: gaudirun.py:227
list options
Definition: gaudirun.py:396
SmartIF< IFace > as() const
return a new SmartIF instance to another interface
Definition: SmartIF.h:110
int main(int argc, char **argv)
Definition: genconf.cpp:241
GAUDI_API ISvcLocator * svcLocator()
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
#define LOG_INFO
Definition: genconf.cpp:84
General service interface definition.
Definition: IService.h:18
Definition of the basic interface.
Definition: IInterface.h:234
virtual StatusCode setProperty(const Property &p)=0
Set the property by property.
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
Definition: System.cpp:637
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:617
void genHeader(std::ostream &pyOut, std::ostream &dbOut)
Definition: genconf.cpp:711
stringstream m_dbBuf
buffer of generated configurables informations for the "Db" file The "Db" file is holding information...
Definition: genconf.cpp:125
configGenerator(const string &pkgName, const string &outputDirName)
Definition: genconf.cpp:135
The IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:23
void setConfigurableAlgorithm(const std::string &cfgAlgorithm)
customize the configurable base class for Algorithm component
Definition: genconf.cpp:165
void init_logging(boost::log::trivial::severity_level level)
Definition: genconf.cpp:215
Base class of array's of various gaudihandles.
Definition: GaudiHandle.h:320
string m_outputDirName
absolute path to the directory where genconf will store auto-generated files (Configurables and Confi...
Definition: genconf.cpp:110
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
virtual unsigned long release()=0
Release Interface instance.
#define LOG_WARNING
Definition: genconf.cpp:83
def basename(url)
void genImport(std::ostream &s, const boost::format &frmt, std::string indent)
Definition: genconf.cpp:675
bool m_importGaudiHandles
switch to decide if the generated configurables need to import GaudiHandles (ie: if one of the compon...
Definition: genconf.cpp:117
void setConfigurableService(const std::string &cfgService)
customize the configurable base class for Service component
Definition: genconf.cpp:183
The interface implemented by the AlgTool base class.
Definition: IAlgTool.h:23
const GaudiHandleBase & value() const
Definition: Property.h:832
GAUDI_API const std::string getLastErrorString()
Get last system error as string.
Definition: System.cpp:254
string s
Definition: gaudirun.py:245
In-memory database of the loaded factories.
string m_pkgName
name of the package we are processing
Definition: genconf.cpp:106
GAUDI_API unsigned long loadDynamicLib(const std::string &name, ImageHandle *handle)
Load dynamic link library.
Definition: System.cpp:124
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
static GAUDI_API void disableChecking()
Definition: StatusCode.cpp:23
const std::type_info * type_info() const
property type-info
Definition: Property.h:49
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:88
void genTrailer(std::ostream &pyOut, std::ostream &dbOut)
Definition: genconf.cpp:737
bool m_importDataObjectDescriptors
Definition: genconf.cpp:119
Base class to handles to be used in lieu of naked pointers to various Gaudi components.
Definition: GaudiHandle.h:93
virtual StatusCode configure()=0
Configure the job.
The IProperty is the basic interface for all components which have properties that can be set or get...
Definition: IProperty.h:21
Base class for all services.
Definition: Service.h:35
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
list i
Definition: ana.py:128
int createAppMgr()
Definition: genconf.cpp:930
The IAuditor is the interface implmented by the AlgAuditor base class.
Definition: IAuditor.h:18
std::string libNativeName(const std::string &libName)
Definition: DsoUtils.h:18
void genBody(std::ostream &pyOut, std::ostream &dbOut)
Definition: genconf.cpp:196
string type
Definition: gaudirun.py:151
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition: Time.cpp:279
GAUDI_API IAppMgrUI * createApplicationMgr(const std::string &dllname, const std::string &factname)
const std::string pythonRepr() const
virtual void toStream(std::ostream &out) const =0
value -> stream
void setConfigurableAuditor(const std::string &cfgAuditor)
customize the configurable base class for AlgTool component
Definition: genconf.cpp:177
std::string pythonRepr() const override
Python representation of array of handles, i.e.
Definition: GaudiHandle.cpp:94