The Gaudi Framework  v37r1 (a7f61348)
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 not isinstance(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  if attr in self.__tools:
495  return self.__tools[attr]
496 
497  if attr in self._properties:
498  if isinstance(self._properties[attr].__get__(self), DataHandle):
499  return self._properties[attr].__get__(self)
500 
501  for c in self.__children:
502  if c.getName() == attr:
503  return c
504 
505  raise AttributeError(
506  "'%s' object has no attribute '%s'" % (self.__class__, attr)
507  )
508 
509  def __setattr__(self, name, value):
510  if self._configurationLocked:
511  raise RuntimeError(
512  "%s: Configuration cannot be modified after the ApplicationMgr has been started."
513  % self.name()
514  )
515  try:
516  super(Configurable, self).__setattr__(name, value)
517  except AttributeError:
518  raise AttributeError(
519  "Configurable '%s' does not have property '%s'."
520  % (self.__class__.__name__, name)
521  )
522 
523  def __delattr__(self, attr):
524  # remove as property, otherwise try as child
525  try:
526  # remove history etc., then reset to default (in case set before)
527  prop = self._properties[attr]
528  prop.__delete__(self)
529  prop.__set__(self, prop.default)
530  return # reaches here? was property: done now
531  except KeyError:
532  pass
533  # otherwise, remove the private tool
534  if attr in self.__tools:
535  del self.__tools[attr]
536 
537  # otherwise, remove child, if one is so named
538  for c in self.__children:
539  if c.getName() == attr:
540  self.__children.remove(c)
541 
542  # potentially, there are left over caches (certain user derived classes)
543  try:
544  del self.__dict__[attr]
545  except (AttributeError, KeyError):
546  pass
547 
548  def __bool__(self):
549  return True
550 
551  # Python 2 compatibility
552  __nonzero__ = __bool__
553 
554  def remove(self, items):
555  if not isinstance(items, (list, tuple)):
556  items = [items]
557 
558  self.__children = [e for e in self.__children if e not in items]
559 
560  def removeAll(self):
561  self.remove(self.__children)
562 
563  # called by __iadd__; determines child copy semantics
564  def copyChild(self, child):
565  return copy.deepcopy(child)
566 
567  def setParent(self, parentName):
568  pass
569 
570  def getParent(self):
571  return ""
572 
573  def hasParent(self, parent):
574  return False
575 
576  def copyChildAndSetParent(self, cfg, parent):
577  cc = self.copyChild(cfg)
578 
579  if hasattr(cc, "setParent") and parent:
580  try:
581  cc.setParent(parent)
582  except RuntimeError as e:
583  # temporary backdoor resolution for compatibility
584  log.error(str(e) + "%s", error_explanation)
585  ccbd = cc.configurables[cc.getJobOptName()]
586 
587  # merge properties, new over pre-existing
588  for proxy in self._properties.values():
589  if cc in proxy.history:
590  proxy.__set__(ccbd, proxy.__get__(cc))
591 
592  # consolidate
593  cc = ccbd
594  return cc
595 
596  def getChildren(self):
597  return self.__children[:] # read only
598 
599  def getTools(self):
600  return self.__tools.values() # read only
601 
602  def children(self):
603  log.error("children() is deprecated, use getChildren() instead for consistency")
604  log.error(
605  "getChildren() returns a copy; to add a child, use 'parent += child'%s",
606  error_explanation,
607  )
608  return self.__children # by ref, for compatibility
609 
610  def getAllChildren(self):
611  """Get all (private) configurable children, both explicit ones (added with +=)
612  and the ones in the private GaudiHandle properties"""
613  childs = []
614  # add private configurable properties (also inside handles)
615  for proxy in self._properties.values():
616  try:
617  c = proxy.__get__(self)
618  except AttributeError:
619  pass
620  else:
621  if isinstance(c, Configurable) and not c.isPublic():
622  childs.append(c)
623  elif isinstance(c, GaudiHandle):
624  try:
625  conf = c.configurable
626  except AttributeError:
627  pass
628  else:
629  if not conf.isPublic():
630  childs.append(conf)
631  elif isinstance(c, GaudiHandleArray):
632  # only setup private arrays
633  if not c.isPublic():
634  for ci in c:
635  if isinstance(ci, Configurable):
636  childs.append(ci)
637  else:
638  try:
639  conf = ci.configurable
640  except AttributeError:
641  pass
642  else:
643  childs.append(conf)
644 
645  # add explicit children
646  childs += self.__children
647  return childs
648 
649  def getSequence(self):
650  elems = []
651  for c in self.__children:
652  elems.append(c.getFullName())
653  return elems
654 
655  def setup(self):
656  # make sure base class init has been called
657  if not hasattr(self, "_initok") or not self._initok:
658  # could check more, but this is the only explanation
659  raise TypeError(
660  "Configurable.__init__ not called in %s override"
661  % self.__class__.__name__
662  )
663 
664  # log.debug("calling setup() on " + self.getFullJobOptName())
665 
666  # setup self: this collects all values on the python side
667  self.__setupServices()
668  self.__setupDlls()
669  self.__setupDefaults()
670 
671  # setup children
672  for c in self.getAllChildren():
673  c.setup()
674 
675  # now get handle to work with for moving properties into the catalogue
676  handle = self.getHandle()
677  if not handle:
678  log.debug("no handle for %s: not transporting properties", self._name)
679  return # allowed, done early
680 
681  # pass final set of properties on to handle on the C++ side or JobOptSvc
682  for name in self._properties.keys():
683  if hasattr(self, name): # means property has python-side value/default
684  setattr(handle, name, getattr(self, name))
685 
686  # for debugging purposes
687  self._setupok = True
688 
689  def getProperties(self):
690  props = {}
691  for name, proxy in self._properties.items():
692  try:
693  props[name] = proxy.__get__(self)
694  except AttributeError:
695  props[name] = Configurable.propertyNoValue
696 
697  return props
698 
700  """Get all properties with their description string as { name : (value, desc) }."""
701  props = {}
702  for name, proxy in self._properties.items():
703  try:
704  props[name] = (proxy.__get__(self), proxy.__doc__)
705  except AttributeError:
706  props[name] = (Configurable.propertyNoValue, proxy.__doc__)
707  return props
708 
710  props = {}
711  for name, proxy in self._properties.items():
712  if self.isPropertySet(name):
713  value = proxy.__get__(self)
714  if hasattr(value, "getFullName"):
715  value = value.getFullName()
716  elif type(value) in [list, tuple]:
717  new_value = []
718  for i in value:
719  if hasattr(i, "getFullName"):
720  new_value.append(i.getFullName())
721  else:
722  new_value.append(i)
723  value = type(value)(new_value)
724  elif type(value) is dict:
725  new_value = {}
726  for i in value:
727  if hasattr(value[i], "getFullName"):
728  new_value[i] = value[i].getFullName()
729  else:
730  new_value[i] = value[i]
731  value = new_value
732  props[name] = value
733 
734  return props
735 
736  def properties(self):
737  return self.getProperties() # compatibility
738 
739  @classmethod
741  class collector:
742  pass
743 
744  # user provided defaults
745  c = collector()
746  cls.setDefaults(c)
747 
748  # defaults from C++
749  for k, v in cls._properties.items():
750  if k not in c.__dict__ and hasattr(v, "default"):
751  c.__dict__[k] = v.default
752 
753  return c.__dict__
754 
755  @classmethod
756  def getDefaultProperty(cls, name):
757  class collector:
758  pass
759 
760  # user provided defaults
761  c = collector()
762  cls.setDefaults(c)
763 
764  if name in c.__dict__:
765  return c.__dict__[name]
766 
767  # defaults from C++
768  try:
769  v = cls._properties[name]
770  if hasattr(v, "default"):
771  return v.default
772  except KeyError:
773  pass
774 
775  return None
776 
777  def getProp(self, name):
778  """Returns the value of the given property."""
779  if hasattr(self, name):
780  return getattr(self, name)
781  else:
782  return self.getDefaultProperties()[name]
783 
784  def setProp(self, name, value):
785  """Set the value of a given property"""
786  return setattr(self, name, value)
787 
788  def isPropertySet(self, name):
789  """Tell if the property 'name' has been set or not.
790 
791  Because of a problem with list and dictionary properties, in those cases
792  if the value is equal to the default, the property is considered as not
793  set.
794  """
795  if not hasattr(self, name):
796  return False
797  default = self.getDefaultProperty(name)
798  if isinstance(default, (list, dict, DataHandle)):
799  value = getattr(self, name)
800  return value != default
801  return True
802 
803  def getType(cls):
804  return cls.__name__
805 
806  def getName(self):
807  return self._name
808 
809  def name(self):
810  return self.getName()
811 
812  def getJobOptName(self): # full hierachical name
813  return self.getName()
814 
815  def isPublic(self):
816  return True
817 
818  # for a couple of existing uses out there
819  def jobOptName(self):
820  log.error(
821  "jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
822  error_explanation,
823  )
824  return self.getJobOptName() # compatibility
825 
826  def getFullName(self):
827  return str(self.getType() + "/" + self.getName())
828 
829  def getFullJobOptName(self):
830  return "%s/%s" % (self.getType(), self.getJobOptName() or self.getName())
831 
832  def getPrintTitle(self):
833  return self.getGaudiType() + " " + self.getTitleName()
834 
835  def getTitleName(self):
836  if log.isEnabledFor(logging.DEBUG):
837  return self.getFullJobOptName()
838  else:
839  return self.getFullName()
840 
841  def setDefaults(cls, handle):
842  pass
843 
844  def clone(self, name=None, **kwargs):
845  if not name:
846  if hasattr(self, "DefaultedName"):
847  name = self.DefaultedName
848  else:
849  name = self.getType()
850 
851  newconf = Configurable.__new__(self.__class__, name)
852  self.__class__.__init__(newconf, name)
853 
854  for proxy in self._properties.values():
855  try:
856  value = proxy.__get__(self)
857  if type(value) in [str, list, dict, tuple]:
858  # clone the values of the properties for basic types
859  value = type(value)(value)
860  proxy.__set__(newconf, value)
861  except AttributeError:
862  pass
863 
864  for c in self.__children:
865  newconf += c # processes proper copy semantics
866 
867  for n, t in self.__tools.items():
868  newconf.addTool(t, n)
869 
870  for name, value in kwargs.items():
871  setattr(newconf, name, value)
872 
873  return newconf
874 
875  def splitName(self):
876  fullname = self.getName()
877  dot = fullname.find(".")
878  if dot != -1:
879  parentname = fullname[:dot]
880  longname = fullname[dot + 1 :]
881  else:
882  parentname = ""
883  longname = fullname
884  dot = longname.find(".")
885  if dot != -1:
886  name = longname[:dot]
887  else:
888  name = longname
889  return parentname, name, longname
890 
891  def addTool(self, tool, name=None):
892  if isclass(tool) and issubclass(tool, ConfigurableAlgTool):
893  if name is None:
894  name = tool.__name__
895  priv_tool = tool(self.getName() + "." + name)
896  elif isinstance(tool, ConfigurableAlgTool):
897  if name is None:
898  name = tool.splitName()[1]
899  priv_tool = tool.clone(self.getName() + "." + name)
900  else:
901  if isclass(tool):
902  classname = tool.__name__
903  else:
904  classname = type(tool).__name__
905  raise TypeError(
906  "addTool requires AlgTool configurable. Got %s type" % classname
907  )
908  self.__tools[name] = priv_tool
909  if name in self.__slots__:
910  # this is to avoid that the property hides the tool
911  setattr(self, name, self.__tools[name])
912  return self.__tools[name]
913 
914  def _isInSetDefaults(self):
915  return self._inSetDefaults
916 
917  def __setupServices(self):
918  # svcs = self.getServices()
919  # if not svcs:
920  svcs = []
921  # elif type(svcs) == types.StringType:
922  # svcs = [ svcs ]
923 
924  import __main__
925 
926  for svc in svcs:
927  handle = __main__.Service(svc) # noqa: F841 (used in eval below)
928  # services should be configurables as well, but aren't for now
929  # handle.setup()
930 
931  # allow Configurable to make some changes
932  if hasattr(self, "configure" + svc):
933  eval("self.configure" + svc + "( handle )")
934 
935  def __setupDlls(self):
936  dlls = self.getDlls()
937  if not dlls:
938  dlls = []
939  elif isinstance(dlls, types.StringType):
940  dlls = [dlls]
941 
942  from __main__ import theApp
943 
944  dlls = filter(lambda d: d not in theApp.Dlls, dlls)
945  if dlls:
946  theApp.Dlls += dlls
947 
948  def __setupDefaults(self):
949  # set handle defaults flags to inform __setattr__ that it is being
950  # called during setDefaults of the concrete Configurable
951  self._inSetDefaults = True
952  self.setDefaults(self)
953  self._inSetDefaults = False
954 
955  @staticmethod
956  def _printHeader(indentStr, title):
957  preLen = Configurable.printHeaderPre
958  postLen = (
959  Configurable.printHeaderWidth - preLen - 3 - len(title)
960  ) # - len(indentStr)
961  postLen = max(preLen, postLen)
962  return indentStr + "/%s %s %s" % (preLen * "*", title, postLen * "*")
963 
964  @staticmethod
965  def _printFooter(indentStr, title):
966  preLen = Configurable.printHeaderPre
967  postLen = (
968  Configurable.printHeaderWidth - preLen - 12 - len(title)
969  ) # - len(indentStr)
970  postLen = max(preLen, postLen)
971  return indentStr + "\\%s (End of %s) %s" % (preLen * "-", title, postLen * "-")
972 
973  def __repr__(self):
974  return "{0}({1!r})".format(self.__class__.__name__, self.name())
975 
976  def __str__(self, indent=0, headerLastIndentUnit=indentUnit):
977  global log # to print some info depending on output level
978  indentStr = indent * Configurable.indentUnit
979  # print header
980  title = self.getPrintTitle()
981  # print line to easily see start-of-configurable
982  if indent > 0:
983  headerIndent = (indent - 1) * Configurable.indentUnit + headerLastIndentUnit
984  else:
985  headerIndent = ""
986  rep = Configurable._printHeader(headerIndent, title)
987  rep += os.linesep
988  # print own properties
989  props = self.getProperties()
990  defs = self.getDefaultProperties()
991  if not props:
992  rep += indentStr + "|-<no properties>" + os.linesep
993  else:
994  # get property name with
995  nameWidth = 0
996  for p in props.keys():
997  nameWidth = max(nameWidth, len(p))
998  for p, v in props.items():
999  # start with indent and property name
1000  prefix = indentStr + "|-%-*s" % (nameWidth, p)
1001  # add memory address for debugging (not for defaults)
1002  if log.isEnabledFor(logging.DEBUG):
1003  if v != Configurable.propertyNoValue:
1004  address = " @%11s" % hex(id(v))
1005  else:
1006  address = 13 * " "
1007  prefix += address
1008  # add value and default
1009  default = defs.get(p)
1010  if v == Configurable.propertyNoValue:
1011  # show default value as value, and no extra 'default'
1012  strVal = repr(default)
1013  strDef = None
1014  else:
1015  # convert configurable to handle
1016  if hasattr(v, "getGaudiHandle"):
1017  vv = v.getGaudiHandle()
1018  else:
1019  vv = v
1020  if isinstance(vv, (GaudiHandle, GaudiHandleArray, DataHandle)):
1021  strVal = repr(vv)
1022  # the default may not be a GaudiHandle (?)
1023  if hasattr(default, "toStringProperty"):
1024  strDef = repr(default.toStringProperty())
1025  else:
1026  strDef = repr(default)
1027  if strDef == repr(vv.toStringProperty()):
1028  strDef = None
1029  else:
1030  strVal = repr(vv)
1031  strDef = repr(default)
1032  # add the value
1033  line = prefix + " = " + strVal
1034  # add default if present
1035  if strDef is not None:
1036  # put default on new line if too big
1037  if len(line) + len(strDef) > Configurable.printHeaderWidth:
1038  line += (
1039  os.linesep
1040  + indentStr
1041  + "| "
1042  + (len(prefix) - len(indentStr) - 3) * " "
1043  )
1044  line += " (default: %s)" % (strDef,)
1045  # add the line to the total string
1046  rep += line + os.linesep
1047  # print out full private configurables
1048  # if isinstance(v,Configurable) and not v.isPublic():
1049 
1054 
1055  # print configurables + their properties, or loop over sequence
1056  # for cfg in self.__children:
1057  for cfg in self.getAllChildren():
1058  rep += cfg.__str__(indent + 1, "|=") + os.linesep
1059 
1060  # print line to easily see end-of-configurable. Note: No linesep!
1061  rep += Configurable._printFooter(indentStr, title)
1062  return rep
1063 
1064  def isApplicable(self):
1065  """
1066  Return True is the instance can be "applied".
1067  Always False for plain Configurable instances
1068  (i.e. not ConfigurableUser).
1069  """
1070  return False
1071 
1072 
1073 # classes for generic Gaudi component ===========
1074 
1075 
1076 class DummyDescriptor(object):
1077  def __init__(self, name):
1078  self.__name__ = name # conventional
1079 
1080  def __get__(self, obj, type=None):
1081  return getattr(obj, self.__name__)
1082 
1083  def __set__(self, obj, value):
1084  object.__setattr__(obj, self.__name__, value)
1085 
1086 
1088  # __slots__ = { }
1089 
1090  def __init__(self, name=Configurable.DefaultName):
1091  Configurable.__init__(self, name)
1092  self._name = name
1093  self._properties = {}
1094 
1095  def __deepcopy__(self, memo):
1096  return self # algorithms are always shared
1097 
1098  @classmethod
1099  def getGaudiType(cls):
1100  return "GenericComponent"
1101 
1102  def getDlls(self):
1103  pass
1104 
1105  def getHandle(self):
1106  pass
1107 
1108  def __setattr__(self, name, value):
1109  # filter private (user) variables
1110  if name[0] == "_":
1111  super(ConfigurableGeneric, self).__setattr__(name, value)
1112  return
1113 
1114  # filter configurable types
1115  if isinstance(value, Configurable):
1116  self.__dict__[name] = value
1117  return
1118 
1119  # assume all the rest are properties
1120  if name not in self._properties:
1121  self._properties[name] = PropertyProxy(DummyDescriptor(name))
1122  self._properties[name].__set__(self, value)
1123 
1124  def getJobOptName(self):
1125  return None
1126 
1127 
1128 # base classes for individual Gaudi algorithms/services/algtools ===========
1130  __slots__ = {
1131  "_jobOptName": 0,
1132  "OutputLevel": 0,
1133  "Enable": 1,
1134  "ErrorMax": 1,
1135  "ErrorCount": 0,
1136  "AuditAlgorithms": 0,
1137  "AuditInitialize": 0,
1138  "AuditReinitialize": 0,
1139  "AuditExecute": 0,
1140  "AuditFinalize": 0,
1141  }
1142 
1143  def __init__(self, name=Configurable.DefaultName):
1144  super(ConfigurableAlgorithm, self).__init__(name)
1145  name = self.getName()
1146  self._jobOptName = name[name.find("/") + 1 :] # strips class
1147 
1148  def __deepcopy__(self, memo):
1149  return self # algorithms are always shared
1150 
1151  def getHandle(self):
1152  return iAlgorithm( # noqa: F821 (to avoid circular dependeny)
1153  self.getJobOptName()
1154  )
1155 
1156  @classmethod
1157  def getGaudiType(cls):
1158  return "Algorithm"
1159 
1160  def getJobOptName(self):
1161  return self._jobOptName
1162 
1163  # mimick the ControlFlowLeaf interface
1164  def __and__(self, rhs):
1165  if rhs is CFTrue:
1166  return self
1167  elif rhs is CFFalse:
1168  return CFFalse
1169  return AndNode(self, rhs)
1170 
1171  def __or__(self, rhs):
1172  if rhs is CFFalse:
1173  return self
1174  elif rhs is CFTrue:
1175  return CFTrue
1176  return OrNode(self, rhs)
1177 
1178  def __invert__(self):
1179  return InvertNode(self)
1180 
1181  def __rshift__(self, rhs):
1182  return OrderedNode(self, rhs)
1183 
1184  def visitNode(self, visitor):
1185  visitor.enter(self)
1186  self._visitSubNodes(visitor)
1187  visitor.leave(self)
1188 
1189  def _visitSubNodes(self, visitor):
1190  pass
1191 
1192  def __eq__(self, other):
1193  return repr(self) == repr(other)
1194 
1195  def __hash__(self):
1196  """Return a unique identifier for this object.
1197 
1198  As we use the `repr` of this object to check for equality, we use it
1199  here to define uniqueness.
1200  """
1201  # The hash of the 1-tuple containing the repr of this object
1202  return hash((repr(self),))
1203 
1204 
1206  __slots__ = {
1207  "OutputLevel": 0,
1208  "AuditServices": 0,
1209  "AuditInitialize": 0,
1210  "AuditFinalize": 0,
1211  }
1212 
1213  def __deepcopy__(self, memo):
1214  return self # services are always shared
1215 
1216  def copyChild(self, child):
1217  # Copy private tools but all else is shared
1218  if isinstance(child, ConfigurableAlgTool) and not child.isPublic():
1219  return copy.deepcopy(child)
1220  else:
1221  return child
1222 
1223  def getHandle(self):
1224  return iService(self._name) # noqa: F821 (to avoid circular dependeny)
1225 
1226  @classmethod
1227  def getGaudiType(cls):
1228  return "Service"
1229 
1230  def getGaudiHandle(self):
1231  return ServiceHandle(self.toStringProperty())
1232 
1233  def toStringProperty(self):
1234  # called on conversion to a string property for the jocat
1235  return self.getName()
1236 
1237 
1239  __slots__ = {
1240  "_jobOptName": "",
1241  "OutputLevel": 0,
1242  "AuditTools": 0,
1243  "AuditInitialize": 0,
1244  "AuditFinalize": 0,
1245  }
1246 
1247  def __init__(self, name=Configurable.DefaultName):
1248  super(ConfigurableAlgTool, self).__init__(name)
1249  if "." not in self._name:
1250  # Public tools must have ToolSvc as parent
1251  self._name = "ToolSvc." + self._name
1252  name = self.getName()
1253  name = name[name.find("/") + 1 :] # strips class, if any
1254  self._jobOptName = name
1255 
1256  def getHandle(self):
1257  # iAlgTool isn't useful, unless one knows for sure that the tool exists
1258  return iProperty( # noqa: F821 (to avoid circular dependeny)
1259  self.getJobOptName()
1260  )
1261 
1262  @classmethod
1263  def getGaudiType(cls):
1264  return "AlgTool"
1265 
1266  def getGaudiHandle(self):
1267  if self.isPublic():
1268  return PublicToolHandle(self.toStringProperty())
1269  else:
1270  return PrivateToolHandle(self.toStringProperty())
1271 
1272  def getPrintTitle(self):
1273  if self.isPublic():
1274  pop = "Public "
1275  else:
1276  pop = "Private "
1277  return pop + Configurable.getPrintTitle(self)
1278 
1279  def setParent(self, parentName):
1280  # print "ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName)
1281  # print "Calling stack:"
1282  # import traceback
1283  # traceback.print_stack()
1284  # propagate parent to AlgTools in children
1285  for c in self.getAllChildren():
1286  if isinstance(c, ConfigurableAlgTool):
1287  c.setParent(parentName)
1288 
1289  # update my own parent
1290  name = self.getName()
1291  name = name[name.rfind(".") + 1 :] # Name of the instance
1292  self._jobOptName = self._name = parentName + "." + name
1293 
1294  def getParent(self):
1295  dot = self._jobOptName.rfind(".")
1296  if dot != -1:
1297  return self._jobOptName[:dot]
1298  else:
1299  return ""
1300 
1301  def hasParent(self, parent):
1302  return self._jobOptName.startswith(parent + ".")
1303 
1304  def getJobOptName(self):
1305  return self._jobOptName
1306 
1307  def isPublic(self):
1308  return self.isInToolSvc()
1309 
1310  def isInToolSvc(self):
1311  (parent, child) = self._jobOptName.rsplit(".", 1)
1312  return parent == "ToolSvc"
1313 
1314  def toStringProperty(self):
1315  # called on conversion to a string property for the jocat
1316  return self.getFullName()
1317 
1318  def getFullName(self):
1319  # for Tools, the "full name" means "Type/LocalName",
1320  # without the names of the parents
1321  name = self.getName()
1322  # strip off everything before the last '.'
1323  name = name[name.rfind(".") + 1 :]
1324  return str(self.getType() + "/" + name)
1325 
1326 
1327 # FIXME: this is just a placeholder, waiting for a real implementation
1328 # It is sufficient to get us going... (and import a PkgConf which
1329 # happens to contain an Auditor...)
1331  __slots__ = {"_jobOptName": 0, "OutputLevel": 0, "Enable": 1}
1332 
1333  def __init__(self, name=Configurable.DefaultName):
1334  super(ConfigurableAuditor, self).__init__(name)
1335  name = self.getName()
1336  name = name[name.find("/") + 1 :] # strips class, if any
1337  self._jobOptName = name
1338 
1339  def getHandle(self):
1340  # iAlgTool isn't useful, unless one knows for sure that the tool exists
1341  return iProperty( # noqa: F821 (to avoid circular dependeny)
1342  self.getJobOptName()
1343  )
1344 
1345  @classmethod
1346  def getGaudiType(cls):
1347  return "Auditor"
1348 
1349  def getJobOptName(self):
1350  return self._jobOptName
1351 
1352  def toStringProperty(self):
1353  # called on conversion to a string property for the jocat
1354  return self.getType() + "/" + self.getName()
1355 
1356 
1358  __slots__ = {
1359  "__users__": [],
1360  "__used_instances__": [],
1361  "_enabled": True,
1362  "_applied": False,
1363  }
1364  # list of ConfigurableUser classes this one is going to modify in the
1365  # __apply_configuration__ method.
1366  # The list may contain class objects, strings representing class objects or
1367  # tuples with the class object (or a string) as first element and the instance
1368  # name as second element.
1369  # If the instance name is None or not present, the function _instanceName()
1370  # is used to determine the name of the instance (the default implementation
1371  # returns "<this name>_<other name>".
1372  __used_configurables__ = []
1373  # list of ConfigurableUser classes this one is going to query in the
1374  # __apply_configuration__ method
1375  __queried_configurables__ = []
1376 
1377  def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs):
1378  super(ConfigurableUser, self).__init__(name)
1379  for n, v in kwargs.items():
1380  setattr(self, n, v)
1381  self._enabled = _enabled
1382  self.__users__ = []
1383  self._applied = False
1384 
1385  # Needed to retrieve the actual class if the declaration in __used_configurables__
1386  # and __queried_configurables__ is done with strings.
1387  from GaudiKernel.ConfigurableDb import getConfigurable as confDbGetConfigurable
1388 
1389  # Set the list of users of the used configurables
1390  #
1392  for used in self.__used_configurables__:
1393  # By default we want to use the default name of the instances
1394  # for the used configurables
1395  used_name = Configurable.DefaultName
1396  # If the entry in the list is a tuple, we need a named instance
1397  if type(used) is tuple:
1398  used, used_name = used # we re-set used to re-use the code below
1399  if not used_name:
1400  used_name = self._instanceName(used)
1401  # Check is 'used' is a string or not
1402  if type(used) is str:
1403  used_class = confDbGetConfigurable(used)
1404  else:
1405  used_class = used
1406  # Instantiate the configurable that we are going to use
1407  try:
1408  inst = used_class(name=used_name, _enabled=False)
1409  except AttributeError:
1410  # This cover the case where the used configurable is not a
1411  # ConfigurableUser instance, i.e. id doesn't have the attribute
1412  # '_enabled'.
1413  inst = used_class(name=used_name)
1414  self.__addActiveUseOf(inst)
1415  for queried in self.__queried_configurables__:
1416  try:
1417  if type(queried) is str:
1418  queried = confDbGetConfigurable(queried)
1419  inst = queried(_enabled=False)
1420  except AttributeError:
1421  inst = queried()
1422  self.__addPassiveUseOf(inst)
1423 
1424  def __addActiveUseOf(self, other):
1425  """
1426  Declare that we are going to modify the Configurable 'other' in our
1427  __apply_configuration__.
1428  """
1429  self.__used_instances__.append(other)
1430  if hasattr(other, "__users__"): # allow usage of plain Configurables
1431  other.__users__.append(self)
1432 
1433  def __addPassiveUseOf(self, other):
1434  """
1435  Declare that we are going to retrieve property values from the
1436  ConfigurableUser 'other' in our __apply_configuration__.
1437  """
1438  if not isinstance(other, ConfigurableUser):
1439  raise Error(
1440  "'%s': Cannot make passive use of '%s', it is not a ConfigurableUser"
1441  % (self.name(), other.name())
1442  )
1443  other.__addActiveUseOf(self)
1444 
1445  @classmethod
1446  def getGaudiType(cls):
1447  return "User"
1448 
1449  def getDlls(self):
1450  return None
1451 
1452  def getHandle(self):
1453  return None
1454 
1455  def __detach_used__(self):
1456  """
1457  Remove this ConfigurableUser instance from the users list of the used
1458  instances.
1459  """
1460  for used in self.__used_instances__:
1461  if hasattr(used, "__users__"): # allow usage of plain Configurables
1462  used.__users__.remove(self)
1463 
1464  def propagateProperty(self, name, others=None, force=True):
1465  """
1466  Propagate the property 'name' (if set) to other configurables (if possible).
1467  'others' can be:
1468  None:
1469  propagate to all the entries in __used_configurables__
1470  a configurable instance:
1471  propagate only to it
1472  list of configurable instances:
1473  propagate to all of them.
1474 
1475 
1476  The logic is:
1477  - if the local property is set, the other property will be overwritten
1478  - local property not set and other set => keep other
1479  - local property not set and other not set => overwrite the default for
1480  ConfigurableUser instances and set the property for Configurables
1481  """
1482  # transform 'others' to a list of configurable instances
1483  if others is None:
1484  others = self.__used_instances__
1485  elif type(others) not in [list, tuple]:
1486  others = [others]
1487  # these can be computed before the loop
1488  local_is_set = self.isPropertySet(name)
1489  value = self.getProp(name)
1490  # loop over the others that do have 'name' in their slots
1491  for other in [o for o in others if name in o.__slots__]:
1492  # If self property is set, use it
1493  if local_is_set:
1494  if other.isPropertySet(name):
1495  log.warning(
1496  "Property '%(prop)s' is set in both '%(self)s' and '%(other)s', using '%(self)s.%(prop)s'"
1497  % {"self": self.name(), "other": other.name(), "prop": name}
1498  )
1499  other.setProp(name, value)
1500  # If not, and other property also not set, propagate the default
1501  elif not other.isPropertySet(name):
1502  if isinstance(other, ConfigurableUser):
1503  otherType = type(other._properties[name].getDefault())
1504  other._properties[name].setDefault(value)
1505  if otherType in [list, dict]:
1506  # Special case for list and dictionaries:
1507  # also set the property to the same value of the default (copy)
1508  other.setProp(name, otherType(value))
1509  else:
1510  other.setProp(name, value)
1511  # If not set and other set, do nothing
1512 
1513  def propagateProperties(self, names=None, others=None, force=True):
1514  """
1515  Call propagateProperty for each property listed in 'names'.
1516  If 'names' is None, all the properties are propagated.
1517  """
1518  if names is None:
1519  # use all the non-private slots
1520  names = [p for p in self.__slots__ if not p.startswith("_")]
1521  for n in names:
1522  self.propagateProperty(n, others, force)
1523 
1525  """
1526  Function to be overridden to convert the high level configuration into a
1527  low level one.
1528  The default implementation calls applyConf, which is the method defined
1529  in some ConfigurableUser implementations.
1530  """
1531  return self.applyConf()
1532 
1533  def applyConf(self):
1534  """
1535  Function to be overridden to convert the high level configuration into a
1536  low level one.
1537  """
1538  pass
1539 
1540  def _instanceName(self, cls):
1541  """
1542  Function used to define the name of the private instance of a given class
1543  name.
1544  This method is used when the __used_configurables_property__ declares the
1545  need of a private used configurable without specifying the name.
1546  """
1547  if type(cls) is str:
1548  clName = cls
1549  else:
1550  clName = cls.__name__
1551  return "%s_%s" % (self.name(), clName)
1552 
1553  def getUsedInstance(self, name):
1554  """
1555  Return the used instance with a given name.
1556  """
1557  for i in self.__used_instances__:
1558  if i.name() == name:
1559  if hasattr(i, "_enabled"):
1560  # ensure that the instances retrieved through the method are
1561  # enabled
1562  i._enabled = True
1563  return i
1564  raise KeyError(name)
1565 
1566  def isApplicable(self):
1567  """
1568  Return True is the instance can be "applied".
1569  """
1570  return (not self.__users__) and (not self._applied)
1571 
1572 
1573 # list of callables to be called after all the __apply_configuration__ are called.
1574 postConfigActions = []
1575 
1576 
1578  """
1579  Add a new callable ('function') to the list of post-configuration actions.
1580  If the callable is already in the list, it is moved to the end of the list.
1581  The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1582  """
1583  try:
1584  postConfigActions.remove(function)
1585  except Exception:
1586  pass
1587  postConfigActions.append(function)
1588 
1589 
1591  """
1592  Remove a callable from the list of post-config actions.
1593  The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1594  """
1595  postConfigActions.remove(function)
1596 
1597 
1598 _appliedConfigurableUsers_ = False
1599 
1600 
1602  """
1603  Call the apply method of all the ConfigurableUser instances respecting the
1604  dependencies. First the C.U.s that are not used by anybody, then the used
1605  ones, when they are not used anymore.
1606  """
1607  # Avoid double calls
1608  global _appliedConfigurableUsers_, postConfigActions
1609  if _appliedConfigurableUsers_:
1610  return
1611  _appliedConfigurableUsers_ = True
1612 
1613  def applicableConfUsers():
1614  """
1615  Generator returning all the configurables that can be applied in the
1616  order in which they can be applied.
1617  """
1618  # This is tricky...
1619  # We keep on looking for the first configurable that can be applied.
1620  # When we cannot find any, 'next()' raises a StopIteration that is
1621  # propagated outside of the infinite loop and the function, then handled
1622  # correctly from outside (it is the exception that is raised when you
1623  # exit from a generator).
1624  # Checking every time the full list is inefficient, but it is the
1625  # easiest way to fix bug #103803.
1626  # <https://savannah.cern.ch/bugs/?103803>
1627  while True:
1628  try:
1629  yield next(
1630  c
1631  for c in Configurable.allConfigurables.values()
1632  if c.isApplicable()
1633  )
1634  except StopIteration:
1635  break
1636 
1637  debugApplyOrder = "GAUDI_DUBUG_CONF_USER" in os.environ
1638  for c in applicableConfUsers():
1639  if c._enabled:
1640  log.info("applying configuration of %s", c.name())
1641  if debugApplyOrder:
1642  sys.stderr.write("applying %r" % c)
1643  c.__apply_configuration__()
1644  log.info(c)
1645  else:
1646  log.info("skipping configuration of %s", c.name())
1647  c._applied = True # flag the instance as already applied
1648  if hasattr(c, "__detach_used__"):
1649  # tells the used configurables that they are not needed anymore
1650  c.__detach_used__()
1651 
1652  # check for dependency loops
1653  leftConfUsers = [
1654  c
1655  for c in Configurable.allConfigurables.values()
1656  if hasattr(c, "__apply_configuration__") and c._enabled and not c._applied
1657  ]
1658  # if an enabled configurable has not been applied, there must be a dependency loop
1659  if leftConfUsers:
1660  raise Error(
1661  "Detected loop in the ConfigurableUser"
1662  " dependencies: %r" % [c.name() for c in leftConfUsers]
1663  )
1664  # ensure that all the Handles have been triggered
1665  known = set()
1666  unknown = set(Configurable.allConfigurables)
1667  while unknown:
1668  for k in unknown:
1669  if not known: # do not print during the first iteration
1670  log.debug("new configurable created automatically: %s", k)
1671  # this trigger the instantiation from handles
1672  Configurable.allConfigurables[k].properties()
1673  known.add(k)
1674  unknown -= known
1675  # Call post-config actions
1676  for action in postConfigActions:
1677  action()
1678 
1679 
1681  """
1682  Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1683  backward compatibility for configurations that where relying (implicitly) on
1684  bug #103803, or on a specific (non guaranteed) order of execution.
1685 
1686  @see applyConfigurableUsers()
1687  """
1688  # Avoid double calls
1689  global _appliedConfigurableUsers_, postConfigActions
1690  if _appliedConfigurableUsers_:
1691  return
1692  _appliedConfigurableUsers_ = True
1693 
1694  debugApplyOrder = "GAUDI_DUBUG_CONF_USER" in os.environ
1695  confUsers = [
1696  c
1697  for c in Configurable.allConfigurables.values()
1698  if hasattr(c, "__apply_configuration__")
1699  ]
1700  applied = True # needed to detect dependency loops
1701  while applied and confUsers:
1702  newConfUsers = [] # list of conf users that cannot be applied yet
1703  applied = False
1704  for c in confUsers:
1705  if hasattr(c, "__users__") and c.__users__:
1706  newConfUsers.append(c) # cannot use this one yet
1707  else: # it does not have users or the list is empty
1708  applied = True
1709  # the ConfigurableUser is enabled if it doesn't have an _enabled
1710  # property or its value is True
1711  enabled = (not hasattr(c, "_enabled")) or c._enabled
1712  if enabled:
1713  log.info("applying configuration of %s", c.name())
1714  if debugApplyOrder:
1715  sys.stderr.write("applying %r" % c)
1716  c.__apply_configuration__()
1717  log.info(c)
1718  else:
1719  log.info("skipping configuration of %s", c.name())
1720  if hasattr(c, "__detach_used__"):
1721  # tells the used configurables that they are not needed anymore
1722  c.__detach_used__()
1723  confUsers = newConfUsers # list of C.U.s still to go
1724  if confUsers:
1725  # this means that some C.U.s could not be applied because of a dependency loop
1726  raise Error(
1727  "Detected loop in the ConfigurableUser "
1728  " dependencies: %r" % [c.name() for c in confUsers]
1729  )
1730  # ensure that all the Handles have been triggered
1731  known = set()
1732  unknown = set(Configurable.allConfigurables)
1733  while unknown:
1734  for k in unknown:
1735  if not known: # do not print during the first iteration
1736  log.debug("new configurable created automatically: %s", k)
1737  # this trigger the instantiation from handles
1738  Configurable.allConfigurables[k].properties()
1739  known.add(k)
1740  unknown -= known
1741  # Call post-config actions
1742  for action in postConfigActions:
1743  action()
1744 
1745 
1747  """
1748  Function to select all and only the configurables that have to be used in
1749  GaudiPython.AppMgr constructor.
1750  This is needed because in Athena the implementation have to be different (the
1751  configuration is used in a different moment).
1752  """
1753  return sorted(
1754  k
1755  for k, v in Configurable.allConfigurables.items()
1756  if v.getGaudiType() != "User"
1757  ) # Exclude ConfigurableUser instances
1758 
1759 
1760 def purge():
1761  """
1762  Clean up all configurations and configurables.
1763  """
1764  for c in Configurable.allConfigurables.values():
1765  c.__class__.configurables.clear()
1766  Configurable.allConfigurables.clear()
1767  # FIXME: (MCl) this is needed because instances of ConfigurableGeneric are not
1768  # migrated to the correct class when this is known.
1769  ConfigurableGeneric.configurables.clear()
1770  import os.path
1771  import sys
1772 
1773  from .ProcessJobOptions import _included_files
1774 
1775  for file in _included_files:
1776  dirname, basname = os.path.split(file)
1777  basname, ext = os.path.splitext(basname)
1778  if basname in sys.modules:
1779  del sys.modules[basname]
1780  _included_files.clear()
1781 
1782 
1784  def __init__(self):
1785  self.stack = []
1786 
1787  @property
1788  def sequence(self):
1789  return self.stack[-1]
1790 
1791  def enter(self, visitee):
1792  pass
1793 
1794  def _getUniqueName(self, prefix):
1795  from Gaudi.Configuration import allConfigurables
1796 
1797  cnt = 0
1798  name = prefix + str(cnt)
1799  while name in allConfigurables:
1800  cnt += 1
1801  name = prefix + str(cnt)
1802  return name
1803 
1804  def _newSeq(self, prefix="seq_", **kwargs):
1805  from Configurables import Gaudi__Sequencer
1806 
1807  return Gaudi__Sequencer(self._getUniqueName("seq_"), **kwargs)
1808 
1809  def leave(self, visitee):
1810  stack = self.stack
1811  if visitee in (CFTrue, CFFalse):
1812  stack.append(self._newSeq(Invert=visitee is CFFalse))
1813  elif isinstance(visitee, (ControlFlowLeaf, ConfigurableAlgorithm)):
1814  stack.append(visitee)
1815  elif isinstance(visitee, (OrNode, AndNode, OrderedNode)):
1816  b = stack.pop()
1817  a = stack.pop()
1818  seq = self._newSeq(
1819  Members=[a, b],
1820  ModeOR=isinstance(visitee, OrNode),
1821  ShortCircuit=not isinstance(visitee, OrderedNode),
1822  )
1823  stack.append(seq)
1824  elif isinstance(visitee, ignore):
1825  if hasattr(stack[-1], "IgnoreFilterPassed"):
1826  stack[-1].IgnoreFilterPassed = True
1827  else:
1828  stack.append(
1829  self._newSeq(Members=[stack.pop()], IgnoreFilterPassed=True)
1830  )
1831  elif isinstance(visitee, InvertNode):
1832  if hasattr(stack[-1], "Invert"):
1833  stack[-1].Invert = True
1834  else:
1835  stack.append(self._newSeq(Members=[stack.pop()], Invert=True))
1836 
1837 
1838 def makeSequences(expression):
1839  """
1840  Convert a control flow expression to nested GaudiSequencers.
1841  """
1842  if not isinstance(expression, ControlFlowNode):
1843  raise ValueError(
1844  "ControlFlowNode instance expected, got %s" % type(expression).__name__
1845  )
1846  visitor = CreateSequencesVisitor()
1847  expression.visitNode(visitor)
1848  return visitor.sequence
1849 
1850 
1852  """
1853  Helper class to use a ControlFlowNode as an algorithm configurable
1854  instance.
1855  """
1856 
1857  def __new__(cls, name=None, **kwargs):
1858  if name is None:
1859  name = cls.__name__
1860  if name in Configurable.allConfigurables:
1861  instance = Configurable.allConfigurables[name]
1862  assert type(instance) is cls, (
1863  "trying to reuse {0!r} as name of a {1} instance while it"
1864  "s "
1865  "already used for an instance of {2}"
1866  ).format(name, cls.__name__, type(instance).__name__)
1867  return instance
1868  else:
1869  instance = super(SuperAlgorithm, cls).__new__(cls)
1870  Configurable.allConfigurables[name] = instance
1871  return instance
1872 
1873  def __init__(self, name=None, **kwargs):
1874  self._name = name or self.getType()
1875  self.graph = self._initGraph()
1876  for key in kwargs:
1877  setattr(self, key, kwargs[key])
1878 
1879  @property
1880  def name(self): # name is a read only property
1881  return self._name
1882 
1883  @classmethod
1884  def getType(cls):
1885  return cls.__name__
1886 
1887  # required to be registered in allConfigurables
1888  def properties(self):
1889  pass
1890 
1891  # required to be registered in allConfigurables
1892  def isApplicable(self):
1893  return False
1894 
1895  # required to be registered in allConfigurables
1896  @classmethod
1897  def getGaudiType(cls):
1898  return "User"
1899 
1900  def _makeAlg(self, typ, **kwargs):
1901  """
1902  Instantiate and algorithm of type 'typ' with a name suitable for use
1903  inside a SuperAlgorithm.
1904  """
1905  name = "{0}_{1}".format(self.name, kwargs.pop("name", typ.getType()))
1906  return typ(name, **kwargs)
1907 
1908  def _initGraph(self):
1909  raise NotImplementedError()
1910 
1911  def __repr__(self):
1912  return "{0}({1!r})".format(self.getType(), self.name)
1913 
1914  def _visitSubNodes(self, visitor):
1915  if self.graph:
1916  self.graph.visitNode(visitor)
1917 
1918  def __setattr__(self, name, value):
1919  super(SuperAlgorithm, self).__setattr__(name, value)
1920  if name in ("_name", "graph"):
1921  # do not propagate internal data members
1922  return
1923 
1924  class PropSetter(object):
1925  def enter(self, node):
1926  try:
1927  setattr(node, name, value)
1928  except (ValueError, AttributeError):
1929  # ignore type and name mismatch
1930  pass
1931 
1932  def leave(self, node):
1933  pass
1934 
1935  self._visitSubNodes(PropSetter())
GaudiKernel.Configurable.ConfigurableGeneric
Definition: Configurable.py:1087
GaudiKernel.Configurable.Configurable.allConfigurables
allConfigurables
Definition: Configurable.py:175
GaudiKernel.Configurable.SuperAlgorithm.__repr__
def __repr__(self)
Definition: Configurable.py:1911
GaudiKernel.Configurable.Configurable.getSequence
def getSequence(self)
Definition: Configurable.py:649
GaudiKernel.Configurable.ConfigurableUser
Definition: Configurable.py:1357
GaudiKernel.Configurable.ConfigurableGeneric.getDlls
def getDlls(self)
Definition: Configurable.py:1102
GaudiKernel.Configurable.Configurable.children
def children(self)
Definition: Configurable.py:602
GaudiKernel.Configurable.Configurable.getDefaultProperties
def getDefaultProperties(cls)
Definition: Configurable.py:740
GaudiKernel.Configurable.ConfigurableAlgTool.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1304
GaudiKernel.Configurable.ConfigurableService.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1227
GaudiKernel.Configurable.ConfigurableUser.__used_instances__
__used_instances__
Definition: Configurable.py:1391
MSG::hex
MsgStream & hex(MsgStream &log)
Definition: MsgStream.h:282
GaudiKernel.Configurable.SuperAlgorithm.graph
graph
Definition: Configurable.py:1875
GaudiKernel.Configurable.ConfigurableAlgorithm.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1143
GaudiKernel.Configurable.ConfigurableAlgTool.getFullName
def getFullName(self)
Definition: Configurable.py:1318
GaudiKernel.Configurable.ConfigurableUser._instanceName
def _instanceName(self, cls)
Definition: Configurable.py:1540
GaudiKernel.Configurable.Configurable.__setupDefaults
def __setupDefaults(self)
Definition: Configurable.py:948
GaudiKernel.Configurable.ConfigurableGeneric.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:1095
GaudiKernel.Configurable.ConfigurableUser.applyConf
def applyConf(self)
Definition: Configurable.py:1533
GaudiKernel.Configurable.Configurable.isPropertySet
def isPropertySet(self, name)
Definition: Configurable.py:788
GaudiKernel.Configurable.Configurable.getParent
def getParent(self)
Definition: Configurable.py:570
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:1171
GaudiKernel.Configurable.SuperAlgorithm
Definition: Configurable.py:1851
GaudiKernel.Configurable.Configurable.setProp
def setProp(self, name, value)
Definition: Configurable.py:784
GaudiKernel.Configurable.ConfigurableService.getHandle
def getHandle(self)
Definition: Configurable.py:1223
GaudiKernel.Configurable.ConfigurableGeneric.getHandle
def getHandle(self)
Definition: Configurable.py:1105
GaudiKernel.Configurable.CreateSequencesVisitor
Definition: Configurable.py:1783
GaudiKernel.Configurable.SuperAlgorithm.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:1918
GaudiKernel.Configurable.CreateSequencesVisitor.leave
def leave(self, visitee)
Definition: Configurable.py:1809
GaudiKernel.Configurable.Configurable.hasParent
def hasParent(self, parent)
Definition: Configurable.py:573
GaudiKernel.Configurable.DummyDescriptor.__name__
__name__
Definition: Configurable.py:1078
GaudiKernel.Configurable.ConfigurableUser.propagateProperty
def propagateProperty(self, name, others=None, force=True)
Definition: Configurable.py:1464
GaudiKernel.Configurable.ConfigurableUser.propagateProperties
def propagateProperties(self, names=None, others=None, force=True)
Definition: Configurable.py:1513
GaudiKernel.Configurable.Configurable.__iter__
def __iter__(self)
Definition: Configurable.py:438
GaudiKernel.Configurable.ConfigurableGeneric.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1124
GaudiKernel.Configurable.ConfigurableAlgTool.isPublic
def isPublic(self)
Definition: Configurable.py:1307
GaudiKernel.Configurable.Configurable.getProp
def getProp(self, name)
Definition: Configurable.py:777
GaudiKernel.Configurable.ConfigurableAlgorithm._jobOptName
_jobOptName
Definition: Configurable.py:1146
GaudiKernel.Configurable.ConfigurableAlgTool.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1247
GaudiKernel.Configurable.ConfigurableUser.getHandle
def getHandle(self)
Definition: Configurable.py:1452
GaudiKernel.Configurable.Configurable._isInSetDefaults
def _isInSetDefaults(self)
Definition: Configurable.py:914
GaudiKernel.Configurable.Configurable.__bool__
def __bool__(self)
Definition: Configurable.py:548
GaudiKernel.Configurable.Configurable.getAllChildren
def getAllChildren(self)
Definition: Configurable.py:610
GaudiKernel.Configurable.Configurable.getTools
def getTools(self)
Definition: Configurable.py:599
GaudiKernel.Configurable.SuperAlgorithm.name
def name(self)
Definition: Configurable.py:1880
GaudiKernel.Configurable.Configurable.__iadd__
def __iadd__(self, configs, descr=None)
Definition: Configurable.py:458
GaudiKernel.Configurable.Configurable.jobOptName
def jobOptName(self)
Definition: Configurable.py:819
GaudiKernel.Configurable.ConfigurableAlgTool._jobOptName
_jobOptName
Definition: Configurable.py:1254
GaudiKernel.Configurable.Error
Definition: Configurable.py:102
GaudiKernel.Configurable.DummyDescriptor.__init__
def __init__(self, name)
Definition: Configurable.py:1077
GaudiKernel.ConfigurableMeta
Definition: ConfigurableMeta.py:1
GaudiKernel.Configurable.ConfigurableUser.__init__
def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs)
Definition: Configurable.py:1377
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:1148
GaudiKernel.Configurable.Configurable.__repr__
def __repr__(self)
Definition: Configurable.py:973
GaudiKernel.Configurable.Configurable.isPublic
def isPublic(self)
Definition: Configurable.py:815
max
EventIDBase max(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:225
GaudiKernel.Configurable.Configurable.removeAll
def removeAll(self)
Definition: Configurable.py:560
GaudiKernel.Configurable.Configurable.getFullName
def getFullName(self)
Definition: Configurable.py:826
GaudiKernel.Configurable.ConfigurableAlgorithm._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: Configurable.py:1189
GaudiKernel.Configurable.DummyDescriptor.__set__
def __set__(self, obj, value)
Definition: Configurable.py:1083
GaudiKernel.Configurable.ConfigurableAlgTool.hasParent
def hasParent(self, parent)
Definition: Configurable.py:1301
GaudiKernel.Constants
Definition: Constants.py:1
GaudiKernel.Configurable.Configurable.properties
def properties(self)
Definition: Configurable.py:736
GaudiKernel.Configurable.ConfigurableAlgorithm.__invert__
def __invert__(self)
Definition: Configurable.py:1178
GaudiKernel.Configurable.ConfigurableUser.getDlls
def getDlls(self)
Definition: Configurable.py:1449
GaudiKernel.Configurable.Configurable.__setupDlls
def __setupDlls(self)
Definition: Configurable.py:935
GaudiKernel.Configurable.ConfigurableUser.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1446
GaudiAlg.Algs.iAlgorithm
iAlgorithm
Definition: Algs.py:67
GaudiConfig.ControlFlow.OrNode
Definition: ControlFlow.py:143
GaudiKernel.Configurable.Configurable.name
def name(self)
Definition: Configurable.py:809
GaudiKernel.DataHandle
Definition: DataHandle.py:1
GaudiKernel.Configurable.Configurable.getType
def getType(cls)
Definition: Configurable.py:803
GaudiKernel.Configurable.ConfigurableAlgorithm.getHandle
def getHandle(self)
Definition: Configurable.py:1151
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:1873
GaudiKernel.Configurable.Configurable._printFooter
def _printFooter(indentStr, title)
Definition: Configurable.py:965
GaudiKernel.Configurable.Configurable.getProperties
def getProperties(self)
Definition: Configurable.py:689
GaudiKernel.Configurable.CreateSequencesVisitor.enter
def enter(self, visitee)
Definition: Configurable.py:1791
GaudiKernel.Configurable.ConfigurableAuditor.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1346
GaudiKernel.Configurable.ConfigurableAlgTool.getParent
def getParent(self)
Definition: Configurable.py:1294
GaudiKernel.Configurable.applyConfigurableUsers_old
def applyConfigurableUsers_old()
Definition: Configurable.py:1680
GaudiKernel.Configurable.Configurable.getPropertiesWithDescription
def getPropertiesWithDescription(self)
Definition: Configurable.py:699
GaudiKernel.Configurable.CreateSequencesVisitor.sequence
def sequence(self)
Definition: Configurable.py:1788
GaudiKernel.Configurable.SuperAlgorithm.isApplicable
def isApplicable(self)
Definition: Configurable.py:1892
GaudiKernel.Configurable.makeSequences
def makeSequences(expression)
Definition: Configurable.py:1838
GaudiKernel.Configurable.Configurable.__tools
__tools
Definition: Configurable.py:378
GaudiKernel.Configurable.Configurable.getName
def getName(self)
Definition: Configurable.py:806
GaudiKernel.Configurable.ConfigurableAlgTool.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:1314
GaudiKernel.Configurable.Configurable.__getnewargs__
def __getnewargs__(self)
Definition: Configurable.py:415
GaudiKernel.Configurable.ConfigurableUser.__used_configurables__
__used_configurables__
Definition: Configurable.py:1372
GaudiKernel.Configurable.DummyDescriptor.__get__
def __get__(self, obj, type=None)
Definition: Configurable.py:1080
GaudiKernel.Configurable.appendPostConfigAction
def appendPostConfigAction(function)
Definition: Configurable.py:1577
bug_34121.tool
tool
Definition: bug_34121.py:17
GaudiKernel.Configurable.ConfigurableUser._applied
_applied
Definition: Configurable.py:1383
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: details.h:440
GaudiKernel.Configurable.Configurable.clone
def clone(self, name=None, **kwargs)
Definition: Configurable.py:844
GaudiKernel.Configurable.ConfigurableAlgTool.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1263
GaudiKernel.Configurable.Configurable.copyChild
def copyChild(self, child)
Definition: Configurable.py:564
GaudiKernel.Configurable.ConfigurableAuditor._jobOptName
_jobOptName
Definition: Configurable.py:1337
GaudiKernel.Configurable.ConfigurableService.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:1230
GaudiKernel.Configurable.Configurable.DefaultName
Definition: Configurable.py:157
GaudiKernel.Configurable.SuperAlgorithm.__new__
def __new__(cls, name=None, **kwargs)
Definition: Configurable.py:1857
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:1129
GaudiKernel.Configurable.DummyDescriptor
Definition: Configurable.py:1076
GaudiKernel.Configurable.Configurable.getChildren
def getChildren(self)
Definition: Configurable.py:596
GaudiKernel.Configurable.Configurable.setDefaults
def setDefaults(cls, handle)
Definition: Configurable.py:841
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:1352
GaudiKernel.Configurable.ConfigurableGeneric.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1090
GaudiKernel.Configurable.Configurable.getTitleName
def getTitleName(self)
Definition: Configurable.py:835
GaudiKernel.Configurable.ConfigurableService.copyChild
def copyChild(self, child)
Definition: Configurable.py:1216
GaudiKernel.Configurable.SuperAlgorithm._initGraph
def _initGraph(self)
Definition: Configurable.py:1908
GaudiKernel.Configurable.ConfigurableUser.isApplicable
def isApplicable(self)
Definition: Configurable.py:1566
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:1900
GaudiKernel.Configurable.Configurable.splitName
def splitName(self)
Definition: Configurable.py:875
GaudiKernel.GaudiHandles.ServiceHandle
Definition: GaudiHandles.py:110
GaudiKernel.Configurable.Configurable.__delattr__
def __delattr__(self, attr)
Definition: Configurable.py:523
GaudiKernel.Configurable.ConfigurableAlgTool.isInToolSvc
def isInToolSvc(self)
Definition: Configurable.py:1310
GaudiKernel.PropertyProxy
Definition: PropertyProxy.py:1
GaudiKernel.Configurable.ConfigurableAuditor.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1333
GaudiKernel.Configurable.Configurable.getPrintTitle
def getPrintTitle(self)
Definition: Configurable.py:832
GaudiKernel.Configurable.PropertyReference.name
name
Definition: Configurable.py:115
GaudiKernel.Configurable.ConfigurableAlgorithm.__eq__
def __eq__(self, other)
Definition: Configurable.py:1192
GaudiKernel.Configurable.ConfigurableUser._enabled
_enabled
Definition: Configurable.py:1381
GaudiKernel.Configurable.ConfigurableGeneric.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:1108
GaudiKernel.Configurable.Configurable.setup
def setup(self)
Definition: Configurable.py:655
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:709
GaudiKernel.Configurable.ConfigurableAlgorithm.visitNode
def visitNode(self, visitor)
Definition: Configurable.py:1184
GaudiKernel.Configurable.ConfigurableUser.__addActiveUseOf
def __addActiveUseOf(self, other)
Definition: Configurable.py:1424
GaudiConfig.ControlFlow.ControlFlowNode.visitNode
def visitNode(self, visitor)
Definition: ControlFlow.py:44
GaudiKernel.Configurable.ConfigurableAuditor.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1349
GaudiKernel.Configurable.Configurable._printHeader
def _printHeader(indentStr, title)
Definition: Configurable.py:956
GaudiKernel.Configurable.ConfigurableAlgTool.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:1266
GaudiConfig.ControlFlow.InvertNode
Definition: ControlFlow.py:160
gaudirun.type
type
Definition: gaudirun.py:162
GaudiKernel.Configurable.ConfigurableGeneric.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1099
GaudiKernel.Configurable.removePostConfigAction
def removePostConfigAction(function)
Definition: Configurable.py:1590
GaudiKernel.Configurable.ConfigurableService.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:1233
GaudiKernel.Configurable.SuperAlgorithm._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: Configurable.py:1914
GaudiKernel.Configurable.ConfigurableUser.__queried_configurables__
__queried_configurables__
Definition: Configurable.py:1375
StringKeyEx.keys
keys
Definition: StringKeyEx.py:63
GaudiKernel.Configurable.ConfigurableUser.getUsedInstance
def getUsedInstance(self, name)
Definition: Configurable.py:1553
GaudiKernel.Configurable.Configurable.__children
__children
Definition: Configurable.py:377
GaudiKernel.Configurable.getNeededConfigurables
def getNeededConfigurables()
Definition: Configurable.py:1746
GaudiKernel.Configurable.Configurable.addTool
def addTool(self, tool, name=None)
Definition: Configurable.py:891
GaudiKernel.Configurable.ConfigurableAlgorithm.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1160
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:1256
GaudiKernel.Configurable.ConfigurableUser.__apply_configuration__
def __apply_configuration__(self)
Definition: Configurable.py:1524
GaudiKernel.Configurable.SuperAlgorithm._name
_name
Definition: Configurable.py:1874
GaudiKernel.Configurable.Configurable._inSetDefaults
_inSetDefaults
Definition: Configurable.py:390
GaudiKernel.Configurable.ConfigurableUser.__users__
__users__
Definition: Configurable.py:1382
GaudiKernel.Configurable.ConfigurableService
Definition: Configurable.py:1205
GaudiConfig.ControlFlow.ControlFlowNode
Definition: ControlFlow.py:19
GaudiKernel.Configurable.Configurable.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:812
GaudiKernel.Configurable.CreateSequencesVisitor._newSeq
def _newSeq(self, prefix="seq_", **kwargs)
Definition: Configurable.py:1804
GaudiKernel.Configurable.ConfigurableAlgTool.setParent
def setParent(self, parentName)
Definition: Configurable.py:1279
GaudiKernel.Configurable.Configurable.copyChildAndSetParent
def copyChildAndSetParent(self, cfg, parent)
Definition: Configurable.py:576
GaudiKernel.Configurable.ConfigurableAlgorithm.__rshift__
def __rshift__(self, rhs)
Definition: Configurable.py:1181
GaudiKernel.GaudiHandles.PrivateToolHandle
Definition: GaudiHandles.py:101
GaudiKernel.Configurable.Configurable.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:509
GaudiKernel.Configurable.ConfigurableUser.__detach_used__
def __detach_used__(self)
Definition: Configurable.py:1455
GaudiKernel.Configurable.ConfigurableAlgorithm.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1157
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:1884
GaudiKernel.Configurable.SuperAlgorithm.properties
def properties(self)
Definition: Configurable.py:1888
GaudiKernel.Configurable.Configurable.__slots__
__slots__
Definition: Configurable.py:165
GaudiKernel.Configurable.Configurable.getFullJobOptName
def getFullJobOptName(self)
Definition: Configurable.py:829
GaudiKernel.Configurable.ConfigurableAlgorithm.__hash__
def __hash__(self)
Definition: Configurable.py:1195
GaudiKernel.Configurable.Configurable._configurationLocked
_configurationLocked
Definition: Configurable.py:179
GaudiKernel.Configurable.CreateSequencesVisitor._getUniqueName
def _getUniqueName(self, prefix)
Definition: Configurable.py:1794
GaudiKernel.Configurable.ConfigurableAuditor
Definition: Configurable.py:1330
gaudirun.action
action
Definition: gaudirun.py:155
GaudiKernel.Configurable.SuperAlgorithm.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1897
GaudiKernel.ConfigurableMeta.ConfigurableMeta
Definition: ConfigurableMeta.py:25
GaudiKernel.Configurable.purge
def purge()
Definition: Configurable.py:1760
GaudiKernel.Configurable.ConfigurableAlgorithm.__and__
def __and__(self, rhs)
Definition: Configurable.py:1164
GaudiKernel.Configurable.Configurable.isApplicable
def isApplicable(self)
Definition: Configurable.py:1064
GaudiKernel.Configurable.ConfigurableGeneric._properties
_properties
Definition: Configurable.py:1093
GaudiKernel.Configurable.Configurable
Definition: Configurable.py:150
GaudiKernel.Configurable.CreateSequencesVisitor.__init__
def __init__(self)
Definition: Configurable.py:1784
GaudiKernel.GaudiHandles
Definition: GaudiHandles.py:1
GaudiKernel.Configurable.ConfigurableAlgTool
Definition: Configurable.py:1238
GaudiKernel.Configurable.ConfigurableUser.__addPassiveUseOf
def __addPassiveUseOf(self, other)
Definition: Configurable.py:1433
GaudiKernel.Configurable.ConfigurableService.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:1213
GaudiKernel.Configurable.Configurable.__str__
def __str__(self, indent=0, headerLastIndentUnit=indentUnit)
Definition: Configurable.py:976
GaudiKernel.ConfigurableDb
Definition: ConfigurableDb.py:1
GaudiKernel.Configurable.ConfigurableAlgTool.getPrintTitle
def getPrintTitle(self)
Definition: Configurable.py:1272
GaudiKernel.Configurable.Configurable.getDefaultProperty
def getDefaultProperty(cls, name)
Definition: Configurable.py:756
GaudiKernel.Configurable.Configurable.setParent
def setParent(self, parentName)
Definition: Configurable.py:567
GaudiKernel.Configurable.expandvars
def expandvars(data)
Definition: Configurable.py:78
GaudiKernel.Configurable.ConfigurableAuditor.getHandle
def getHandle(self)
Definition: Configurable.py:1339
GaudiKernel.GaudiHandles.PublicToolHandle
Definition: GaudiHandles.py:92
GaudiKernel.Configurable.Configurable.remove
def remove(self, items)
Definition: Configurable.py:554
GaudiKernel.Configurable.Configurable.__setupServices
def __setupServices(self)
Definition: Configurable.py:917
GaudiKernel.Configurable.CreateSequencesVisitor.stack
stack
Definition: Configurable.py:1785
GaudiPython.Pythonizations.items
items
Definition: Pythonizations.py:546
GaudiKernel.Configurable.applyConfigurableUsers
def applyConfigurableUsers()
Definition: Configurable.py:1601
GaudiConfig.ControlFlow.AndNode
Definition: ControlFlow.py:126