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