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