| The Gaudi Framework v29r0 (ff2e7097)

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

- File List
- File Members

Configurable.py
Go to the documentation of this file.
1 # File: AthenaCommon/python/Configurable.py
2 # Author: Wim Lavrijsen (WLavrijsen@lbl.gov)
3 # Author: Martin Woudstra (Martin.Woudstra@cern.ch)
4
5 import copy
6 import string
7 import types
8 import os
9 import sys
10 from inspect import isclass
11 import GaudiKernel.ConfigurableMeta as ConfigurableMeta
12 from GaudiKernel.Constants import error_explanation, \
13 VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL
14 from GaudiKernel.PropertyProxy import PropertyProxy
15 from GaudiKernel.GaudiHandles import *
16 from GaudiKernel.DataObjectHandleBase import *
17
18 from GaudiConfig.ControlFlow import (OrNode, AndNode, OrderedNode,
19 ignore, InvertNode,
20 ControlFlowLeaf, ControlFlowNode,
21 CFTrue, CFFalse)
22
23 # data ---------------------------------------------------------------------
24 __all__ = ['Configurable',
25 'ConfigurableAlgorithm',
26 'ConfigurableAlgTool',
27 'ConfigurableAuditor',
28 'ConfigurableService',
29 'ConfigurableUser',
30 'VERBOSE', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL',
31 'appendPostConfigAction', 'removePostConfigAction']
32
33 # for messaging
34 import logging
35 log = logging.getLogger('Configurable')
36
37
38 def expandvars(data):
39 """
40 Expand environment variables "data".
41 Data can be string, list, tuple and dictionary. For collection, all the
42 contained strings will be manipulated (recursively).
43 """
44 import os.path
45 typ = type(data)
46 if typ is str:
47 return os.path.expandvars(data)
48 elif typ in [list, tuple]:
49 collect = []
50 for i in data:
51 collect.append(expandvars(i))
52 return typ(collect)
53 elif typ is dict:
54 collect = {}
55 for k in data:
56 collect[expandvars(k)] = expandvars(data[k])
57 return collect
58 return data
59
60
61 class Error(RuntimeError):
62 """
63 Error occurred in the configuration process.
64 """
65 pass
66
67 # Allow references to options as in old style
68
69
70 class PropertyReference(object):
71 def __init__(self, propname):
72 self.name = propname
73
74 def __str__(self):
75 return "@%s" % self.name
76
77 def __resolve__(self):
78 # late binding for property references
79 retval = None
80 refname, refprop = self.name.rsplit('.', 1)
81 if refname in Configurable.allConfigurables:
82 conf = Configurable.allConfigurables[refname]
83 retval = getattr(conf, refprop)
84 if hasattr(retval, "getFullName"):
85 retval = retval.getFullName()
86 else:
87 raise NameError("name '%s' not found resolving '%s'" %
88 (refname, self))
89 return retval
90
91 def getFullName(self):
92 """This function allow transparent integration with
93 Configurable.getValuedProperties.
94 """
95 try:
96 return self.__resolve__()
97 except NameError:
98 # ignore the error if we cannot resolve the name yet
99 return self
100 except AttributeError:
101 # ignore the error if we cannot resolve the attribute yet
102 return self
103
104 # base class for configurable Gaudi algorithms/services/algtools/etc. ======
105
106
107 class Configurable(object):
108 """Base class for Gaudi components that implement the IProperty interface.
109 Provides most of the boilerplate code, but the actual useful classes
110 are its derived ConfigurableAlgorithm, ConfigurableService, and
111 ConfigurableAlgTool."""
112
113 # for detecting the default name
114 class DefaultName:
115 pass
116
117 propertyNoValue = '<no value>'
118 indentUnit = '| '
119 printHeaderWidth = 100
120 printHeaderPre = 5
121
122 __metaclass__ = ConfigurableMeta.ConfigurableMeta
123
124 __slots__ = (
125 '__children', # controlled components, e.g. private AlgTools
126 '__tools', # private AlgTools (#PM-->)
127 '_name', # the (unqualified) component name
128 '_inSetDefaults', # currently setting default values
129 '_initok', # used to enforce base class init
130 '_setupok' # for debugging purposes (temporary)
131 )
132
133 allConfigurables = {} # just names would do, but currently refs to the actual
134 configurableServices = {} # just names would do, but currently refs to the actual
135 # configurables is needed for (temporary) backwards
136 # compatibility; will change in the future
137 _configurationLocked = False
138
139 def __new__(cls, *args, **kwargs):
140 """To Gaudi, any object with the same type/name is the same object. Hence,
141 this is mimicked in the configuration: instantiating a new Configurable
142 of a type with the same name will return the same instance."""
143
144 global log
145 # try to get the name of the Configurable (having a name is compulsory)
146 if 'name' in kwargs:
147 # simple keyword (by far the easiest)
148 name = kwargs['name']
149 elif 'name' in cls.__init__.func_code.co_varnames:
150 # either positional in args, or default
151 index = list(cls.__init__.func_code.co_varnames).index('name')
152 try:
153 # var names index is offset by one as __init__ is to be called with self
154 name = args[index - 1]
155 except IndexError:
156 # retrieve default value, then
157 name = cls.__init__.func_defaults[index - (len(args) + 1)]
158 else:
159 # positional index is assumed (will work most of the time)
160 try:
161 name = args[1] # '0' is for self
162 except (IndexError, TypeError):
163 raise TypeError(
164 'no "name" argument while instantiating "%s"' % cls.__name__)
165
166 argname = name
167 if name == Configurable.DefaultName:
168 if hasattr(cls, 'DefaultedName'):
169 name = cls.DefaultedName
170 else:
171 name = cls.getType()
172 elif not name or type(name) != str:
173 # unnamed, highly specialized user code, etc. ... unacceptable
174 raise TypeError(
175 'could not retrieve name from %s.__init__ arguments' % cls.__name__)
176
177 # Handle the case of global tools to prepend ToolSvc in the name.
178 # This is needed for compatibility with old JobOptions files being read
179 if issubclass(cls, ConfigurableAlgTool) and '.' not in name:
180 name = 'ToolSvc.' + name
181
182 # close backdoor access to otherwise private subalgs/tools
183 # PM if 0 <= name.find( '.' ):
184 # PM # temp protection for old style types
185 # PM from OldStyleConfig import GenericConfigurable
186 # PM if not issubclass( cls, GenericConfigurable ): # except raised for new types only
187 # PM raise NameError( '"%s": backdoor access to private configurables not allowed' % name )
188
189 # ordinary recycle case
190 if name in cls.configurables:
191 conf = cls.configurables[name]
192 if name != argname: # special case: user derived <-> real ... make same
193 cls.configurables[conf.getType()] = conf
194 #---PM: Initialize additional properties
195 for n, v in kwargs.items():
196 if n != "name": # it should not be confused with a normal property
197 setattr(conf, n, v)
198 if not cls._configurationLocked and not "_enabled" in kwargs and isinstance(conf, ConfigurableUser):
199 # Ensure that the ConfigurableUser gets enabled if nothing is
200 # specified in the constructor.
201 setattr(conf, "_enabled", True)
202 return conf
203
204 # a couple of special cases (note that these cases don't mix)
205 spos = name.find('/')
206 ti_name = None
207 if spos < 0:
208 ti_name = "%s/%s" % (name, name)
209 if ti_name in cls.configurables:
210 # support for old-style name as type/name lookup where name==type
211 return cls.configurables[ti_name]
212
213 i_name = None
214 if spos > 0:
215 i_name = name[:spos]
216 if i_name == name[spos + 1:] and i_name in cls.configurables:
217 # this is the opposite of the above special case
218 return cls.configurables[i_name]
219
220 # the following is purely for debugging support and should realistically bomb
221 conf = cls.allConfigurables.get(name, None) or\
222 (spos < 0 and cls.allConfigurables.get(ti_name, None)) or\
223 (spos > 0 and i_name == name[spos + 1:]
224 and cls.allConfigurables.get(i_name, None))
225 if conf: # wrong type used?
226 if conf.__class__ is ConfigurableGeneric:
227 # If the instance found is ConfigurableGeneric then
228 # we create a new one with the proper type and fill with
229 # the contents of the generic one
230 newconf = object.__new__(cls)
231 cls.__init__(newconf, *args, **kwargs)
232 # initialize with the properties of generic configurable
233 # (we map the names of the properties to lowercase versions because
234 # old options are not case sensitive)
235 names = {}
236 for n in newconf.__slots__:
237 names[n.lower()] = n
238 for n in conf._properties:
239 if names[n.lower()] != n:
240 log.warning("Option '%s' was used for %s, but the correct spelling is '%s'" % (
241 n, name, names[n.lower()]))
242 setattr(newconf, names[n.lower()], getattr(conf, n))
243 for n, v in kwargs.items():
244 setattr(newconf, n, v)
245 cls.configurables[name] = newconf
246 cls.allConfigurables[name] = newconf
247 return newconf
248 else:
249 # will be an actual error in the future (now only report as such)
250 log.error('attempt to redefine type of "%s" (was: %s, new: %s)%s',
251 name, conf.__class__.__name__, cls.__name__, error_explanation)
252 # in the future:
253 # return None # will bomb on use (or go unharmed on non-use)
254 # for now, allow use through allConfigurables lookup
255 #---PM: Initialize additional properties
256 for n, v in kwargs.items():
257 setattr(conf, n, v)
258 return conf
259
260 # still here: create a new instance and initialize it
261 conf = object.__new__(cls)
262 cls.__init__(conf, *args, **kwargs)
263
264 # update normal, per-class cache
265 cls.configurables[name] = conf
266
267 for base in cls.__bases__:
268 if base.__name__ == 'ConfigurableService':
269 cls.configurableServices[name] = conf
270
271 # update generics super-cache, if needed
272 cls.allConfigurables[name] = conf
273 #-->PM#if hasattr( cls, 'getType' ) and name.find('/') < 0:
274 #-->PM# cls.allConfigurables[ cls.getType() + '/' + name ] = conf
275
276 return conf
277
278 def __init__(self, name=DefaultName):
279 # check class readiness, all required overloads should be there now
280 klass = self.__class__
281
282 # this is an abstract class
283 if klass == Configurable:
284 raise TypeError, "%s is an ABC and can not be instantiated" % str(
285 Configurable)
286
287 # the following methods require overloading
288 # NOT YET meths = { 'getServices' : 1, # retrieve list of services to configure
289 meths = {'getDlls': 1, # provide list of Dlls to load
290 'getGaudiType': 1, # return string describing component class
291 'getHandle': 1} # provide access to C++ side component instance
292 # 'getType' : 1 } # return the type of the actual C++ component
293
294 for meth, nArgs in meths.items():
295 try:
296 f = getattr(klass, meth).im_func
297 except AttributeError:
298 raise NotImplementedError, "%s is missing in class %s" % (
299 meth, str(klass))
300
301 # in addition, verify the number of arguments w/o defaults
302 nargcount = f.func_code.co_argcount
303 ndefaults = f.func_defaults and len(f.func_defaults) or 0
304 if not nargcount - ndefaults <= nArgs <= nargcount:
305 raise TypeError, "%s.%s requires exactly %d arguments" % (
306 klass, meth, nArgs)
307
308 # for using this Configurable as a (Gaudi) sequence
309 self.__children = []
310 self.__tools = {}
311
312 # know who we are
313 if name == Configurable.DefaultName:
314 if hasattr(self.__class__, 'DefaultedName'):
315 self._name = self.__class__.DefaultedName
316 else:
317 self._name = self.getType()
318 else:
319 self._name = name
320
321 # set to True when collecting defaults, False otherwise
322 self._inSetDefaults = False
323
324 # for later, in case __init__ itself is overridden
325 self._initok = True
326
327 # for debugging purposes (temporary)
328 self._setupok = False
329
330 # pickle support
331 def __getstate__(self):
332 dict = {}
333 for name, proxy in self._properties.items():
334 try:
335 dict[name] = proxy.__get__(self)
336 except AttributeError:
337 pass
338
339 dict['_Configurable__children'] = self.__children
340 dict['_Configurable__tools'] = self.__tools
341 dict['_name'] = self._name
342 return dict
343
344 def __getnewargs__(self):
345 return (self._name,)
346
347 def __setstate__(self, dict):
348 self._initok = True
349 for n, v in dict.items():
350 setattr(self, n, v)
351 return
352
353 # to allow a few basic sanity checks, as well as nice syntax
354 def __len__(self):
355 return len(self.__children)
356
357 def __iter__(self):
358 return iter(self.__children)
359
360 # ownership rules of self through copying
361 def __deepcopy__(self, memo):
362 newconf = object.__new__(self.__class__)
363 self.__class__.__init__(newconf, self.getName())
364
365 for proxy in self._properties.values():
366 try:
367 proxy.__set__(newconf, proxy.__get__(self))
368 except AttributeError:
369 pass # means property was not set for self
370
371 for c in self.__children:
372 newconf += c # processes proper copy semantics
373
374 return newconf
375
376 # hierarchy building, and ownership rules of children
377 def __iadd__(self, configs, descr=None):
378 if not type(configs) in (list, tuple):
379 configs = (configs, )
380
381 joname = self.getJobOptName()
382
383 for cfg in configs:
384 # prevent type mismatches
385 if not isinstance(cfg, Configurable):
386 raise TypeError("'%s' is not a Configurable" % str(cfg))
387
388 cc = self.copyChildAndSetParent(cfg, joname)
389
390 # filters dupes; usually "ok" (backdoor should catch them)
391 ccjo = cc.getJobOptName()
392 for c in self.__children:
393 if c.getJobOptName() == ccjo:
394 log.error(
395 'attempt to add a duplicate ... dupe ignored%s', error_explanation)
396 break
397 else:
398 self.__children.append(cc)
399
400 try:
401 if descr: # support for tool properties
402 descr.__set__(self, cc)
403 else:
404 setattr(self, cc.getName(), cc)
405 except AttributeError:
406 pass # to allow free addition of tools/subalgorithms
407
408 return self
409
410 def __getattr__(self, attr): # until ToolProperties exist ...
411
412 if attr in self.__tools:
413 return self.__tools[attr]
414
415 if attr in self._properties:
416 if isinstance(self._properties[attr].__get__(self), DataObjectHandleBase):
417 return self._properties[attr].__get__(self)
418
419 for c in self.__children:
420 if c.getName() == attr:
421 return c
422
423 raise AttributeError(
424 "'%s' object has no attribute '%s'" % (self.__class__, attr))
425
426 def __setattr__(self, name, value):
427 if self._configurationLocked:
428 raise RuntimeError(
429 "%s: Configuration cannot be modified after the ApplicationMgr has been started." % self.name())
430 try:
431 super(Configurable, self).__setattr__(name, value)
432 except AttributeError:
433 raise AttributeError("Configurable '%s' does not have property '%s'."
434 % (self.__class__.__name__, name))
435
436 def __delattr__(self, attr):
437 # remove as property, otherwise try as child
438 try:
439 # remove history etc., then reset to default (in case set before)
440 prop = self._properties[attr]
441 prop.__delete__(self)
442 prop.__set__(self, prop.default)
443 return # reaches here? was property: done now
444 except KeyError:
445 pass
446 # otherwise, remove the private tool
447 if attr in self.__tools:
448 del self.__tools[attr]
449
450 # otherwise, remove child, if one is so named
451 for c in self.__children:
452 if c.getName() == attr:
453 self.__children.remove(c)
454
455 # potentially, there are left over caches (certain user derived classes)
456 try:
457 del self.__dict__[attr]
458 except (AttributeError, KeyError):
459 pass
460
461 def __nonzero__(self):
462 return True
463
464 def remove(self, items):
465 if type(items) != list and type(items) != tuple:
466 items = [items]
467
468 self.__children = [e for e in self.__children if not e in items]
469
470 def removeAll(self):
471 self.remove(self.__children)
472
473 # called by __iadd__; determines child copy semantics
474 def copyChild(self, child):
475 return copy.deepcopy(child)
476
477 def setParent(self, parentName):
478 pass
479
480 def getParent(self):
481 return ""
482
483 def hasParent(self, parent):
484 return False
485
486 def copyChildAndSetParent(self, cfg, parent):
487 cc = self.copyChild(cfg)
488
489 if hasattr(cc, 'setParent') and parent:
490 try:
491 cc.setParent(parent)
492 except RuntimeError, e:
493 # temporary backdoor resolution for compatibility
494 log.error(str(e) + '%s', error_explanation)
495 ccbd = cc.configurables[cc.getJobOptName()]
496
497 # merge properties, new over pre-existing
498 for proxy in self._properties.values():
499 if proxy.history.has_key(cc):
500 proxy.__set__(ccbd, proxy.__get__(cc))
501
502 # consolidate
503 cc = ccbd
504 return cc
505
506 def getChildren(self):
507 return self.__children[:] # read only
508
509 def getTools(self):
510 return self.__tools.values() # read only
511
512 def children(self):
513 log.error(
514 "children() is deprecated, use getChildren() instead for consistency")
515 log.error("getChildren() returns a copy; to add a child, use 'parent += child'%s",
516 error_explanation)
517 return self.__children # by ref, for compatibility
518
519 def getAllChildren(self):
520 """Get all (private) configurable children, both explicit ones (added with +=)
521 and the ones in the private GaudiHandle properties"""
522 childs = []
523 # add private configurable properties (also inside handles)
524 for proxy in self._properties.values():
525 try:
526 c = proxy.__get__(self)
527 except AttributeError:
528 pass
529 else:
530 if isinstance(c, Configurable) and not c.isPublic():
531 childs.append(c)
532 elif isinstance(c, GaudiHandle):
533 try:
534 conf = c.configurable
535 except AttributeError:
536 pass
537 else:
538 if not conf.isPublic():
539 childs.append(conf)
540 elif isinstance(c, GaudiHandleArray):
541 # only setup private arrays
542 if not c.isPublic():
543 for ci in c:
544 if isinstance(ci, Configurable):
545 childs.append(ci)
546 else:
547 try:
548 conf = ci.configurable
549 except AttributeError:
550 pass
551 else:
552 childs.append(conf)
553
554 # add explicit children
555 childs += self.__children
556 return childs
557
558 def getSequence(self):
559 elems = []
560 for c in self.__children:
561 elems.append(c.getFullName())
562 return elems
563
564 def setup(self):
565 # make sure base class init has been called
566 if not hasattr(self, '_initok') or not self._initok:
567 # could check more, but this is the only explanation
568 raise TypeError, \
569 "Configurable.__init__ not called in %s override" % self.__class__.__name__
570
571 # log.debug("calling setup() on " + self.getFullJobOptName())
572
573 # setup self: this collects all values on the python side
574 self.__setupServices()
575 self.__setupDlls()
576 self.__setupDefaults()
577
578 # setup children
579 for c in self.getAllChildren():
580 c.setup()
581
582 # now get handle to work with for moving properties into the catalogue
583 handle = self.getHandle()
584 if not handle:
585 log.debug('no handle for %s: not transporting properties', self._name)
586 return # allowed, done early
587
588 # pass final set of properties on to handle on the C++ side or JobOptSvc
589 for name in self._properties.keys():
590 if hasattr(self, name): # means property has python-side value/default
591 setattr(handle, name, getattr(self, name))
592
593 # for debugging purposes
594 self._setupok = True
595
596 def getProperties(self):
597 props = {}
598 for name, proxy in self._properties.items():
599 try:
600 props[name] = proxy.__get__(self)
601 except AttributeError:
602 props[name] = Configurable.propertyNoValue
603
604 return props
605
606 def getPropertiesWithDescription(self):
607 """Get all properties with their description string as { name : (value, desc) }."""
608 props = {}
609 for name, proxy in self._properties.items():
610 try:
611 props[name] = (proxy.__get__(self), proxy.__doc__)
612 except AttributeError:
613 props[name] = (Configurable.propertyNoValue, proxy.__doc__)
614 return props
615
616 def getValuedProperties(self):
617 props = {}
618 for name, proxy in self._properties.items():
619 if self.isPropertySet(name):
620 value = proxy.__get__(self)
621 if hasattr(value, 'getFullName'):
622 value = value.getFullName()
623 elif type(value) in [list, tuple]:
624 new_value = []
625 for i in value:
626 if hasattr(i, 'getFullName'):
627 new_value.append(i.getFullName())
628 else:
629 new_value.append(i)
630 value = type(value)(new_value)
631 elif type(value) is dict:
632 new_value = {}
633 for i in value:
634 if hasattr(value[i], 'getFullName'):
635 new_value[i] = value[i].getFullName()
636 else:
637 new_value[i] = value[i]
638 value = new_value
639 props[name] = value
640
641 return props
642
643 def properties(self):
644 return self.getProperties() # compatibility
645
646 @classmethod
647 def getDefaultProperties(cls):
648 class collector:
649 pass
650
651 # user provided defaults
652 c = collector()
653 cls.setDefaults(c)
654
655 # defaults from C++
656 for k, v in cls._properties.items():
657 if not k in c.__dict__ and hasattr(v, 'default'):
658 c.__dict__[k] = v.default
659
660 return c.__dict__
661
662 @classmethod
663 def getDefaultProperty(cls, name):
664 class collector:
665 pass
666
667 # user provided defaults
668 c = collector()
669 cls.setDefaults(c)
670
671 if name in c.__dict__:
672 return c.__dict__[name]
673
674 # defaults from C++
675 try:
676 v = cls._properties[name]
677 if hasattr(v, 'default'):
678 return v.default
679 except KeyError:
680 pass
681
682 return None
683
684 def getProp(self, name):
685 """Returns the value of the given property.
686 """
687 if hasattr(self, name):
688 return getattr(self, name)
689 else:
690 return self.getDefaultProperties()[name]
691
692 def setProp(self, name, value):
693 """Set the value of a given property
694 """
695 return setattr(self, name, value)
696
697 def isPropertySet(self, name):
698 """Tell if the property 'name' has been set or not.
699
700 Because of a problem with list and dictionary properties, in those cases
701 if the value is equal to the default, the property is considered as not
702 set.
703 """
704 if not hasattr(self, name):
705 return False
706 default = self.getDefaultProperty(name)
707 if isinstance(default, (list, dict, DataObjectHandleBase)):
708 value = getattr(self, name)
709 return value != default
710 return True
711
712 def getType(cls):
713 return cls.__name__
714
715 def getName(self):
716 return self._name
717
718 def name(self):
719 return self.getName()
720
721 def getJobOptName(self): # full hierachical name
722 return self.getName()
723
724 def isPublic(self):
725 return True
726
727 # for a couple of existing uses out there
728 def jobOptName(self):
729 log.error("jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
730 error_explanation)
731 return self.getJobOptName() # compatibility
732
733 def getFullName(self):
734 return str(self.getType() + '/' + self.getName())
735
736 def getFullJobOptName(self):
737 return "%s/%s" % (self.getType(), self.getJobOptName() or self.getName())
738
739 def getPrintTitle(self):
740 return self.getGaudiType() + ' ' + self.getTitleName()
741
742 def getTitleName(self):
743 if log.isEnabledFor(logging.DEBUG):
744 return self.getFullJobOptName()
745 else:
746 return self.getFullName()
747
748 def setDefaults(cls, handle):
749 pass
750
751 def clone(self, name=None, **kwargs):
752 if not name:
753 if hasattr(self, 'DefaultedName'):
754 name = self.DefaultedName
755 else:
756 name = self.getType()
757
758 newconf = Configurable.__new__(self.__class__, name)
759 self.__class__.__init__(newconf, name)
760
761 for proxy in self._properties.values():
762 try:
763 value = proxy.__get__(self)
764 if type(value) in [str, list, dict, tuple]:
765 # clone the values of the properties for basic types
766 value = type(value)(value)
767 proxy.__set__(newconf, value)
768 except AttributeError:
769 pass
770
771 for c in self.__children:
772 newconf += c # processes proper copy semantics
773
774 for n, t in self.__tools.items():
775 newconf.addTool(t, n)
776
777 for name, value in kwargs.items():
778 setattr(newconf, name, value)
779
780 return newconf
781
782 def splitName(self):
783 fullname = self.getName()
784 dot = fullname.find('.')
785 if dot != -1:
786 parentname = fullname[:dot]
787 longname = fullname[dot + 1:]
788 else:
789 parentname = ''
790 longname = fullname
791 dot = longname.find('.')
792 if dot != -1:
793 name = longname[:dot]
794 else:
795 name = longname
796 return parentname, name, longname
797
798 def addTool(self, tool, name=None):
799 if isclass(tool) and issubclass(tool, ConfigurableAlgTool):
800 if name is None:
801 name = tool.__name__
802 priv_tool = tool(self.getName() + '.' + name)
803 elif isinstance(tool, ConfigurableAlgTool):
804 if name is None:
805 name = tool.splitName()[1]
806 priv_tool = tool.clone(self.getName() + '.' + name)
807 else:
808 if isclass(tool):
809 classname = tool.__name__
810 else:
811 classname = type(tool).__name__
812 raise TypeError, "addTool requires AlgTool configurable. Got %s type" % classname
813 self.__tools[name] = priv_tool
814 if name in self.__slots__:
815 # this is to avoid that the property hides the tool
816 setattr(self, name, self.__tools[name])
817 return self.__tools[name]
818
819 def _isInSetDefaults(self):
820 return self._inSetDefaults
821
822 def __setupServices(self):
823 #svcs = self.getServices()
824 # if not svcs:
825 svcs = []
826 # elif type(svcs) == types.StringType:
827 # svcs = [ svcs ]
828
829 import __main__
830 for svc in svcs:
831 handle = __main__.Service(svc)
832 # services should be configurables as well, but aren't for now
833 # handle.setup()
834
835 # allow Configurable to make some changes
836 if hasattr(self, 'configure' + svc):
837 eval('self.configure' + svc + '( handle )')
838
839 def __setupDlls(self):
840 dlls = self.getDlls()
841 if not dlls:
842 dlls = []
843 elif type(dlls) == types.StringType:
844 dlls = [dlls]
845
846 from __main__ import theApp
847 dlls = filter(lambda d: d not in theApp.Dlls, dlls)
848 if dlls:
849 theApp.Dlls += dlls
850
851 def __setupDefaults(self):
852 # set handle defaults flags to inform __setattr__ that it is being
853 # called during setDefaults of the concrete Configurable
854 self._inSetDefaults = True
855 self.setDefaults(self)
856 self._inSetDefaults = False
857
858 @staticmethod
859 def _printHeader(indentStr, title):
860 preLen = Configurable.printHeaderPre
861 postLen = Configurable.printHeaderWidth - \
862 preLen - 3 - len(title) # - len(indentStr)
863 postLen = max(preLen, postLen)
864 return indentStr + '/%s %s %s' % (preLen * '*', title, postLen * '*')
865
866 @staticmethod
867 def _printFooter(indentStr, title):
868 preLen = Configurable.printHeaderPre
869 postLen = Configurable.printHeaderWidth - \
870 preLen - 12 - len(title) # - len(indentStr)
871 postLen = max(preLen, postLen)
872 return indentStr + '\\%s (End of %s) %s' % (preLen * '-', title, postLen * '-')
873
874 def __repr__(self):
875 return '{0}({1!r})'.format(self.__class__.__name__, self.name())
876
877 def __str__(self, indent=0, headerLastIndentUnit=indentUnit):
878 global log # to print some info depending on output level
879 indentStr = indent * Configurable.indentUnit
880 # print header
881 title = self.getPrintTitle()
882 # print line to easily see start-of-configurable
883 if indent > 0:
884 headerIndent = (indent - 1) * \
885 Configurable.indentUnit + headerLastIndentUnit
886 else:
887 headerIndent = ''
888 rep = Configurable._printHeader(headerIndent, title)
889 rep += os.linesep
890 # print own properties
891 props = self.getProperties()
892 defs = self.getDefaultProperties()
893 if not props:
894 rep += indentStr + '|-<no properties>' + os.linesep
895 else:
896 # get property name with
897 nameWidth = 0
898 for p in props.keys():
899 nameWidth = max(nameWidth, len(p))
900 for p, v in props.items():
901 # start with indent and property name
902 prefix = indentStr + '|-%-*s' % (nameWidth, p)
903 # add memory address for debugging (not for defaults)
904 if log.isEnabledFor(logging.DEBUG):
905 if v != Configurable.propertyNoValue:
906 address = ' @%11s' % hex(id(v))
907 else:
908 address = 13 * ' '
909 prefix += address
910 # add value and default
911 default = defs.get(p)
912 if v == Configurable.propertyNoValue:
913 # show default value as value, and no extra 'default'
914 strVal = repr(default)
915 strDef = None
916 else:
917 # convert configurable to handle
918 if hasattr(v, "getGaudiHandle"):
919 vv = v.getGaudiHandle()
920 else:
921 vv = v
922 if isinstance(vv, GaudiHandle) or isinstance(vv, GaudiHandleArray):
923 strVal = repr(vv)
924 # the default may not be a GaudiHandle (?)
925 if hasattr(default, "toStringProperty"):
926 strDef = repr(default.toStringProperty())
927 else:
928 strDef = repr(default)
929 if strDef == repr(vv.toStringProperty()):
930 strDef = None
931 else:
932 strVal = repr(vv)
933 strDef = repr(default)
934 # add the value
935 line = prefix + ' = ' + strVal
936 # add default if present
937 if strDef is not None:
938 # put default on new line if too big
939 if len(line) + len(strDef) > Configurable.printHeaderWidth:
940 line += os.linesep + indentStr + '| ' + \
941 (len(prefix) - len(indentStr) - 3) * ' '
942 line += ' (default: %s)' % (strDef,)
943 # add the line to the total string
944 rep += line + os.linesep
945 # print out full private configurables
946 # if isinstance(v,Configurable) and not v.isPublic():
947 ## rep += v.__str__( indent + 1 ) + os.linesep
948 # elif isinstance(v,GaudiHandleArray):
949 # for vi in v:
950 # if isinstance(vi,Configurable) and not vi.isPublic():
951 ## rep += vi.__str__( indent + 1 ) + os.linesep
952
953 # print configurables + their properties, or loop over sequence
954 # for cfg in self.__children:
955 for cfg in self.getAllChildren():
956 rep += cfg.__str__(indent + 1, '|=') + os.linesep
957
958 # print line to easily see end-of-configurable. Note: No linesep!
959 rep += Configurable._printFooter(indentStr, title)
960 return rep
961
962 def isApplicable(self):
963 '''
964 Return True is the instance can be "applied".
965 Always False for plain Configurable instances
966 (i.e. not ConfigurableUser).
967 '''
968 return False
969
970 # classes for generic Gaudi component ===========
971
972
973 class DummyDescriptor(object):
974 def __init__(self, name):
975 self.__name__ = name # conventional
976
977 def __get__(self, obj, type=None):
978 return getattr(obj, self.__name__)
979
980 def __set__(self, obj, value):
981 object.__setattr__(obj, self.__name__, value)
982
983
984 class ConfigurableGeneric(Configurable):
985 #__slots__ = { }
986
987 def __init__(self, name=Configurable.DefaultName):
988 Configurable.__init__(self, name)
989 self._name = name
990 self._properties = {}
991
992 def __deepcopy__(self, memo):
993 return self # algorithms are always shared
994
995 def getGaudiType(self): return 'GenericComponent'
996
997 def getDlls(self): pass
998
999 def getHandle(self): pass
1000
1001 def __setattr__(self, name, value):
1002 # filter private (user) variables
1003 if name[0] == '_':
1004 super(ConfigurableGeneric, self).__setattr__(name, value)
1005 return
1006
1007 # filter configurable types
1008 if isinstance(value, Configurable):
1009 self.__dict__[name] = value
1010 return
1011
1012 # assume all the rest are properties
1013 if not name in self._properties:
1014 self._properties[name] = PropertyProxy(DummyDescriptor(name))
1015 self._properties[name].__set__(self, value)
1016
1017 def getJobOptName(self): return None
1018
1019
1020 # base classes for individual Gaudi algorithms/services/algtools ===========
1021 class ConfigurableAlgorithm(Configurable):
1022 __slots__ = {'_jobOptName': 0, 'OutputLevel': 0,
1023 'Enable': 1, 'ErrorMax': 1, 'ErrorCount': 0, 'AuditAlgorithms': 0,
1024 'AuditInitialize': 0, 'AuditReinitialize': 0, 'AuditExecute': 0,
1025 'AuditFinalize': 0, 'AuditBeginRun': 0, 'AuditEndRun': 0}
1026
1027 def __init__(self, name=Configurable.DefaultName):
1028 super(ConfigurableAlgorithm, self).__init__(name)
1029 name = self.getName()
1030 self._jobOptName = name[name.find('/') + 1:] # strips class
1031
1032 def __deepcopy__(self, memo):
1033 return self # algorithms are always shared
1034
1035 def getHandle(self):
1036 return iAlgorithm(self.getJobOptName())
1037
1038 def getGaudiType(self):
1039 return 'Algorithm'
1040
1041 def getJobOptName(self):
1042 return self._jobOptName
1043
1044 # mimick the ControlFlowLeaf interface
1045 def __and__(self, rhs):
1046 if rhs is CFTrue:
1047 return self
1048 elif rhs is CFFalse:
1049 return CFFalse
1050 return AndNode(self, rhs)
1051
1052 def __or__(self, rhs):
1053 if rhs is CFFalse:
1054 return self
1055 elif rhs is CFTrue:
1056 return CFTrue
1057 return OrNode(self, rhs)
1058
1059 def __invert__(self):
1060 return InvertNode(self)
1061
1062 def __rshift__(self, rhs):
1063 return OrderedNode(self, rhs)
1064
1065 def visitNode(self, visitor):
1066 visitor.enter(self)
1067 self._visitSubNodes(visitor)
1068 visitor.leave(self)
1069
1070 def _visitSubNodes(self, visitor):
1071 pass
1072
1073 def __eq__(self, other):
1074 return (repr(self) == repr(other))
1075
1076
1077 class ConfigurableService(Configurable):
1078 __slots__ = {'OutputLevel': 0,
1079 'AuditServices': 0, 'AuditInitialize': 0, 'AuditFinalize': 0}
1080
1081 def __deepcopy__(self, memo):
1082 return self # services are always shared
1083
1084 def copyChild(self, child):
1085 return child # full sharing
1086
1087 def getHandle(self):
1088 return iService(self._name)
1089
1090 def getGaudiType(self):
1091 return 'Service'
1092
1093 def getGaudiHandle(self):
1094 return ServiceHandle(self.toStringProperty())
1095
1096 def toStringProperty(self):
1097 # called on conversion to a string property for the jocat
1098 return self.getName()
1099
1100
1101 class ConfigurableAlgTool(Configurable):
1102 __slots__ = {'_jobOptName': '', 'OutputLevel': 0,
1103 'AuditTools': 0, 'AuditInitialize': 0, 'AuditFinalize': 0}
1104
1105 def __init__(self, name=Configurable.DefaultName):
1106 super(ConfigurableAlgTool, self).__init__(name)
1107 if '.' not in self._name:
1108 # Public tools must have ToolSvc as parent
1109 self._name = "ToolSvc." + self._name
1110 name = self.getName()
1111 name = name[name.find('/') + 1:] # strips class, if any
1112 self._jobOptName = name
1113
1114 def getHandle(self):
1115 # iAlgTool isn't useful, unless one knows for sure that the tool exists
1116 return iProperty(self.getJobOptName())
1117
1118 def getGaudiType(self):
1119 return 'AlgTool'
1120
1121 def getGaudiHandle(self):
1122 if self.isPublic():
1123 return PublicToolHandle(self.toStringProperty())
1124 else:
1125 return PrivateToolHandle(self.toStringProperty())
1126
1127 def getPrintTitle(self):
1128 if self.isPublic():
1129 pop = 'Public '
1130 else:
1131 pop = 'Private '
1132 return pop + Configurable.getPrintTitle(self)
1133
1134 def setParent(self, parentName):
1135 # print "ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName)
1136 # print "Calling stack:"
1137 # import traceback
1138 # traceback.print_stack()
1139 # propagate parent to AlgTools in children
1140 for c in self.getAllChildren():
1141 if isinstance(c, ConfigurableAlgTool):
1142 c.setParent(parentName)
1143
1144 # update my own parent
1145 name = self.getName()
1146 name = name[name.rfind('.') + 1:] # Name of the instance
1147 self._jobOptName = self._name = parentName + '.' + name
1148
1149 def getParent(self):
1150 dot = self._jobOptName.rfind('.')
1151 if dot != -1:
1152 return self._jobOptName[:dot]
1153 else:
1154 return ""
1155
1156 def hasParent(self, parent):
1157 return self._jobOptName.startswith(parent + '.')
1158
1159 def getJobOptName(self):
1160 return self._jobOptName
1161
1162 def isPublic(self):
1163 return self.isInToolSvc()
1164
1165 def isInToolSvc(self):
1166 return self._jobOptName.startswith('ToolSvc.')
1167
1168 def toStringProperty(self):
1169 # called on conversion to a string property for the jocat
1170 return self.getFullName()
1171
1172 def getFullName(self):
1173 # for Tools, the "full name" means "Type/LocalName",
1174 # without the names of the parents
1175 name = self.getName()
1176 # strip off everything before the last '.'
1177 name = name[name.rfind('.') + 1:]
1178 return str(self.getType() + '/' + name)
1179
1180
1181 # FIXME: this is just a placeholder, waiting for a real implementation
1182 # It is sufficient to get us going... (and import a PkgConf which
1183 # happens to contain an Auditor...)
1184 class ConfigurableAuditor(Configurable):
1185 __slots__ = {'_jobOptName': 0, 'OutputLevel': 0,
1186 'Enable': 1}
1187
1188 def __init__(self, name=Configurable.DefaultName):
1189 super(ConfigurableAuditor, self).__init__(name)
1190 name = self.getName()
1191 name = name[name.find('/') + 1:] # strips class, if any
1192 self._jobOptName = name
1193
1194 def getHandle(self):
1195 # iAlgTool isn't useful, unless one knows for sure that the tool exists
1196 return iProperty(self.getJobOptName())
1197
1198 def getGaudiType(self):
1199 return 'Auditor'
1200
1201 def getJobOptName(self):
1202 return self._jobOptName
1203
1204 def toStringProperty(self):
1205 # called on conversion to a string property for the jocat
1206 return self.getType() + '/' + self.getName()
1207
1208
1209 class ConfigurableUser(Configurable):
1210 __slots__ = {"__users__": [],
1211 "__used_instances__": [],
1212 "_enabled": True,
1213 "_applied": False}
1214 # list of ConfigurableUser classes this one is going to modify in the
1215 # __apply_configuration__ method.
1216 # The list may contain class objects, strings representing class objects or
1217 # tuples with the class object (or a string) as first element and the instance
1218 # name as second element.
1219 # If the instance name is None or not present, the function _instanceName()
1220 # is used to determine the name of the instance (the default implementation
1221 # returns "<this name>_<other name>".
1222 __used_configurables__ = []
1223 # list of ConfigurableUser classes this one is going to query in the
1224 # __apply_configuration__ method
1225 __queried_configurables__ = []
1226
1227 def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs):
1228 super(ConfigurableUser, self).__init__(name)
1229 for n, v in kwargs.items():
1230 setattr(self, n, v)
1231 self._enabled = _enabled
1232 self.__users__ = []
1233 self._applied = False
1234
1235 # Needed to retrieve the actual class if the declaration in __used_configurables__
1236 # and __queried_configurables__ is done with strings.
1237 from GaudiKernel.ConfigurableDb import getConfigurable as confDbGetConfigurable
1238
1239 # Set the list of users of the used configurables
1240 #
1241 self.__used_instances__ = []
1242 for used in self.__used_configurables__:
1243 # By default we want to use the default name of the instances
1244 # for the used configurables
1245 used_name = Configurable.DefaultName
1246 # If the entry in the list is a tuple, we need a named instance
1247 if type(used) is tuple:
1248 used, used_name = used # we re-set used to re-use the code below
1249 if not used_name:
1250 used_name = self._instanceName(used)
1251 # Check is 'used' is a string or not
1252 if type(used) is str:
1253 used_class = confDbGetConfigurable(used)
1254 else:
1255 used_class = used
1256 # Instantiate the configurable that we are going to use
1257 try:
1258 inst = used_class(name=used_name, _enabled=False)
1259 except AttributeError:
1260 # This cover the case where the used configurable is not a
1261 # ConfigurableUser instance, i.e. id doesn't have the attribute
1262 # '_enabled'.
1263 inst = used_class(name=used_name)
1264 self.__addActiveUseOf(inst)
1265 for queried in self.__queried_configurables__:
1266 try:
1267 if type(queried) is str:
1268 queried = confDbGetConfigurable(used)
1269 inst = queried(_enabled=False)
1270 except AttributeError:
1271 inst = queried()
1272 self.__addPassiveUseOf(inst)
1273
1274 def __addActiveUseOf(self, other):
1275 """
1276 Declare that we are going to modify the Configurable 'other' in our
1277 __apply_configuration__.
1278 """
1279 self.__used_instances__.append(other)
1280 if hasattr(other, "__users__"): # allow usage of plain Configurables
1281 other.__users__.append(self)
1282
1283 def __addPassiveUseOf(self, other):
1284 """
1285 Declare that we are going to retrieve property values from the
1286 ConfigurableUser 'other' in our __apply_configuration__.
1287 """
1288 if not isinstance(other, ConfigurableUser):
1289 raise Error("'%s': Cannot make passive use of '%s', it is not a ConfigurableUser" % (
1290 self.name(), other.name()))
1291 other.__addActiveUseOf(self)
1292
1293 def getGaudiType(self):
1294 return 'User'
1295
1296 def getDlls(self):
1297 return None
1298
1299 def getHandle(self):
1300 return None
1301
1302 def __detach_used__(self):
1303 """
1304 Remove this ConfigurableUser instance from the users list of the used
1305 instances.
1306 """
1307 for used in self.__used_instances__:
1308 if hasattr(used, "__users__"): # allow usage of plain Configurables
1309 used.__users__.remove(self)
1310
1311 def propagateProperty(self, name, others=None, force=True):
1312 """
1313 Propagate the property 'name' (if set) to other configurables (if possible).
1314 'others' can be:
1315 None:
1316 propagate to all the entries in __used_configurables__
1317 a configurable instance:
1318 propagate only to it
1319 list of configurable instances:
1320 propagate to all of them.
1321
1322
1323 The logic is:
1324 - if the local property is set, the other property will be overwritten
1325 - local property not set and other set => keep other
1326 - local property not set and other not set => overwrite the default for
1327 ConfigurableUser instances and set the property for Configurables
1328 """
1329 # transform 'others' to a list of configurable instances
1330 if others is None:
1331 others = self.__used_instances__
1332 elif type(others) not in [list, tuple]:
1333 others = [others]
1334 # these can be computed before the loop
1335 local_is_set = self.isPropertySet(name)
1336 value = self.getProp(name)
1337 # loop over the others that do have 'name' in their slots
1338 for other in [o for o in others if name in o.__slots__]:
1339 # If self property is set, use it
1340 if local_is_set:
1341 if other.isPropertySet(name):
1342 log.warning("Property '%(prop)s' is set in both '%(self)s' and '%(other)s', using '%(self)s.%(prop)s'" %
1343 {"self": self.name(),
1344 "other": other.name(),
1345 "prop": name})
1346 other.setProp(name, value)
1347 # If not, and other property also not set, propagate the default
1348 elif not other.isPropertySet(name):
1349 if isinstance(other, ConfigurableUser):
1350 otherType = type(other._properties[name].getDefault())
1351 other._properties[name].setDefault(value)
1352 if otherType in [list, dict]:
1353 # Special case for list and dictionaries:
1354 # also set the property to the same value of the default (copy)
1355 other.setProp(name, otherType(value))
1356 else:
1357 other.setProp(name, value)
1358 # If not set and other set, do nothing
1359
1360 def propagateProperties(self, names=None, others=None, force=True):
1361 """
1362 Call propagateProperty for each property listed in 'names'.
1363 If 'names' is None, all the properties are propagated.
1364 """
1365 if names is None:
1366 # use all the non-private slots
1367 names = [p for p in self.__slots__ if not p.startswith("_")]
1368 for n in names:
1369 self.propagateProperty(n, others, force)
1370
1371 def __apply_configuration__(self):
1372 """
1373 Function to be overridden to convert the high level configuration into a
1374 low level one.
1375 The default implementation calls applyConf, which is the method defined
1376 in some ConfigurableUser implementations.
1377 """
1378 return self.applyConf()
1379
1380 def applyConf(self):
1381 """
1382 Function to be overridden to convert the high level configuration into a
1383 low level one.
1384 """
1385 pass
1386
1387 def _instanceName(self, cls):
1388 """
1389 Function used to define the name of the private instance of a given class
1390 name.
1391 This method is used when the __used_configurables_property__ declares the
1392 need of a private used configurable without specifying the name.
1393 """
1394 if type(cls) is str:
1395 clName = cls
1396 else:
1397 clName = cls.__name__
1398 return "%s_%s" % (self.name(), clName)
1399
1400 def getUsedInstance(self, name):
1401 """
1402 Return the used instance with a given name.
1403 """
1404 for i in self.__used_instances__:
1405 if i.name() == name:
1406 if hasattr(i, "_enabled"):
1407 # ensure that the instances retrieved through the method are
1408 # enabled
1409 i._enabled = True
1410 return i
1411 raise KeyError(name)
1412
1413 def isApplicable(self):
1414 '''
1415 Return True is the instance can be "applied".
1416 '''
1417 return (not self.__users__) and (not self._applied)
1418
1419
1420 # list of callables to be called after all the __apply_configuration__ are called.
1421 postConfigActions = []
1422
1423
1424 def appendPostConfigAction(function):
1425 """
1426 Add a new callable ('function') to the list of post-configuration actions.
1427 If the callable is already in the list, it is moved to the end of the list.
1428 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1429 """
1430 try:
1431 postConfigActions.remove(function)
1432 except:
1433 pass
1434 postConfigActions.append(function)
1435
1436
1437 def removePostConfigAction(function):
1438 """
1439 Remove a callable from the list of post-config actions.
1440 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1441 """
1442 postConfigActions.remove(function)
1443
1444
1445 _appliedConfigurableUsers_ = False
1446
1447
1448 def applyConfigurableUsers():
1449 """
1450 Call the apply method of all the ConfigurableUser instances respecting the
1451 dependencies. First the C.U.s that are not used by anybody, then the used
1452 ones, when they are not used anymore.
1453 """
1454 # Avoid double calls
1455 global _appliedConfigurableUsers_, postConfigActions
1456 if _appliedConfigurableUsers_:
1457 return
1458 _appliedConfigurableUsers_ = True
1459
1460 def applicableConfUsers():
1461 '''
1462 Generator returning all the configurables that can be applied in the
1463 order in which they can be applied.
1464 '''
1465 # This is tricky...
1466 # We keep on looking for the first configurable that can be applied.
1467 # When we cannot find any, 'next()' raises a StopIteration that is
1468 # propagated outside of the infinite loop and the function, then handled
1469 # correctly from outside (it is the exception that is raised when you
1470 # exit from a generator).
1471 # Checking every time the full list is inefficient, but it is the
1472 # easiest way to fix bug #103803.
1473 # <https://savannah.cern.ch/bugs/?103803>
1474 while True:
1475 yield (c for c in Configurable.allConfigurables.values()
1476 if c.isApplicable()).next()
1477
1478 debugApplyOrder = 'GAUDI_DUBUG_CONF_USER' in os.environ
1479 for c in applicableConfUsers():
1480 if c._enabled:
1481 log.info("applying configuration of %s", c.name())
1482 if debugApplyOrder:
1483 sys.stderr.write('applying %r' % c)
1484 c.__apply_configuration__()
1485 log.info(c)
1486 else:
1487 log.info("skipping configuration of %s", c.name())
1488 c._applied = True # flag the instance as already applied
1489 if hasattr(c, "__detach_used__"):
1490 # tells the used configurables that they are not needed anymore
1491 c.__detach_used__()
1492
1493 # check for dependency loops
1494 leftConfUsers = [c for c in Configurable.allConfigurables.values()
1495 if hasattr(c, '__apply_configuration__') and
1496 c._enabled and not c._applied]
1497 # if an enabled configurable has not been applied, there must be a dependency loop
1498 if leftConfUsers:
1499 raise Error("Detected loop in the ConfigurableUser"
1500 " dependencies: %r" % [c.name()
1501 for c in leftConfUsers])
1502 # ensure that all the Handles have been triggered
1503 known = set()
1504 unknown = set(Configurable.allConfigurables)
1505 while unknown:
1506 for k in unknown:
1507 if not known: # do not print during the first iteration
1508 log.debug('new configurable created automatically: %s', k)
1509 # this trigger the instantiation from handles
1510 Configurable.allConfigurables[k].properties()
1511 known.add(k)
1512 unknown -= known
1513 # Call post-config actions
1514 for action in postConfigActions:
1515 action()
1516
1517
1518 def applyConfigurableUsers_old():
1519 """
1520 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1521 backward compatibility for configurations that where relying (implicitly) on
1522 bug #103803, or on a specific (non guaranteed) order of execution.
1523
1524 @see applyConfigurableUsers()
1525 """
1526 # Avoid double calls
1527 global _appliedConfigurableUsers_, postConfigActions
1528 if _appliedConfigurableUsers_:
1529 return
1530 _appliedConfigurableUsers_ = True
1531
1532 debugApplyOrder = 'GAUDI_DUBUG_CONF_USER' in os.environ
1533 confUsers = [c
1534 for c in Configurable.allConfigurables.values()
1535 if hasattr(c, "__apply_configuration__")]
1536 applied = True # needed to detect dependency loops
1537 while applied and confUsers:
1538 newConfUsers = [] # list of conf users that cannot be applied yet
1539 applied = False
1540 for c in confUsers:
1541 if hasattr(c, "__users__") and c.__users__:
1542 newConfUsers.append(c) # cannot use this one yet
1543 else: # it does not have users or the list is empty
1544 applied = True
1545 # the ConfigurableUser is enabled if it doesn't have an _enabled
1546 # property or its value is True
1547 enabled = (not hasattr(c, "_enabled")) or c._enabled
1548 if enabled:
1549 log.info("applying configuration of %s", c.name())
1550 if debugApplyOrder:
1551 sys.stderr.write('applying %r' % c)
1552 c.__apply_configuration__()
1553 log.info(c)
1554 else:
1555 log.info("skipping configuration of %s", c.name())
1556 if hasattr(c, "__detach_used__"):
1557 # tells the used configurables that they are not needed anymore
1558 c.__detach_used__()
1559 confUsers = newConfUsers # list of C.U.s still to go
1560 if confUsers:
1561 # this means that some C.U.s could not be applied because of a dependency loop
1562 raise Error("Detected loop in the ConfigurableUser "
1563 " dependencies: %r" % [c.name()
1564 for c in confUsers])
1565 # ensure that all the Handles have been triggered
1566 known = set()
1567 unknown = set(Configurable.allConfigurables)
1568 while unknown:
1569 for k in unknown:
1570 if not known: # do not print during the first iteration
1571 log.debug('new configurable created automatically: %s', k)
1572 # this trigger the instantiation from handles
1573 Configurable.allConfigurables[k].properties()
1574 known.add(k)
1575 unknown -= known
1576 # Call post-config actions
1577 for action in postConfigActions:
1578 action()
1579
1580
1581 def getNeededConfigurables():
1582 """
1583 Function to select all and only the configurables that have to be used in
1584 GaudiPython.AppMgr constructor.
1585 This is needed because in Athena the implementation have to be different (the
1586 configuration is used in a different moment).
1587 """
1588 return [k
1589 for k, v in Configurable.allConfigurables.items()
1590 if v.getGaudiType() != "User"] # Exclude ConfigurableUser instances
1591
1592
1593 def purge():
1594 """
1595 Clean up all configurations and configurables.
1596 """
1597 for c in Configurable.allConfigurables.values():
1598 c.__class__.configurables.clear()
1599 Configurable.allConfigurables.clear()
1600 # FIXME: (MCl) this is needed because instances of ConfigurableGeneric are not
1601 # migrated to the correct class when this is known.
1602 ConfigurableGeneric.configurables.clear()
1603 from ProcessJobOptions import _included_files
1604 import os.path
1605 import sys
1606 for file in _included_files:
1607 dirname, basname = os.path.split(file)
1608 basname, ext = os.path.splitext(basname)
1609 if basname in sys.modules:
1610 del sys.modules[basname]
1611 _included_files.clear()
1612
1613
1614 class CreateSequencesVisitor(object):
1615 def __init__(self):
1616 self.stack = []
1617
1618 @property
1619 def sequence(self):
1620 return self.stack[-1]
1621
1622 def enter(self, visitee):
1623 pass
1624
1625 def _getUniqueName(self, prefix):
1626 from Gaudi.Configuration import allConfigurables
1627 cnt = 0
1628 name = prefix + str(cnt)
1629 while name in allConfigurables:
1630 cnt += 1
1631 name = prefix + str(cnt)
1632 return name
1633
1634 def _newSeq(self, prefix='seq_', **kwargs):
1635 from Configurables import GaudiSequencer
1636 return GaudiSequencer(self._getUniqueName('seq_'),
1637 **kwargs)
1638
1639 def leave(self, visitee):
1640 stack = self.stack
1641 if visitee in (CFTrue, CFFalse):
1642 stack.append(self._newSeq(Invert=visitee is CFFalse))
1643 elif isinstance(visitee, (ControlFlowLeaf, ConfigurableAlgorithm)):
1644 stack.append(visitee)
1645 elif isinstance(visitee, (OrNode, AndNode, OrderedNode)):
1646 b = stack.pop()
1647 a = stack.pop()
1648 seq = self._newSeq(Members=[a, b],
1649 ModeOR=isinstance(visitee, OrNode),
1650 ShortCircuit=not isinstance(
1651 visitee, OrderedNode),
1652 MeasureTime=True)
1653 stack.append(seq)
1654 elif isinstance(visitee, ignore):
1655 if hasattr(stack[-1], 'IgnoreFilterPassed'):
1656 stack[-1].IgnoreFilterPassed = True
1657 else:
1658 stack.append(self._newSeq(Members=[stack.pop()],
1659 IgnoreFilterPassed=True))
1660 elif isinstance(visitee, InvertNode):
1661 if hasattr(stack[-1], 'Invert'):
1662 stack[-1].Invert = True
1663 else:
1664 stack.append(self._newSeq(Members=[stack.pop()],
1665 Invert=True))
1666
1667
1668 def makeSequences(expression):
1669 '''
1670 Convert a control flow expression to nested GaudiSequencers.
1671 '''
1672 if not isinstance(expression, ControlFlowNode):
1673 raise ValueError('ControlFlowNode instance expected, got %s' %
1674 type(expression).__name__)
1675 visitor = CreateSequencesVisitor()
1676 expression.visitNode(visitor)
1677 return visitor.sequence
1678
1679
1680 class SuperAlgorithm(ControlFlowNode):
1681 '''
1682 Helper class to use a ControlFlowNode as an algorithm configurable
1683 instance.
1684 '''
1685 def __new__(cls, name=None, **kwargs):
1686 if name is None:
1687 name = cls.__name__
1688 if name in Configurable.allConfigurables:
1689 instance = Configurable.allConfigurables[name]
1690 assert type(instance) is cls, \
1691 ('trying to reuse {0!r} as name of a {1} instance while it''s '
1692 'already used for an instance of {2}').format(
1693 name,
1694 cls.__name__,
1695 type(instance).__name__)
1696 return instance
1697 else:
1698 instance = super(SuperAlgorithm, cls).__new__(cls, name, **kwargs)
1699 Configurable.allConfigurables[name] = instance
1700 return instance
1701
1702 def __init__(self, name=None, **kwargs):
1703 self._name = name or self.getType()
1704 self.graph = self._initGraph()
1705 for key in kwargs:
1706 setattr(self, key, kwargs[key])
1707
1708 @property
1709 def name(self): # name is a read only property
1710 return self._name
1711
1712 @classmethod
1713 def getType(cls):
1714 return cls.__name__
1715
1716 # required to be registered in allConfigurables
1717 def properties(self):
1718 pass
1719
1720 # required to be registered in allConfigurables
1721 def isApplicable(self):
1722 return False
1723
1724 # required to be registered in allConfigurables
1725 def getGaudiType(self):
1726 return 'User'
1727
1728 def _makeAlg(self, typ, **kwargs):
1729 '''
1730 Instantiate and algorithm of type 'typ' with a name suitable for use
1731 inside a SuperAlgorithm.
1732 '''
1733 name = '{0}_{1}'.format(self.name, kwargs.pop('name', typ.getType()))
1734 return typ(name, **kwargs)
1735
1736 def _initGraph(self):
1737 raise NotImplementedError()
1738
1739 def __repr__(self):
1740 return '{0}({1!r})'.format(self.getType(), self.name)
1741
1742 def _visitSubNodes(self, visitor):
1743 if self.graph:
1744 self.graph.visitNode(visitor)
1745
1746 def __setattr__(self, name, value):
1747 super(SuperAlgorithm, self).__setattr__(name, value)
1748 if name in ('_name', 'graph'):
1749 # do not propagate internal data members
1750 return
1751
1752 class PropSetter(object):
1753 def enter(self, node):
1754 try:
1755 setattr(node, name, value)
1756 except (ValueError, AttributeError):
1757 # ignore type and name mismatch
1758 pass
1759
1760 def leave(self, node):
1761 pass
1762
1763 self._visitSubNodes(PropSetter())
GaudiKernel.Configurable.getNeededConfigurables
def getNeededConfigurables()
Definition: Configurable.py:1581
GaudiKernel.Configurable.Configurable.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:361
GaudiKernel.Configurable.ConfigurableUser.propagateProperty
def propagateProperty(self, name, others=None, force=True)
Definition: Configurable.py:1311
GaudiKernel.Configurable.Configurable.__children
__children
Definition: Configurable.py:309
GaudiKernel.Configurable.Configurable.setParent
def setParent(self, parentName)
Definition: Configurable.py:477
GaudiKernel.Configurable.ConfigurableUser.__apply_configuration__
def __apply_configuration__(self)
Definition: Configurable.py:1371
GaudiKernel.Configurable.Configurable.getTitleName
def getTitleName(self)
Definition: Configurable.py:742
GaudiKernel.Configurable.SuperAlgorithm.__repr__
def __repr__(self)
Definition: Configurable.py:1739
GaudiKernel.Configurable.ConfigurableUser.__users__
__users__
Definition: Configurable.py:1232
GaudiKernel.Configurable.Configurable.removeAll
def removeAll(self)
Definition: Configurable.py:470
GaudiKernel.Configurable.Configurable.allConfigurables
dictionary allConfigurables
Definition: Configurable.py:133
GaudiKernel.Configurable.SuperAlgorithm.isApplicable
def isApplicable(self)
Definition: Configurable.py:1721
GaudiKernel.Configurable.CreateSequencesVisitor._newSeq
def _newSeq(self, prefix='seq_', kwargs)
Definition: Configurable.py:1634
GaudiKernel.Configurable.ConfigurableAlgorithm.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:1032
GaudiKernel.Configurable.PropertyReference.__resolve__
def __resolve__(self)
Definition: Configurable.py:77
GaudiKernel.Configurable.ConfigurableUser.__detach_used__
def __detach_used__(self)
Definition: Configurable.py:1302
GaudiKernel.Configurable.Configurable.__setstate__
def __setstate__(self, dict)
Definition: Configurable.py:347
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:120
GaudiKernel.Configurable.ConfigurableUser.__queried_configurables__
list __queried_configurables__
Definition: Configurable.py:1225
GaudiKernel.Configurable.Configurable._printHeader
def _printHeader(indentStr, title)
Definition: Configurable.py:859
GaudiKernel.ConfigurableMeta
Definition: ConfigurableMeta.py:1
GaudiKernel.Configurable.CreateSequencesVisitor._getUniqueName
def _getUniqueName(self, prefix)
Definition: Configurable.py:1625
GaudiKernel.Configurable.ConfigurableUser.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1293
GaudiKernel.Configurable.PropertyReference.__str__
def __str__(self)
Definition: Configurable.py:74
GaudiKernel.Configurable.ConfigurableUser.__init__
def __init__(self, name=Configurable.DefaultName, _enabled=True, kwargs)
Definition: Configurable.py:1227
GaudiKernel.Configurable.Configurable.setup
def setup(self)
Definition: Configurable.py:564
GaudiKernel.GaudiHandles
Definition: GaudiHandles.py:1
GaudiKernel.Configurable.Configurable.configurableServices
dictionary configurableServices
Definition: Configurable.py:134
GaudiKernel.Configurable.ConfigurableUser.__addPassiveUseOf
def __addPassiveUseOf(self, other)
Definition: Configurable.py:1283
GaudiKernel.Configurable.Configurable.getProp
def getProp(self, name)
Definition: Configurable.py:684
std::function< StatusCode()>
GaudiKernel.Configurable.ConfigurableAuditor.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1198
GaudiKernel.Configurable.CreateSequencesVisitor
Definition: Configurable.py:1614
GaudiKernel.Configurable.ConfigurableAlgTool._jobOptName
_jobOptName
Definition: Configurable.py:1112
GaudiKernel.Configurable.ConfigurableUser.applyConf
def applyConf(self)
Definition: Configurable.py:1380
GaudiKernel.Configurable.Configurable.__new__
def __new__(cls, args, kwargs)
Definition: Configurable.py:139
GaudiKernel.Configurable.Configurable.splitName
def splitName(self)
Definition: Configurable.py:782
GaudiKernel.Configurable.SuperAlgorithm.getType
def getType(cls)
Definition: Configurable.py:1713
GaudiKernel.Configurable.ConfigurableAlgorithm.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1041
GaudiKernel.Configurable.SuperAlgorithm
Definition: Configurable.py:1680
GaudiKernel.Configurable.Configurable.hasParent
def hasParent(self, parent)
Definition: Configurable.py:483
GaudiKernel.Configurable.SuperAlgorithm.__init__
def __init__(self, name=None, kwargs)
Definition: Configurable.py:1702
GaudiKernel.Configurable.appendPostConfigAction
def appendPostConfigAction(function)
Definition: Configurable.py:1424
GaudiSequencer
Sequencer for executing several algorithms, stopping when one is faulty.
Definition: GaudiSequencer.h:26
GaudiKernel.Configurable.SuperAlgorithm._initGraph
def _initGraph(self)
Definition: Configurable.py:1736
GaudiKernel.Configurable.Configurable.getPrintTitle
def getPrintTitle(self)
Definition: Configurable.py:739
GaudiKernel.Configurable.Configurable.getTools
def getTools(self)
Definition: Configurable.py:509
GaudiKernel.Configurable.Configurable.__init__
def __init__(self, name=DefaultName)
Definition: Configurable.py:278
GaudiKernel.Configurable.Configurable.getPropertiesWithDescription
def getPropertiesWithDescription(self)
Definition: Configurable.py:606
GaudiKernel.Configurable.Configurable.addTool
def addTool(self, tool, name=None)
Definition: Configurable.py:798
GaudiKernel.Configurable.Configurable.__setupDefaults
def __setupDefaults(self)
Definition: Configurable.py:851
GaudiKernel.Configurable.makeSequences
def makeSequences(expression)
Definition: Configurable.py:1668
GaudiKernel.Configurable.Configurable._printFooter
def _printFooter(indentStr, title)
Definition: Configurable.py:867
GaudiKernel.Configurable.ConfigurableAlgTool.setParent
def setParent(self, parentName)
Definition: Configurable.py:1134
GaudiKernel.Configurable.SuperAlgorithm._makeAlg
def _makeAlg(self, typ, kwargs)
Definition: Configurable.py:1728
GaudiKernel.Configurable.DummyDescriptor.__init__
def __init__(self, name)
Definition: Configurable.py:974
GaudiKernel.Configurable.CreateSequencesVisitor.enter
def enter(self, visitee)
Definition: Configurable.py:1622
GaudiKernel.Configurable.Configurable._initok
_initok
Definition: Configurable.py:325
GaudiKernel.Configurable.ConfigurableAlgTool.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1105
GaudiKernel.Configurable.ConfigurableAlgorithm._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: Configurable.py:1070
GaudiKernel.Configurable.applyConfigurableUsers
def applyConfigurableUsers()
Definition: Configurable.py:1448
GaudiKernel.Configurable.ConfigurableAlgTool.getPrintTitle
def getPrintTitle(self)
Definition: Configurable.py:1127
GaudiKernel.Configurable.CreateSequencesVisitor.sequence
def sequence(self)
Definition: Configurable.py:1619
GaudiKernel.Configurable.Configurable.clone
def clone(self, name=None, kwargs)
Definition: Configurable.py:751
GaudiKernel.Configurable.ConfigurableUser._instanceName
def _instanceName(self, cls)
Definition: Configurable.py:1387
GaudiKernel.Configurable.SuperAlgorithm.name
def name(self)
Definition: Configurable.py:1709
GaudiKernel.Configurable.Configurable.setProp
def setProp(self, name, value)
Definition: Configurable.py:692
GaudiKernel.Configurable.ConfigurableAuditor.getHandle
def getHandle(self)
Definition: Configurable.py:1194
GaudiKernel.Configurable.ConfigurableAlgTool.getParent
def getParent(self)
Definition: Configurable.py:1149
GaudiKernel.GaudiHandles.PrivateToolHandle
Definition: GaudiHandles.py:82
Gaudi.Configuration
Definition: Configuration.py:1
GaudiKernel.Configurable.ConfigurableUser.__used_configurables__
list __used_configurables__
Definition: Configurable.py:1222
GaudiKernel.Configurable.ConfigurableGeneric.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:992
GaudiKernel.Configurable.ConfigurableAlgTool.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1118
GaudiKernel.Configurable.CreateSequencesVisitor.leave
def leave(self, visitee)
Definition: Configurable.py:1639
MSG::hex
MsgStream & hex(MsgStream &log)
Definition: MsgStream.h:304
GaudiKernel.Configurable.ConfigurableAlgTool.isInToolSvc
def isInToolSvc(self)
Definition: Configurable.py:1165
GaudiKernel.Configurable.ConfigurableAlgorithm.__invert__
def __invert__(self)
Definition: Configurable.py:1059
GaudiKernel.PropertyProxy
Definition: PropertyProxy.py:1
GaudiKernel.Configurable.ConfigurableUser.getHandle
def getHandle(self)
Definition: Configurable.py:1299
GaudiKernel.Configurable.ConfigurableGeneric.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:987
GaudiKernel.Configurable.Configurable.__getnewargs__
def __getnewargs__(self)
Definition: Configurable.py:344
GaudiKernel.Configurable.Configurable.properties
def properties(self)
Definition: Configurable.py:643
GaudiKernel.Configurable.Configurable.__getattr__
def __getattr__(self, attr)
Definition: Configurable.py:410
GaudiKernel.Configurable.SuperAlgorithm.graph
graph
Definition: Configurable.py:1704
GaudiKernel.Configurable.ConfigurableAlgTool.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1159
GaudiKernel.Configurable.ConfigurableAuditor.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1188
GaudiKernel.Configurable.Configurable.__setupDlls
def __setupDlls(self)
Definition: Configurable.py:839
GaudiKernel.PropertyProxy.PropertyProxy
Definition: PropertyProxy.py:68
GaudiKernel.Configurable.ConfigurableAlgTool.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:1168
GaudiKernel.Configurable.PropertyReference.__init__
def __init__(self, propname)
Definition: Configurable.py:71
GaudiKernel.Configurable.PropertyReference.name
name
Definition: Configurable.py:72
GaudiKernel.ConfigurableDb
Definition: ConfigurableDb.py:1
GaudiKernel.Configurable.ConfigurableService.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:1081
GaudiKernel.Configurable.ConfigurableService.getHandle
def getHandle(self)
Definition: Configurable.py:1087
GaudiKernel.Configurable.PropertyReference.getFullName
def getFullName(self)
Definition: Configurable.py:91
GaudiKernel.Configurable.Configurable.name
def name(self)
Definition: Configurable.py:718
GaudiKernel.Configurable.Configurable.copyChildAndSetParent
def copyChildAndSetParent(self, cfg, parent)
Definition: Configurable.py:486
GaudiKernel.Configurable.ConfigurableGeneric.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:1001
GaudiKernel.Configurable.Configurable.remove
def remove(self, items)
Definition: Configurable.py:464
GaudiKernel.Configurable.Configurable.children
def children(self)
Definition: Configurable.py:512
GaudiKernel.Configurable.ConfigurableUser.__addActiveUseOf
def __addActiveUseOf(self, other)
Definition: Configurable.py:1274
GaudiKernel.Configurable.ConfigurableUser.isApplicable
def isApplicable(self)
Definition: Configurable.py:1413
GaudiKernel.Configurable.Configurable._name
_name
Definition: Configurable.py:315
GaudiKernel.Configurable.Configurable._setupok
_setupok
Definition: Configurable.py:328
GaudiKernel.Configurable.Configurable.__nonzero__
def __nonzero__(self)
Definition: Configurable.py:461
GaudiKernel.Configurable.Configurable.getFullName
def getFullName(self)
Definition: Configurable.py:733
GaudiKernel.Configurable.Configurable.setDefaults
def setDefaults(cls, handle)
Definition: Configurable.py:748
GaudiKernel.Configurable.Configurable.getSequence
def getSequence(self)
Definition: Configurable.py:558
GaudiKernel.Configurable.ConfigurableAlgTool.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:1121
GaudiKernel.Configurable.ConfigurableUser._enabled
_enabled
Definition: Configurable.py:1231
GaudiKernel.Configurable.ConfigurableAlgorithm.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1038
GaudiKernel.Configurable.Configurable.__iadd__
def __iadd__(self, configs, descr=None)
Definition: Configurable.py:377
GaudiKernel.Configurable.ConfigurableAuditor.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1201
GaudiKernel.Configurable.ConfigurableUser.getDlls
def getDlls(self)
Definition: Configurable.py:1296
gaudirun.type
type
Definition: gaudirun.py:133
GaudiKernel.Configurable.Configurable.isPropertySet
def isPropertySet(self, name)
Definition: Configurable.py:697
GaudiKernel.Configurable.ConfigurableAuditor.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:1204
GaudiKernel.Configurable.ConfigurableAlgTool.getFullName
def getFullName(self)
Definition: Configurable.py:1172
GaudiKernel.Configurable.SuperAlgorithm.__new__
def __new__(cls, name=None, kwargs)
Definition: Configurable.py:1685
GaudiKernel.Configurable.Configurable.getProperties
def getProperties(self)
Definition: Configurable.py:596
GaudiKernel.Configurable.Configurable.getDefaultProperties
def getDefaultProperties(cls)
Definition: Configurable.py:647
GaudiKernel.Configurable.ConfigurableUser._applied
_applied
Definition: Configurable.py:1233
GaudiConfig.ControlFlow
Definition: ControlFlow.py:1
GaudiKernel.Configurable.SuperAlgorithm.properties
def properties(self)
Definition: Configurable.py:1717
GaudiKernel.Configurable.ConfigurableAlgorithm.__rshift__
def __rshift__(self, rhs)
Definition: Configurable.py:1062
GaudiKernel.Configurable.ConfigurableAlgorithm.__or__
def __or__(self, rhs)
Definition: Configurable.py:1052
GaudiKernel.Configurable.Configurable.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:721
GaudiKernel.GaudiHandles.PublicToolHandle
Definition: GaudiHandles.py:73
GaudiKernel.Configurable.Configurable.__delattr__
def __delattr__(self, attr)
Definition: Configurable.py:436
GaudiKernel.Configurable.Configurable
Definition: Configurable.py:107
GaudiKernel.Configurable.ConfigurableUser.getUsedInstance
def getUsedInstance(self, name)
Definition: Configurable.py:1400
GaudiKernel.Configurable.ConfigurableGeneric.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:995
GaudiKernel.Configurable.CreateSequencesVisitor.__init__
def __init__(self)
Definition: Configurable.py:1615
GaudiKernel.ConfigurableMeta.ConfigurableMeta
Definition: ConfigurableMeta.py:16
GaudiKernel.Configurable.ConfigurableAuditor
Definition: Configurable.py:1184
GaudiKernel.Constants
Definition: Constants.py:1
GaudiKernel.Configurable.ConfigurableService
Definition: Configurable.py:1077
GaudiKernel.Configurable.ConfigurableAlgTool.isPublic
def isPublic(self)
Definition: Configurable.py:1162
GaudiKernel.Configurable.ConfigurableService.copyChild
def copyChild(self, child)
Definition: Configurable.py:1084
GaudiKernel.Configurable.applyConfigurableUsers_old
def applyConfigurableUsers_old()
Definition: Configurable.py:1518
GaudiKernel.Configurable.Configurable.getParent
def getParent(self)
Definition: Configurable.py:480
GaudiPython.GaudiAlgs.iAlgorithm
iAlgorithm
Definition: GaudiAlgs.py:54
GaudiKernel.Configurable.ConfigurableAlgorithm.__eq__
def __eq__(self, other)
Definition: Configurable.py:1073
GaudiKernel.Configurable.Configurable.getName
def getName(self)
Definition: Configurable.py:715
GaudiKernel.Configurable.SuperAlgorithm.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:1746
GaudiKernel.Configurable.Configurable.getFullJobOptName
def getFullJobOptName(self)
Definition: Configurable.py:736
GaudiKernel.Configurable.Configurable.__len__
def __len__(self)
Definition: Configurable.py:354
GaudiKernel.Configurable.DummyDescriptor.__set__
def __set__(self, obj, value)
Definition: Configurable.py:980
gaudiComponentHelp.properties
properties
Definition: gaudiComponentHelp.py:41
GaudiKernel.Configurable.SuperAlgorithm._name
_name
Definition: Configurable.py:1703
GaudiKernel.Configurable.removePostConfigAction
def removePostConfigAction(function)
Definition: Configurable.py:1437
GaudiKernel.Configurable.ConfigurableAlgTool.hasParent
def hasParent(self, parent)
Definition: Configurable.py:1156
GaudiKernel.GaudiHandles.ServiceHandle
Definition: GaudiHandles.py:91
GaudiKernel.Configurable.Configurable.__str__
def __str__(self, indent=0, headerLastIndentUnit=indentUnit)
Definition: Configurable.py:877
GaudiKernel.Configurable.ConfigurableAlgorithm._jobOptName
_jobOptName
Definition: Configurable.py:1030
GaudiKernel.Configurable.CreateSequencesVisitor.stack
stack
Definition: Configurable.py:1616
GaudiKernel.Configurable.ConfigurableGeneric.getHandle
def getHandle(self)
Definition: Configurable.py:999
GaudiKernel.Configurable.Configurable.jobOptName
def jobOptName(self)
Definition: Configurable.py:728
GaudiKernel.Configurable.Configurable._configurationLocked
bool _configurationLocked
Definition: Configurable.py:137
GaudiKernel.Configurable.Configurable.__setupServices
def __setupServices(self)
Definition: Configurable.py:822
GaudiKernel.Configurable.ConfigurableService.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1090
GaudiKernel.Configurable.DummyDescriptor
Definition: Configurable.py:973
GaudiKernel.Configurable.expandvars
def expandvars(data)
Definition: Configurable.py:38
GaudiKernel.Configurable.Configurable._isInSetDefaults
def _isInSetDefaults(self)
Definition: Configurable.py:819
GaudiKernel.Configurable.ConfigurableAlgorithm.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1027
GaudiKernel.Configurable.ConfigurableUser
Definition: Configurable.py:1209
GaudiKernel.Configurable.DummyDescriptor.__name__
__name__
Definition: Configurable.py:975
GaudiKernel.Configurable.Configurable.isPublic
def isPublic(self)
Definition: Configurable.py:724
GaudiKernel.DataObjectHandleBase
Definition: DataObjectHandleBase.py:1
GaudiKernel.Configurable.ConfigurableGeneric.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1017
GaudiKernel.Configurable.Configurable.getDefaultProperty
def getDefaultProperty(cls, name)
Definition: Configurable.py:663
GaudiKernel.Configurable.Configurable.getChildren
def getChildren(self)
Definition: Configurable.py:506
GaudiKernel.Configurable.ConfigurableService.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:1096
GaudiKernel.Configurable.ConfigurableUser.propagateProperties
def propagateProperties(self, names=None, others=None, force=True)
Definition: Configurable.py:1360
GaudiKernel.Configurable.purge
def purge()
Definition: Configurable.py:1593
GaudiKernel.Configurable.DummyDescriptor.__get__
def __get__(self, obj, type=None)
Definition: Configurable.py:977
GaudiKernel.Configurable.ConfigurableUser.__used_instances__
__used_instances__
Definition: Configurable.py:1241
GaudiKernel.Configurable.SuperAlgorithm._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: Configurable.py:1742
GaudiKernel.Configurable.ConfigurableAlgorithm.getHandle
def getHandle(self)
Definition: Configurable.py:1035
GaudiKernel.Configurable.Configurable.copyChild
def copyChild(self, child)
Definition: Configurable.py:474
GaudiKernel.Configurable.ConfigurableGeneric
Definition: Configurable.py:984
GaudiKernel.Configurable.Configurable.getValuedProperties
def getValuedProperties(self)
Definition: Configurable.py:616
GaudiKernel.Configurable.Configurable.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:426
GaudiKernel.Configurable.isApplicable
def isApplicable(self)
rep += v.__str__( indent + 1 ) + os.linesep elif isinstance(v,GaudiHandleArray): for vi in v: if isin...
Definition: Configurable.py:962
GaudiKernel.Configurable.Configurable.getType
def getType(cls)
Definition: Configurable.py:712
GaudiKernel.Configurable.Configurable.__repr__
def __repr__(self)
Definition: Configurable.py:874
GaudiKernel.Configurable.Configurable.__slots__
tuple __slots__
Definition: Configurable.py:124
GaudiKernel.Configurable.Configurable.__getstate__
def __getstate__(self)
Definition: Configurable.py:331
GaudiKernel.Configurable.ConfigurableGeneric._properties
_properties
Definition: Configurable.py:990
GaudiKernel.Configurable.ConfigurableAlgTool
Definition: Configurable.py:1101
GaudiKernel.Configurable.SuperAlgorithm.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1725
GaudiKernel.Configurable.ConfigurableAuditor._jobOptName
_jobOptName
Definition: Configurable.py:1192
GaudiKernel.Configurable.ConfigurableService.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:1093
GaudiKernel.Configurable.Configurable.__tools
__tools
Definition: Configurable.py:310
GaudiKernel.Configurable.ConfigurableAlgTool.getHandle
def getHandle(self)
Definition: Configurable.py:1114
GaudiKernel.Configurable.Error
Definition: Configurable.py:61
GaudiKernel.Configurable.Configurable.__iter__
def __iter__(self)
Definition: Configurable.py:357
GaudiKernel.Configurable.ConfigurableAlgorithm.visitNode
def visitNode(self, visitor)
Definition: Configurable.py:1065
GaudiKernel.Configurable.Configurable._inSetDefaults
_inSetDefaults
Definition: Configurable.py:322
GaudiKernel.Configurable.ConfigurableAlgorithm.__and__
def __and__(self, rhs)
Definition: Configurable.py:1045
GaudiKernel.Configurable.Configurable.getAllChildren
def getAllChildren(self)
Definition: Configurable.py:519
GaudiKernel.Configurable.Configurable.DefaultName
Definition: Configurable.py:114