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