| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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