Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v38r0 (2143aa4c)
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 import GaudiKernel.ConfigurableMeta as ConfigurableMeta
22 from GaudiConfig.ControlFlow import (
23  AndNode,
24  CFFalse,
25  CFTrue,
26  ControlFlowLeaf,
27  ControlFlowNode,
28  InvertNode,
29  OrderedNode,
30  OrNode,
31  ignore,
32 )
33 from GaudiKernel.Constants import (
34  DEBUG,
35  ERROR,
36  FATAL,
37  INFO,
38  VERBOSE,
39  WARNING,
40  error_explanation,
41 )
42 from GaudiKernel.DataHandle import DataHandle
43 from GaudiKernel.GaudiHandles import (
44  GaudiHandle,
45  GaudiHandleArray,
46  PrivateToolHandle,
47  PublicToolHandle,
48  ServiceHandle,
49 )
50 from GaudiKernel.PropertyProxy import PropertyProxy
51 
52 # data ---------------------------------------------------------------------
53 __all__ = [
54  "Configurable",
55  "ConfigurableAlgorithm",
56  "ConfigurableAlgTool",
57  "ConfigurableAuditor",
58  "ConfigurableService",
59  "ConfigurableUser",
60  "VERBOSE",
61  "DEBUG",
62  "INFO",
63  "WARNING",
64  "ERROR",
65  "FATAL",
66  "appendPostConfigAction",
67  "removePostConfigAction",
68 ]
69 
70 # for messaging
71 import logging
72 
73 log = logging.getLogger("Configurable")
74 
75 
76 def expandvars(data):
77  """
78  Expand environment variables "data".
79  Data can be string, list, tuple and dictionary. For collection, all the
80  contained strings will be manipulated (recursively).
81  """
82  import os.path
83 
84  typ = type(data)
85  if typ is str:
86  return os.path.expandvars(data)
87  elif typ in [list, tuple]:
88  collect = []
89  for i in data:
90  collect.append(expandvars(i))
91  return typ(collect)
92  elif typ is dict:
93  collect = {}
94  for k in data:
95  collect[expandvars(k)] = expandvars(data[k])
96  return collect
97  return data
98 
99 
100 class Error(RuntimeError):
101  """
102  Error occurred in the configuration process.
103  """
104 
105  pass
106 
107 
108 # Allow references to options as in old style
109 
110 
111 class PropertyReference(object):
112  def __init__(self, propname):
113  self.name = propname
114 
115  def __str__(self):
116  return "@%s" % self.name
117 
118  def __resolve__(self):
119  # late binding for property references
120  retval = None
121  refname, refprop = self.name.rsplit(".", 1)
122  if refname in Configurable.allConfigurables:
123  conf = Configurable.allConfigurables[refname]
124  retval = getattr(conf, refprop)
125  if hasattr(retval, "getFullName"):
126  retval = retval.getFullName()
127  else:
128  raise NameError("name '%s' not found resolving '%s'" % (refname, self))
129  return retval
130 
131  def getFullName(self):
132  """This function allow transparent integration with
133  Configurable.getValuedProperties.
134  """
135  try:
136  return self.__resolve__()
137  except NameError:
138  # ignore the error if we cannot resolve the name yet
139  return self
140  except AttributeError:
141  # ignore the error if we cannot resolve the attribute yet
142  return self
143 
144 
145 # base class for configurable Gaudi algorithms/services/algtools/etc. ======
146 
147 
149  """Base class for Gaudi components that implement the IProperty interface.
150  Provides most of the boilerplate code, but the actual useful classes
151  are its derived ConfigurableAlgorithm, ConfigurableService, and
152  ConfigurableAlgTool."""
153 
154  # for detecting the default name
155  class DefaultName:
156  pass
157 
158  propertyNoValue = "<no value>"
159  indentUnit = "| "
160  printHeaderWidth = 100
161  printHeaderPre = 5
162 
163  __slots__ = (
164  "__children", # controlled components, e.g. private AlgTools
165  "__tools", # private AlgTools (#PM-->)
166  "_name", # the (unqualified) component name
167  "_inSetDefaults", # currently setting default values
168  "_initok", # used to enforce base class init
169  "_setupok", # for debugging purposes (temporary)
170  "_unpickling", # flag for actions done during unpickling
171  )
172 
173  allConfigurables = {} # just names would do, but currently refs to the actual
174  configurableServices = {} # just names would do, but currently refs to the actual
175  # configurables is needed for (temporary) backwards
176  # compatibility; will change in the future
177  _configurationLocked = False
178 
179  def __new__(cls, *args, **kwargs):
180  """To Gaudi, any object with the same type/name is the same object. Hence,
181  this is mimicked in the configuration: instantiating a new Configurable
182  of a type with the same name will return the same instance."""
183 
184  global log
185  func_code = cls.__init__.__code__
186  func_defaults = cls.__init__.__defaults__
187  # try to get the name of the Configurable (having a name is compulsory)
188  if "name" in kwargs:
189  # simple keyword (by far the easiest)
190  name = kwargs["name"]
191  elif "name" in func_code.co_varnames:
192  # either positional in args, or default
193  index = list(func_code.co_varnames).index("name")
194  try:
195  # var names index is offset by one as __init__ is to be called with self
196  name = args[index - 1]
197  except IndexError:
198  # retrieve default value, then
199  name = func_defaults[index - (len(args) + 1)]
200  else:
201  # positional index is assumed (will work most of the time)
202  try:
203  name = args[1] # '0' is for self
204  except (IndexError, TypeError):
205  raise TypeError(
206  'no "name" argument while instantiating "%s"' % cls.__name__
207  )
208 
209  argname = name
210  if name == Configurable.DefaultName:
211  if hasattr(cls, "DefaultedName"):
212  name = cls.DefaultedName
213  else:
214  name = cls.getType()
215  elif not name or not isinstance(name, str):
216  # unnamed, highly specialized user code, etc. ... unacceptable
217  raise TypeError(
218  "could not retrieve name from %s.__init__ arguments" % cls.__name__
219  )
220 
221  # Handle the case of global tools to prepend ToolSvc in the name.
222  # This is needed for compatibility with old JobOptions files being read
223  if issubclass(cls, ConfigurableAlgTool) and "." not in name:
224  name = "ToolSvc." + name
225 
226  # close backdoor access to otherwise private subalgs/tools
227  # PM if 0 <= name.find( '.' ):
228  # PM # temp protection for old style types
229  # PM from OldStyleConfig import GenericConfigurable
230  # PM if not issubclass( cls, GenericConfigurable ): # except raised for new types only
231  # PM raise NameError( '"%s": backdoor access to private configurables not allowed' % name )
232 
233  # ordinary recycle case
234  if name in cls.configurables:
235  conf = cls.configurables[name]
236  if name != argname: # special case: user derived <-> real ... make same
237  cls.configurables[conf.getType()] = conf
238  # ---PM: Initialize additional properties
239  for n, v in kwargs.items():
240  if n != "name": # it should not be confused with a normal property
241  setattr(conf, n, v)
242  if (
243  not cls._configurationLocked
244  and "_enabled" not in kwargs
245  and isinstance(conf, ConfigurableUser)
246  ):
247  # Ensure that the ConfigurableUser gets enabled if nothing is
248  # specified in the constructor.
249  setattr(conf, "_enabled", True)
250  return conf
251 
252  # a couple of special cases (note that these cases don't mix)
253  spos = name.find("/")
254  ti_name = None
255  if spos < 0:
256  ti_name = "%s/%s" % (name, name)
257  if ti_name in cls.configurables:
258  # support for old-style name as type/name lookup where name==type
259  return cls.configurables[ti_name]
260 
261  i_name = None
262  if spos > 0:
263  i_name = name[:spos]
264  if i_name == name[spos + 1 :] and i_name in cls.configurables:
265  # this is the opposite of the above special case
266  return cls.configurables[i_name]
267 
268  # the following is purely for debugging support and should realistically bomb
269  conf = (
270  cls.allConfigurables.get(name, None)
271  or (spos < 0 and cls.allConfigurables.get(ti_name, None))
272  or (
273  spos > 0
274  and i_name == name[spos + 1 :]
275  and cls.allConfigurables.get(i_name, None)
276  )
277  )
278  if conf: # wrong type used?
279  if conf.__class__ is ConfigurableGeneric:
280  # If the instance found is ConfigurableGeneric then
281  # we create a new one with the proper type and fill with
282  # the contents of the generic one
283  newconf = object.__new__(cls)
284  cls.__init__(newconf, *args, **kwargs)
285  # initialize with the properties of generic configurable
286  # (we map the names of the properties to lowercase versions because
287  # old options are not case sensitive)
288  names = {}
289  for n in newconf.__slots__:
290  names[n.lower()] = n
291  for n in conf._properties:
292  if names[n.lower()] != n:
293  log.warning(
294  "Option '%s' was used for %s, but the correct spelling is '%s'"
295  % (n, name, names[n.lower()])
296  )
297  setattr(newconf, names[n.lower()], getattr(conf, n))
298  for n, v in kwargs.items():
299  setattr(newconf, n, v)
300  cls.configurables[name] = newconf
301  cls.allConfigurables[name] = newconf
302  return newconf
303  else:
304  # will be an actual error in the future (now only report as such)
305  log.error(
306  'attempt to redefine type of "%s" (was: %s, new: %s)%s',
307  name,
308  conf.__class__.__name__,
309  cls.__name__,
310  error_explanation,
311  )
312  # in the future:
313  # return None # will bomb on use (or go unharmed on non-use)
314  # for now, allow use through allConfigurables lookup
315  # ---PM: Initialize additional properties
316  for n, v in kwargs.items():
317  setattr(conf, n, v)
318  return conf
319 
320  # still here: create a new instance and initialize it
321  conf = object.__new__(cls)
322  cls.__init__(conf, *args, **kwargs)
323 
324  # update normal, per-class cache
325  cls.configurables[name] = conf
326 
327  for base in cls.__bases__:
328  if base.__name__ == "ConfigurableService":
329  cls.configurableServices[name] = conf
330 
331  # update generics super-cache, if needed
332  cls.allConfigurables[name] = conf
333  # -->PM#if hasattr( cls, 'getType' ) and name.find('/') < 0:
334  # -->PM# cls.allConfigurables[ cls.getType() + '/' + name ] = conf
335 
336  return conf
337 
338  def __init__(self, name=DefaultName):
339  # check class readiness, all required overloads should be there now
340  klass = self.__class__
341 
342  # this is an abstract class
343  if klass == Configurable:
344  raise TypeError(
345  "%s is an ABC and can not be instantiated" % str(Configurable)
346  )
347 
348  # the following methods require overloading
349  # NOT YET meths = { 'getServices' : 1, # retrieve list of services to configure
350  meths = {
351  "getDlls": 1, # provide list of Dlls to load
352  "getGaudiType": 1, # return string describing component class
353  "getHandle": 1,
354  } # provide access to C++ side component instance
355  # 'getType' : 1 } # return the type of the actual C++ component
356 
357  for meth, nArgs in meths.items():
358  try:
359  f = getattr(klass, meth)
360  except AttributeError:
361  raise NotImplementedError(
362  "%s is missing in class %s" % (meth, str(klass))
363  )
364 
365  # in addition, verify the number of arguments w/o defaults
366  nargcount = f.__code__.co_argcount
367  fdefaults = f.__defaults__
368  ndefaults = fdefaults and len(fdefaults) or 0
369  if not nargcount - ndefaults <= nArgs <= nargcount:
370  raise TypeError(
371  "%s.%s requires exactly %d arguments" % (klass, meth, nArgs)
372  )
373 
374  # for using this Configurable as a (Gaudi) sequence
375  self.__children = []
376  self.__tools = {}
377 
378  # know who we are
379  if name == Configurable.DefaultName:
380  if hasattr(self.__class__, "DefaultedName"):
381  self._name = self.__class__.DefaultedName
382  else:
383  self._name = self.getType()
384  else:
385  self._name = name
386 
387  # set to True when collecting defaults, False otherwise
388  self._inSetDefaults = False
389 
390  # for later, in case __init__ itself is overridden
391  self._initok = True
392 
393  # for debugging purposes (temporary)
394  self._setupok = False
395 
396  # used to prevent spurious deprecation warnings when unpickling
397  self._unpickling = False
398 
399  # pickle support
400  def __getstate__(self):
401  dict = {}
402  for name, proxy in self._properties.items():
403  try:
404  dict[name] = proxy.__get__(self)
405  except AttributeError:
406  pass
407 
408  dict["_Configurable__children"] = self.__children
409  dict["_Configurable__tools"] = self.__tools
410  dict["_name"] = self._name
411  return dict
412 
413  def __getnewargs__(self):
414  return (self._name,)
415 
416  def __setstate__(self, dict):
417  self._initok = True
418  from contextlib import contextmanager
419 
420  @contextmanager
421  def unpickling():
422  try:
423  self._unpickling = True
424  yield
425  finally:
426  self._unpickling = False
427 
428  with unpickling():
429  for n, v in dict.items():
430  setattr(self, n, v)
431 
432  # to allow a few basic sanity checks, as well as nice syntax
433  def __len__(self):
434  return len(self.__children)
435 
436  def __iter__(self):
437  return iter(self.__children)
438 
439  # ownership rules of self through copying
440  def __deepcopy__(self, memo):
441  newconf = object.__new__(self.__class__)
442  self.__class__.__init__(newconf, self.getName())
443 
444  for proxy in self._properties.values():
445  try:
446  proxy.__set__(newconf, proxy.__get__(self))
447  except AttributeError:
448  pass # means property was not set for self
449 
450  for c in self.__children:
451  newconf += c # processes proper copy semantics
452 
453  return newconf
454 
455  # hierarchy building, and ownership rules of children
456  def __iadd__(self, configs, descr=None):
457  if not type(configs) in (list, tuple):
458  configs = (configs,)
459 
460  joname = self.getJobOptName()
461 
462  for cfg in configs:
463  # prevent type mismatches
464  if not isinstance(cfg, Configurable):
465  raise TypeError("'%s' is not a Configurable" % str(cfg))
466 
467  cc = self.copyChildAndSetParent(cfg, joname)
468 
469  # filters dupes; usually "ok" (backdoor should catch them)
470  ccjo = cc.getJobOptName()
471  for c in self.__children:
472  if c.getJobOptName() == ccjo:
473  log.error(
474  "attempt to add a duplicate ... dupe ignored%s",
475  error_explanation,
476  )
477  break
478  else:
479  self.__children.append(cc)
480 
481  try:
482  if descr: # support for tool properties
483  descr.__set__(self, cc)
484  else:
485  setattr(self, cc.getName(), cc)
486  except AttributeError:
487  pass # to allow free addition of tools/subalgorithms
488 
489  return self
490 
491  def __getattr__(self, attr): # until ToolProperties exist ...
492  if attr in self.__tools:
493  return self.__tools[attr]
494 
495  if attr in self._properties:
496  if isinstance(self._properties[attr].__get__(self), DataHandle):
497  return self._properties[attr].__get__(self)
498 
499  for c in self.__children:
500  if c.getName() == attr:
501  return c
502 
503  raise AttributeError(
504  "'%s' object has no attribute '%s'" % (self.__class__, attr)
505  )
506 
507  def __setattr__(self, name, value):
508  if self._configurationLocked:
509  raise RuntimeError(
510  "%s: Configuration cannot be modified after the ApplicationMgr has been started."
511  % self.name()
512  )
513  try:
514  super(Configurable, self).__setattr__(name, value)
515  except AttributeError:
516  raise AttributeError(
517  "Configurable '%s' does not have property '%s'."
518  % (self.__class__.__name__, name)
519  )
520 
521  def __delattr__(self, attr):
522  # remove as property, otherwise try as child
523  try:
524  # remove history etc., then reset to default (in case set before)
525  prop = self._properties[attr]
526  prop.__delete__(self)
527  prop.__set__(self, prop.default)
528  return # reaches here? was property: done now
529  except KeyError:
530  pass
531  # otherwise, remove the private tool
532  if attr in self.__tools:
533  del self.__tools[attr]
534 
535  # otherwise, remove child, if one is so named
536  for c in self.__children:
537  if c.getName() == attr:
538  self.__children.remove(c)
539 
540  # potentially, there are left over caches (certain user derived classes)
541  try:
542  del self.__dict__[attr]
543  except (AttributeError, KeyError):
544  pass
545 
546  def __bool__(self):
547  return True
548 
549  def remove(self, items):
550  if not isinstance(items, (list, tuple)):
551  items = [items]
552 
553  self.__children = [e for e in self.__children if e not in items]
554 
555  def removeAll(self):
556  self.remove(self.__children)
557 
558  # called by __iadd__; determines child copy semantics
559  def copyChild(self, child):
560  return copy.deepcopy(child)
561 
562  def setParent(self, parentName):
563  pass
564 
565  def getParent(self):
566  return ""
567 
568  def hasParent(self, parent):
569  return False
570 
571  def copyChildAndSetParent(self, cfg, parent):
572  cc = self.copyChild(cfg)
573 
574  if hasattr(cc, "setParent") and parent:
575  try:
576  cc.setParent(parent)
577  except RuntimeError as e:
578  # temporary backdoor resolution for compatibility
579  log.error(str(e) + "%s", error_explanation)
580  ccbd = cc.configurables[cc.getJobOptName()]
581 
582  # merge properties, new over pre-existing
583  for proxy in self._properties.values():
584  if cc in proxy.history:
585  proxy.__set__(ccbd, proxy.__get__(cc))
586 
587  # consolidate
588  cc = ccbd
589  return cc
590 
591  def getChildren(self):
592  return self.__children[:] # read only
593 
594  def getTools(self):
595  return self.__tools.values() # read only
596 
597  def children(self):
598  log.error("children() is deprecated, use getChildren() instead for consistency")
599  log.error(
600  "getChildren() returns a copy; to add a child, use 'parent += child'%s",
601  error_explanation,
602  )
603  return self.__children # by ref, for compatibility
604 
605  def getAllChildren(self):
606  """Get all (private) configurable children, both explicit ones (added with +=)
607  and the ones in the private GaudiHandle properties"""
608  childs = []
609  # add private configurable properties (also inside handles)
610  for proxy in self._properties.values():
611  try:
612  c = proxy.__get__(self)
613  except AttributeError:
614  pass
615  else:
616  if isinstance(c, Configurable) and not c.isPublic():
617  childs.append(c)
618  elif isinstance(c, GaudiHandle):
619  try:
620  conf = c.configurable
621  except AttributeError:
622  pass
623  else:
624  if not conf.isPublic():
625  childs.append(conf)
626  elif isinstance(c, GaudiHandleArray):
627  # only setup private arrays
628  if not c.isPublic():
629  for ci in c:
630  if isinstance(ci, Configurable):
631  childs.append(ci)
632  else:
633  try:
634  conf = ci.configurable
635  except AttributeError:
636  pass
637  else:
638  childs.append(conf)
639 
640  # add explicit children
641  childs += self.__children
642  return childs
643 
644  def getSequence(self):
645  elems = []
646  for c in self.__children:
647  elems.append(c.getFullName())
648  return elems
649 
650  def setup(self):
651  # make sure base class init has been called
652  if not hasattr(self, "_initok") or not self._initok:
653  # could check more, but this is the only explanation
654  raise TypeError(
655  "Configurable.__init__ not called in %s override"
656  % self.__class__.__name__
657  )
658 
659  # log.debug("calling setup() on " + self.getFullJobOptName())
660 
661  # setup self: this collects all values on the python side
662  self.__setupServices()
663  self.__setupDlls()
664  self.__setupDefaults()
665 
666  # setup children
667  for c in self.getAllChildren():
668  c.setup()
669 
670  # now get handle to work with for moving properties into the catalogue
671  handle = self.getHandle()
672  if not handle:
673  log.debug("no handle for %s: not transporting properties", self._name)
674  return # allowed, done early
675 
676  # pass final set of properties on to handle on the C++ side or JobOptSvc
677  for name in self._properties.keys():
678  if hasattr(self, name): # means property has python-side value/default
679  setattr(handle, name, getattr(self, name))
680 
681  # for debugging purposes
682  self._setupok = True
683 
684  def getProperties(self):
685  props = {}
686  for name, proxy in self._properties.items():
687  try:
688  props[name] = proxy.__get__(self)
689  except AttributeError:
690  props[name] = Configurable.propertyNoValue
691 
692  return props
693 
695  """Get all properties with their description string as { name : (value, desc) }."""
696  props = {}
697  for name, proxy in self._properties.items():
698  try:
699  props[name] = (proxy.__get__(self), proxy.__doc__)
700  except AttributeError:
701  props[name] = (Configurable.propertyNoValue, proxy.__doc__)
702  return props
703 
705  props = {}
706  for name, proxy in self._properties.items():
707  if self.isPropertySet(name):
708  value = proxy.__get__(self)
709  if hasattr(value, "getFullName"):
710  value = value.getFullName()
711  elif isinstance(value, (list, set, tuple)):
712  new_value = []
713  for i in value:
714  if hasattr(i, "getFullName"):
715  new_value.append(i.getFullName())
716  else:
717  new_value.append(i)
718  value = type(value)(new_value)
719  elif isinstance(value, dict):
720  new_value = {}
721  for i in value:
722  if hasattr(value[i], "getFullName"):
723  new_value[i] = value[i].getFullName()
724  else:
725  new_value[i] = value[i]
726  value = new_value
727  props[name] = value
728 
729  return props
730 
731  def properties(self):
732  return self.getProperties() # compatibility
733 
734  @classmethod
736  class collector:
737  pass
738 
739  # user provided defaults
740  c = collector()
741  cls.setDefaults(c)
742 
743  # defaults from C++
744  for k, v in cls._properties.items():
745  if k not in c.__dict__ and hasattr(v, "default"):
746  c.__dict__[k] = v.default
747 
748  return c.__dict__
749 
750  @classmethod
751  def getDefaultProperty(cls, name):
752  class collector:
753  pass
754 
755  # user provided defaults
756  c = collector()
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  "AuditAlgorithms": 0,
1140  "AuditInitialize": 0,
1141  "AuditReinitialize": 0,
1142  "AuditExecute": 0,
1143  "AuditFinalize": 0,
1144  }
1145 
1146  def __init__(self, name=Configurable.DefaultName):
1147  super(ConfigurableAlgorithm, self).__init__(name)
1148  name = self.getName()
1149  self._jobOptName = name[name.find("/") + 1 :] # strips class
1150 
1151  def __deepcopy__(self, memo):
1152  return self # algorithms are always shared
1153 
1154  def getHandle(self):
1155  return iAlgorithm( # noqa: F821 (to avoid circular dependeny)
1156  self.getJobOptName()
1157  )
1158 
1159  @classmethod
1160  def getGaudiType(cls):
1161  return "Algorithm"
1162 
1163  def getJobOptName(self):
1164  return self._jobOptName
1165 
1166  # mimick the ControlFlowLeaf interface
1167  def __and__(self, rhs):
1168  if rhs is CFTrue:
1169  return self
1170  elif rhs is CFFalse:
1171  return CFFalse
1172  return AndNode(self, rhs)
1173 
1174  def __or__(self, rhs):
1175  if rhs is CFFalse:
1176  return self
1177  elif rhs is CFTrue:
1178  return CFTrue
1179  return OrNode(self, rhs)
1180 
1181  def __invert__(self):
1182  return InvertNode(self)
1183 
1184  def __rshift__(self, rhs):
1185  return OrderedNode(self, rhs)
1186 
1187  def visitNode(self, visitor):
1188  visitor.enter(self)
1189  self._visitSubNodes(visitor)
1190  visitor.leave(self)
1191 
1192  def _visitSubNodes(self, visitor):
1193  pass
1194 
1195  def __eq__(self, other):
1196  return repr(self) == repr(other)
1197 
1198  def __hash__(self):
1199  """Return a unique identifier for this object.
1200 
1201  As we use the `repr` of this object to check for equality, we use it
1202  here to define uniqueness.
1203  """
1204  # The hash of the 1-tuple containing the repr of this object
1205  return hash((repr(self),))
1206 
1207 
1209  __slots__ = {
1210  "OutputLevel": 0,
1211  "AuditServices": 0,
1212  "AuditInitialize": 0,
1213  "AuditFinalize": 0,
1214  }
1215 
1216  def __deepcopy__(self, memo):
1217  return self # services are always shared
1218 
1219  def copyChild(self, child):
1220  # Copy private tools but all else is shared
1221  if isinstance(child, ConfigurableAlgTool) and not child.isPublic():
1222  return copy.deepcopy(child)
1223  else:
1224  return child
1225 
1226  def getHandle(self):
1227  return iService(self._name) # noqa: F821 (to avoid circular dependeny)
1228 
1229  @classmethod
1230  def getGaudiType(cls):
1231  return "Service"
1232 
1233  def getGaudiHandle(self):
1234  return ServiceHandle(self.toStringProperty())
1235 
1236  def toStringProperty(self):
1237  # called on conversion to a string property for the jocat
1238  return self.getName()
1239 
1240 
1242  __slots__ = {
1243  "_jobOptName": "",
1244  "OutputLevel": 0,
1245  "AuditTools": 0,
1246  "AuditInitialize": 0,
1247  "AuditFinalize": 0,
1248  }
1249 
1250  def __init__(self, name=Configurable.DefaultName):
1251  super(ConfigurableAlgTool, self).__init__(name)
1252  if "." not in self._name:
1253  # Public tools must have ToolSvc as parent
1254  self._name = "ToolSvc." + self._name
1255  name = self.getName()
1256  name = name[name.find("/") + 1 :] # strips class, if any
1257  self._jobOptName = name
1258 
1259  def getHandle(self):
1260  # iAlgTool isn't useful, unless one knows for sure that the tool exists
1261  return iProperty( # noqa: F821 (to avoid circular dependeny)
1262  self.getJobOptName()
1263  )
1264 
1265  @classmethod
1266  def getGaudiType(cls):
1267  return "AlgTool"
1268 
1269  def getGaudiHandle(self):
1270  if self.isPublic():
1271  return PublicToolHandle(self.toStringProperty())
1272  else:
1273  return PrivateToolHandle(self.toStringProperty())
1274 
1275  def getPrintTitle(self):
1276  if self.isPublic():
1277  pop = "Public "
1278  else:
1279  pop = "Private "
1280  return pop + Configurable.getPrintTitle(self)
1281 
1282  def setParent(self, parentName):
1283  # print "ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName)
1284  # print "Calling stack:"
1285  # import traceback
1286  # traceback.print_stack()
1287  # propagate parent to AlgTools in children
1288  for c in self.getAllChildren():
1289  if isinstance(c, ConfigurableAlgTool):
1290  c.setParent(parentName)
1291 
1292  # update my own parent
1293  name = self.getName()
1294  name = name[name.rfind(".") + 1 :] # Name of the instance
1295  self._jobOptName = self._name = parentName + "." + name
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 type(used) is 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 type(used) is 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 type(queried) is 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 type(cls) is 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 
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:173
GaudiKernel.Configurable.SuperAlgorithm.__repr__
def __repr__(self)
Definition: Configurable.py:1914
GaudiKernel.Configurable.Configurable.getSequence
def getSequence(self)
Definition: Configurable.py:644
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:597
GaudiKernel.Configurable.Configurable.getDefaultProperties
def getDefaultProperties(cls)
Definition: Configurable.py:735
GaudiKernel.Configurable.ConfigurableAlgTool.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:1307
GaudiKernel.Configurable.ConfigurableService.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1230
GaudiKernel.Configurable.ConfigurableUser.__used_instances__
__used_instances__
Definition: Configurable.py:1394
MSG::hex
MsgStream & hex(MsgStream &log)
Definition: MsgStream.h:282
GaudiKernel.Configurable.SuperAlgorithm.graph
graph
Definition: Configurable.py:1878
GaudiKernel.Configurable.ConfigurableAlgorithm.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1146
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:565
GaudiConfig.ControlFlow.OrderedNode
Definition: ControlFlow.py:108
GaudiKernel.Configurable.Configurable._initok
_initok
Definition: Configurable.py:391
GaudiConfig.ControlFlow
Definition: ControlFlow.py:1
GaudiKernel.Configurable.ConfigurableAlgorithm.__or__
def __or__(self, rhs)
Definition: Configurable.py:1174
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:1226
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:568
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:436
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:1149
GaudiKernel.Configurable.ConfigurableAlgTool.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:1250
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:546
GaudiKernel.Configurable.Configurable.getAllChildren
def getAllChildren(self)
Definition: Configurable.py:605
GaudiKernel.Configurable.Configurable.getTools
def getTools(self)
Definition: Configurable.py:594
GaudiKernel.Configurable.SuperAlgorithm.name
def name(self)
Definition: Configurable.py:1883
GaudiPartProp.decorators.get
get
decorate the vector of properties
Definition: decorators.py:282
GaudiKernel.Configurable.Configurable.__iadd__
def __iadd__(self, configs, descr=None)
Definition: Configurable.py:456
GaudiKernel.Configurable.Configurable.jobOptName
def jobOptName(self)
Definition: Configurable.py:814
GaudiKernel.Configurable.ConfigurableAlgTool._jobOptName
_jobOptName
Definition: Configurable.py:1257
GaudiKernel.Configurable.Error
Definition: Configurable.py:100
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:381
GaudiKernel.Configurable.PropertyReference.__str__
def __str__(self)
Definition: Configurable.py:115
GaudiKernel.Configurable.ConfigurableAlgorithm.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:1151
GaudiKernel.Configurable.Configurable.__repr__
def __repr__(self)
Definition: Configurable.py:968
GaudiKernel.Configurable.Configurable.isPublic
def isPublic(self)
Definition: Configurable.py:810
max
EventIDBase max(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:225
GaudiKernel.Configurable.Configurable.removeAll
def removeAll(self)
Definition: Configurable.py:555
GaudiKernel.Configurable.Configurable.getFullName
def getFullName(self)
Definition: Configurable.py:821
GaudiKernel.Configurable.ConfigurableAlgorithm._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: Configurable.py:1192
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:731
GaudiKernel.Configurable.ConfigurableAlgorithm.__invert__
def __invert__(self)
Definition: Configurable.py:1181
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
GaudiAlg.Algs.iAlgorithm
iAlgorithm
Definition: Algs.py:66
GaudiConfig.ControlFlow.OrNode
Definition: ControlFlow.py:142
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:1154
GaudiKernel.Configurable.Configurable._unpickling
_unpickling
Definition: Configurable.py:397
GaudiKernel.Configurable.PropertyReference.__resolve__
def __resolve__(self)
Definition: Configurable.py:118
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:684
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:694
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:376
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:413
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:17
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:1266
GaudiKernel.Configurable.Configurable.copyChild
def copyChild(self, child)
Definition: Configurable.py:559
GaudiKernel.Configurable.ConfigurableAuditor._jobOptName
_jobOptName
Definition: Configurable.py:1340
GaudiKernel.Configurable.ConfigurableService.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:1233
GaudiKernel.Configurable.Configurable.DefaultName
Definition: Configurable.py:155
GaudiKernel.Configurable.SuperAlgorithm.__new__
def __new__(cls, name=None, **kwargs)
Definition: Configurable.py:1860
GaudiKernel.PropertyProxy.PropertyProxy
Definition: PropertyProxy.py:81
Gaudi.Configuration
Definition: Configuration.py:1
GaudiKernel.Configurable.Configurable._setupok
_setupok
Definition: Configurable.py:394
GaudiKernel.Configurable.Configurable.configurableServices
configurableServices
Definition: Configurable.py:174
GaudiKernel.Configurable.ConfigurableAlgorithm
Definition: Configurable.py:1132
GaudiKernel.Configurable.DummyDescriptor
Definition: Configurable.py:1079
GaudiKernel.Configurable.Configurable.getChildren
def getChildren(self)
Definition: Configurable.py:591
GaudiKernel.Configurable.Configurable.setDefaults
def setDefaults(cls, handle)
Definition: Configurable.py:836
GaudiKernel.Configurable.PropertyReference.__init__
def __init__(self, propname)
Definition: Configurable.py:112
GaudiKernel.Configurable.Configurable.__len__
def __len__(self)
Definition: Configurable.py:433
GaudiKernel.Configurable.Configurable.__init__
def __init__(self, name=DefaultName)
Definition: Configurable.py:338
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:1219
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:119
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:114
GaudiKernel.Configurable.Configurable.__delattr__
def __delattr__(self, attr)
Definition: Configurable.py:521
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:113
GaudiKernel.Configurable.ConfigurableAlgorithm.__eq__
def __eq__(self, other)
Definition: Configurable.py:1195
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:650
gaudiComponentHelp.properties
properties
Definition: gaudiComponentHelp.py:68
GaudiKernel.Configurable.PropertyReference.getFullName
def getFullName(self)
Definition: Configurable.py:131
GaudiKernel.Configurable.Configurable.getValuedProperties
def getValuedProperties(self)
Definition: Configurable.py:704
GaudiKernel.Configurable.ConfigurableAlgorithm.visitNode
def visitNode(self, visitor)
Definition: Configurable.py:1187
GaudiKernel.Configurable.ConfigurableUser.__addActiveUseOf
def __addActiveUseOf(self, other)
Definition: Configurable.py:1427
GaudiConfig.ControlFlow.ControlFlowNode.visitNode
def visitNode(self, visitor)
Definition: ControlFlow.py:43
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:1269
GaudiConfig.ControlFlow.InvertNode
Definition: ControlFlow.py:159
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:1236
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:63
GaudiKernel.Configurable.ConfigurableUser.getUsedInstance
def getUsedInstance(self, name)
Definition: Configurable.py:1556
GaudiKernel.Configurable.Configurable.__children
__children
Definition: Configurable.py:375
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:1163
GaudiKernel.Configurable.Configurable.__getattr__
def __getattr__(self, attr)
Definition: Configurable.py:491
GaudiKernel.Configurable.Configurable.__getstate__
def __getstate__(self)
Definition: Configurable.py:400
GaudiKernel.Configurable.ConfigurableAlgTool.getHandle
def getHandle(self)
Definition: Configurable.py:1259
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:388
GaudiKernel.Configurable.ConfigurableUser.__users__
__users__
Definition: Configurable.py:1385
GaudiKernel.Configurable.ConfigurableService
Definition: Configurable.py:1208
GaudiConfig.ControlFlow.ControlFlowNode
(c) Copyright 1998-2023 CERN for the benefit of the LHCb and ATLAS collaborations # # This software i...
Definition: ControlFlow.py:18
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:1282
GaudiKernel.Configurable.Configurable.copyChildAndSetParent
def copyChildAndSetParent(self, cfg, parent)
Definition: Configurable.py:571
GaudiKernel.Configurable.ConfigurableAlgorithm.__rshift__
def __rshift__(self, rhs)
Definition: Configurable.py:1184
GaudiKernel.GaudiHandles.PrivateToolHandle
Definition: GaudiHandles.py:105
GaudiKernel.Configurable.Configurable.__setattr__
def __setattr__(self, name, value)
Definition: Configurable.py:507
GaudiKernel.Configurable.ConfigurableUser.__detach_used__
def __detach_used__(self)
Definition: Configurable.py:1458
GaudiKernel.Configurable.ConfigurableAlgorithm.getGaudiType
def getGaudiType(cls)
Definition: Configurable.py:1160
GaudiKernel.Configurable.Configurable.__setstate__
def __setstate__(self, dict)
Definition: Configurable.py:416
GaudiKernel.Configurable.Configurable.__new__
def __new__(cls, *args, **kwargs)
Definition: Configurable.py:179
GaudiKernel.Configurable.Configurable.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:440
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:163
GaudiKernel.Configurable.Configurable.getFullJobOptName
def getFullJobOptName(self)
Definition: Configurable.py:824
GaudiKernel.Configurable.ConfigurableAlgorithm.__hash__
def __hash__(self)
Definition: Configurable.py:1198
GaudiKernel.Configurable.Configurable._configurationLocked
_configurationLocked
Definition: Configurable.py:177
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:1167
GaudiKernel.Configurable.Configurable.isApplicable
def isApplicable(self)
Definition: Configurable.py:1067
GaudiPartProp.Service.iService
iService
Definition: Service.py:37
GaudiKernel.Configurable.ConfigurableGeneric._properties
_properties
Definition: Configurable.py:1096
GaudiKernel.Configurable.Configurable
Definition: Configurable.py:148
GaudiKernel.Configurable.CreateSequencesVisitor.__init__
def __init__(self)
Definition: Configurable.py:1787
GaudiKernel.GaudiHandles
Definition: GaudiHandles.py:1
GaudiKernel.Configurable.ConfigurableAlgTool
Definition: Configurable.py:1241
GaudiKernel.Configurable.ConfigurableUser.__addPassiveUseOf
def __addPassiveUseOf(self, other)
Definition: Configurable.py:1436
GaudiKernel.Configurable.ConfigurableService.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:1216
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:1275
GaudiKernel.Configurable.Configurable.getDefaultProperty
def getDefaultProperty(cls, name)
Definition: Configurable.py:751
GaudiKernel.Configurable.Configurable.setParent
def setParent(self, parentName)
Definition: Configurable.py:562
GaudiKernel.Configurable.expandvars
def expandvars(data)
Definition: Configurable.py:76
GaudiKernel.Configurable.ConfigurableAuditor.getHandle
def getHandle(self)
Definition: Configurable.py:1342
GaudiKernel.GaudiHandles.PublicToolHandle
Definition: GaudiHandles.py:96
GaudiKernel.Configurable.Configurable.remove
def remove(self, items)
Definition: Configurable.py:549
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
GaudiConfig.ControlFlow.AndNode
Definition: ControlFlow.py:125