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.c_str() );
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().c_str(),
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.c_str(),
654  std::ios_base::out|std::ios_base::trunc );
655  std::fstream db( dbName.c_str(),
656  std::ios_base::out|std::ios_base::trunc );
657 
658  genHeader ( py, db );
659  if (!userModule.empty())
660  py << "from " << userModule << " import *" <<endl;
661  genBody ( py, db );
662  genTrailer( py, db );
663 
664  } //> end loop over libraries
665 
666  dummySvc->release();
667  dummySvc = 0;
668 
669  return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
670 }
671 
672 void configGenerator::genImport( std::ostream& s,
673  const boost::format& frmt,
674  std::string indent = ""){
675 
676  std::string::size_type pos = 0, nxtpos = 0;
677  std::string mod;
678 
679  while ( std::string::npos != pos ){
680  // find end of module name
681  nxtpos = m_configurable["Module"].find_first_of(',',pos);
682 
683  // Prepare import string
684  mod = m_configurable["Module"].substr(pos,nxtpos-pos);
685  std::ostringstream import;
686  import << boost::format(frmt) % mod;
687 
688  // append a normal import or a try/except enclosed one depending
689  // on availability of a fall-back module (next in the list)
690  if ( std::string::npos == nxtpos ) {
691  // last possible module
692  s << indent << import.str() << "\n" << flush;
693  pos = std::string::npos;
694  } else {
695  // we have a fallback for this
696  s << indent << "try:\n"
697  << indent << py_tab << import.str() << "\n"
698  << indent << "except ImportError:\n"
699  << flush;
700  pos = nxtpos+1;
701  }
702  // increase indentation level for next iteration
703  indent += py_tab;
704  }
705 }
706 
707 //-----------------------------------------------------------------------------
708 void configGenerator::genHeader( std::ostream& py,
709  std::ostream& db )
710 //-----------------------------------------------------------------------------
711 {
712  // python file part
713  std::string now = Gaudi::Time::current().format(true);
714  py << "#" << now //<< "\n"
715  << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
716  if ( m_importGaudiHandles ) {
717  py << "from GaudiKernel.GaudiHandles import *\n";
718  }
719 
720  genImport(py,boost::format("from %1%.Configurable import *"));
721 
722  // db file part
723  db << "## -*- ascii -*- \n"
724  << "# db file automatically generated by genconf on: "
725  << now
726  << "\n"
727  << flush;
728 }
729 //-----------------------------------------------------------------------------
730 void configGenerator::genTrailer( std::ostream& /*py*/,
731  std::ostream& db )
732 //-----------------------------------------------------------------------------
733 {
734  // db file part
735  db << "## " << m_pkgName << "\n"
736  << std::flush;
737 }
738 
739 //-----------------------------------------------------------------------------
740 int
741 configGenerator::genComponent( const std::string& libName,
742  const std::string& componentName,
743  const std::string& componentType,
744  const vector<Property*>& properties )
745 //-----------------------------------------------------------------------------
746 {
747  string cname = componentName;
748  pythonizeName(cname);
749 
750  typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t;
751  PropertyDoc_t propDoc;
752 
753  m_pyBuf << "\n";
754  m_pyBuf << "class " << cname
755  << "( " << m_configurable[componentType] << " ) :"
756  << "\n";
757  m_pyBuf << " __slots__ = { \n";
758  for ( vector<Property*>::const_iterator it = properties.begin() ;
759  it != properties.end(); ++it ) {
760 
761  const string pname = (*it)->name();
762  // Validate property name (it must be a valid Python identifier)
763  if (!boost::regex_match(pname, pythonIdentifier)) {
764  std::cout << "ERROR: invalid property name \"" << pname
765  << "\" in component " << cname
766  << " (invalid Python identifier)" << std::endl;
767  // try to make the buffer at least more or less valid python code.
768  m_pyBuf << " #ERROR-invalid identifier '" << pname << "'\n"
769  << " }\n";
770  return 1;
771  }
772 
773  string pvalue, ptype;
774  pythonizeValue( (*it), pvalue, ptype );
775  m_pyBuf << " '" << pname << "' : " << pvalue <<", # " << ptype << "\n";
776 
777  if ( (*it)->documentation() != "none" ) {
778  propDoc[pname] = (*it)->documentation();
779  }
780 
781  }
782  m_pyBuf << " }\n";
783  m_pyBuf << " _propertyDocDct = { \n";
784  for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
785  iProp != propDoc.end();
786  ++iProp ) {
787  m_pyBuf << std::setw(5)
788  << "'" << iProp->first << "' : "
789  << "\"\"\" " << iProp->second << " \"\"\",\n";
790  }
791  m_pyBuf << " }\n";
792 
793  m_pyBuf
794  << " def __init__(self, name = " << m_configurable["DefaultName"]
795  << ", **kwargs):\n"
796  << " super(" << cname << ", self).__init__(name)\n"
797  << " for n,v in kwargs.items():\n"
798  << " setattr(self, n, v)\n"
799  << " def getDlls( self ):\n"
800  << " return '" << libName << "'\n"
801  << " def getType( self ):\n"
802  << " return '" << componentName << "'\n"
803  << " pass # class " << cname << "\n"
804  << flush;
805 
806  // name of the auto-generated module
807  const string pyName = ( fs::path(m_outputDirName) /
808  fs::path(libName+"Conf.py") ).string();
809  const string modName = fs::basename( fs::path( pyName ).leaf() );
810 
811  // now the db part
812  m_dbBuf
813  << m_pkgName << "." << modName << " "
814  << libName << " " << cname
815  << "\n"
816  << flush;
817 
818  return 0;
819 }
820 //-----------------------------------------------------------------------------
821 void configGenerator::pythonizeName( string& name )
822 //-----------------------------------------------------------------------------
823 {
824  static string in("<>&*,: ().");
825  static string out("__rp__s___");
826  boost::algorithm::replace_all(name, ", ", ",");
827  for ( string::iterator i = name.begin(); i != name.end(); ++i ) {
828  if ( in.find(*i) != string::npos ) *i = out[in.find(*i)];
829  }
830 }
831 
832 //-----------------------------------------------------------------------------
834  string& pvalue, string& ptype )
835 //-----------------------------------------------------------------------------
836 {
837  const std::string cvalue = p->toString();
838  const type_info& ti = *p->type_info();
839  if ( ti == typeid(bool) ) {
840  pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" )
841  ? "False"
842  : "True";
843  ptype = "bool";
844  }
845  else if ( ti == typeid(char) || ti == typeid(signed char)
846  || ti == typeid(unsigned char) ||
847  ti == typeid(short) || ti == typeid(unsigned short) ||
848  ti == typeid(int) || ti == typeid(unsigned int) ||
849  ti == typeid(long) || ti == typeid(unsigned long) ) {
850  pvalue = cvalue;
851  ptype = "int";
852  }
853  else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) {
854  pvalue = cvalue + "L";
855  ptype = "long";
856  }
857  else if ( ti == typeid(float) || ti == typeid(double) ) {
858  // forces python to handle this as a float: put a dot in there...
859  pvalue = boost::to_lower_copy(cvalue);
860  if ( pvalue == "nan" ) {
861  pvalue = "float('nan')";
862  std::cout << "WARNING: default value for ["
863  << p->name() << "] is NaN !!"
864  << std::endl;
865  } else if ( std::string::npos == pvalue.find(".") &&
866  std::string::npos == pvalue.find("e") ) {
867  pvalue = cvalue + ".0";
868  }
869  ptype = "float";
870  }
871  else if ( ti == typeid(string) ) {
872 
873  pvalue = "'"+cvalue+"'";
874  ptype = "str";
875  }
876  else if ( ti == typeid(GaudiHandleBase) ) {
877  m_importGaudiHandles = true;
878  const GaudiHandleProperty& hdl
879  = dynamic_cast<const GaudiHandleProperty&>(*p);
880  const GaudiHandleBase& base = hdl.value();
881 
882  pvalue = base.pythonRepr();
883  ptype = "GaudiHandle";
884  }
885  else if ( ti == typeid(GaudiHandleArrayBase) ) {
886  m_importGaudiHandles = true;
887  const GaudiHandleArrayProperty& hdl
888  = dynamic_cast<const GaudiHandleArrayProperty&>(*p);
889  const GaudiHandleArrayBase& base = hdl.value();
890 
891  pvalue = base.pythonRepr();
892  ptype = "GaudiHandleArray";
893  }
894  else {
895  std::ostringstream v_str;
896  v_str.setf(std::ios::fixed); // to correctly display floats
897  p->toStream(v_str);
898  pvalue = v_str.str();
899  ptype = "list";
900  }
901 }
902 
903 #include "GaudiKernel/IMessageSvc.h"
904 //-----------------------------------------------------------------------------
906 //-----------------------------------------------------------------------------
907 {
909  SmartIF<IProperty> propMgr ( iface );
910  SmartIF<IAppMgrUI> appUI ( iface );
911 
912  if ( propMgr.isValid() && appUI.isValid() ) {
913  propMgr->setProperty( "JobOptionsType", "NONE" ); // No job options
914  propMgr->setProperty( "AppName", ""); // No initial printout message
915  propMgr->setProperty( "OutputLevel", "7"); // No other printout messages
916  appUI->configure();
918  msgSvc->setProperty("setWarning", "['DefaultName', 'PropertyMgr']");
919  msgSvc->setProperty("Format", "%T %0W%M");
920  return EXIT_SUCCESS;
921  }
922  else {
923  return EXIT_FAILURE;
924  }
925 }
const GaudiHandleArrayBase & value() const
Definition: Property.h:917
int genConfig(const Strings_t &modules, const string &userModule)
main entry point of this class:
Definition: genconf.cpp:479
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:26
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:47
-*- C++ -*- /////////////////////////////
int genComponent(const std::string &libName, const std::string &componentName, const std::string &componentType, const vector< Property * > &properties)
Definition: genconf.cpp:741
void pythonizeValue(const Property *prop, string &pvalue, string &ptype)
handle the "marshalling" of Properties
Definition: genconf.cpp:833
static Time current(void)
Returns the current time.
Definition: Time.cpp:114
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:821
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:55
void setConfigurableAlgTool(const std::string &cfgAlgTool)
customize the configurable base class for AlgTool component
Definition: genconf.cpp:167
return false
Definition: Bootstrap.cpp:338
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:536
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:226
list options
Definition: gaudirun.py:395
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:19
Definition of the basic interface.
Definition: IInterface.h:160
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:638
virtual const std::string pythonRepr() const
Python representation of handle, i.e.
Definition: GaudiHandle.cpp:56
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:618
void genHeader(std::ostream &pyOut, std::ostream &dbOut)
Definition: genconf.cpp:708
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:20
void setConfigurableAlgorithm(const std::string &cfgAlgorithm)
customize the configurable base class for Algorithm component
Definition: genconf.cpp:161
void reset(TYPE *ptr=0)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:74
void init_logging(boost::log::trivial::severity_level level)
Definition: genconf.cpp:211
Base class of array's of various gaudihandles.
Definition: GaudiHandle.h:303
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:43
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)
bool isValid() const
Allow for check if smart pointer is valid.
Definition: SmartIF.h:51
void genImport(std::ostream &s, const boost::format &frmt, std::string indent)
Definition: genconf.cpp:672
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:23
const GaudiHandleBase & value() const
Definition: Property.h:857
GAUDI_API const std::string getLastErrorString()
Get last system error as string.
Definition: System.cpp:254
string s
Definition: gaudirun.py:244
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:51
void genTrailer(std::ostream &pyOut, std::ostream &dbOut)
Definition: genconf.cpp:730
Base class to handles to be used in lieu of naked pointers to various Gaudi components.
Definition: GaudiHandle.h:80
virtual StatusCode configure()=0
Configure the job.
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:31
list i
Definition: ana.py:128
int createAppMgr()
Definition: genconf.cpp:905
The IAuditor is the interface implmented by the AlgAuditor base class.
Definition: IAuditor.h:18
virtual const std::string pythonRepr() const
Python representation of array of handles, i.e.
Definition: GaudiHandle.cpp:99
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:133
string type
Definition: gaudirun.py:151
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition: Time.cpp:280
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