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