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