ATLAS Offline Software
Configurable.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 # File: AthenaCommon/python/Configurable.py
4 # Author: Wim Lavrijsen (WLavrijsen@lbl.gov)
5 # Author: Martin Woudstra (Martin.Woudstra@cern.ch)
6 
7 import copy, os, weakref
8 from AthenaCommon import ConfigurableMeta
9 
10 # Note: load iProperty etc. from GaudiPython only as-needed
11 import GaudiKernel.GaudiHandles as GaudiHandles
12 import GaudiKernel.DataHandle as DataHandle
13 from collections.abc import MutableSequence
14 
15 
16 __version__ = '3.2.0'
17 __author__ = 'Wim Lavrijsen (WLavrijsen@lbl.gov)'
18 
19 __all__ = [ 'Configurable',
20  'ConfigurableAlgorithm', 'ConfigurablePyAlgorithm',
21  'ConfigurableAlgTool',
22  'ConfigurableAuditor',
23  'ConfigurableService',
24  'ConfigurableUser'
25  ]
26 
27 
28 
29 from AthenaCommon.Logging import logging
30 log = logging.getLogger( 'Configurable' )
31 
32 
33 # Context Manager to set Configurable behavior
35  def __init__(self, target_state=True):
36  self._target_state = target_state
37  self._previous_state = None
38  def __enter__(self):
39  self._previous_state = Configurable._useGlobalInstances
40  # CA does not use global instances:
41  Configurable._useGlobalInstances = not self._target_state
42  def __exit__(self, exception_type, exception_value, traceback):
43  Configurable._useGlobalInstances = self._previous_state
44 
45 
46 
48  """Base class for Gaudi components that implement the IProperty interface.
49  Provides most of the boilerplate code, but the actual useful classes
50  are its derived ConfigurableAlgorithm, ConfigurableService, and
51  ConfigurableAlgTool."""
52 
53  # for detecting the default name
54  class DefaultName:
55  pass
56 
57  # for collecting default values
59  pass
60 
61  propertyNoValue = '<no value>'
62  indentUnit = '| '
63  printHeaderWidth=100
64  printHeaderPre=5
65 
66  _fInSetDefaults = 0x01 # currently setting default values
67  _fIsLocked = 0x02 # track configurable to be locking
68  _fIsPrinting = 0x04 # inside __str__ to avoid setting of private AlgTools
69  _fInitOk = 0x08 # used to enforce base class init
70  _fSetupOk = 0x10 # for debugging purposes (temporary (?))
71 
72  __slots__ = (
73  '__weakref__', # required for dealing with weak references
74  '__children', # controlled components, e.g. private AlgTools
75  '_name', # the (unqualified) component name
76  '_flags', # see list of flags above
77  )
78 
79  allConfigurables = weakref.WeakValueDictionary() # just names would do,
80  # but currently refs to the actual configurables
81  # are used for debugging purposes
82 
83  _printOnce = 0
84 
85  # The default is the pre-ComponentAccumulator behavior, i.e. use
86  # a global namespace for configurable instances:
87  _useGlobalInstances = True
88 
89  def __new__ ( cls, *args, **kwargs ):
90  """To Gaudi, any object with the same type/name is the same object. Hence,
91  this is mimicked in the configuration: instantiating a new Configurable
92  of a type with the same name will return the same instance."""
93 
94  # try to get the name of the Configurable (having a name is compulsory)
95  if 'name' in kwargs:
96  # simple keyword (by far the easiest)
97  name = kwargs[ 'name' ]
98  elif 'name' in cls.__init__.__code__.co_varnames:
99  # either positional in args, or default
100  index = list(cls.__init__.__code__.co_varnames).index( 'name' )
101  try:
102  # var names index is offset by one as __init__ is to be called with self
103  name = args[ index - 1 ]
104  except IndexError:
105  # retrieve default value, then
106  name = cls.__init__.__defaults__[ index - (len(args)+1) ]
107  else:
108  # positional index is assumed (will work most of the time)
109  try:
110  name = args[1] # '0' is for self
111  except (IndexError,TypeError):
112  raise TypeError( 'no "name" argument while instantiating "%s"' % cls.__name__ )
113 
114  if name == Configurable.DefaultName:
115  # select either conventional name, or the type of the class
116  if hasattr( cls, 'DefaultedName' ):
117  name = cls.DefaultedName
118  else:
119  name = cls.getType()
120  elif not name or type(name) is not str:
121  # unnamed, highly specialized user code, etc. ... unacceptable
122  raise TypeError( 'could not retrieve name from %s.__init__ arguments' % cls.__name__ )
123 
124  # close backdoor access to otherwise private subalgs/tools
125  if 0 <= name.find( '.' ):
126  raise NameError( '"%s": Gaudi name indexing with "." to private configurables not '
127  'allowed, as it leads to uncheckable backdoors' % name )
128 
129  if 0 <= name.find( '/' ):
130  raise NameError( '"%s": type separator "/" no allowed in component name, '
131  'typename is derived from configurable instead' % name )
132 
133  if cls._useGlobalInstances:
134  # ordinary recycle case
135  try:
136  conf = cls.configurables[ name ]
137 
138  # initialize additional properties, if any
139  for n,v in kwargs.items():
140  try:
141  setattr( conf, n, v )
142  except AttributeError as originalAttributeError:
143 
144  # now for a completely different can of worms ...
145  acceptableKeyWord = False
146 
147  # little helper
148  def flat( classtree ):
149  if isinstance(classtree, (list, tuple)):
150  return [ j for i in classtree for j in flat( i ) ]
151  else:
152  return [ classtree ]
153 
154  # the following attempts to figure out if the missing attribute
155  # is in fact an acceptable formal function argument to __init__,
156  import inspect
157  allclasses = flat( inspect.getclasstree( [ conf.__class__ ] ) )
158  for confklass in allclasses:
159  try:
160  # the following may result in the same init tried several
161  # times, but we shouldn't be in this loop too often anyway
162  if n in confklass.__init__.__code__.co_varnames:
163  acceptableKeyWord = True
164  break
165  except AttributeError:
166  pass
167 
168  # raising here will break the usage of keywords in __init__, but
169  # there don't appear to be such cases in ATLAS yet ...
170  if not acceptableKeyWord:
171  raise originalAttributeError
172  return conf
173  except KeyError:
174  pass
175  else:
176  #Run 3 style config
177  #Uncomment this line to verify that RecExCommon doesn't use that
178  #print "Run 3 style config"
179  pass #end if not new configuration approach
180  # still here: create a new instance ...
181  conf = object.__new__( cls )
182 
183  # ... python convention says to silently return, if __new__ fails ...
184  if conf is None:
185  return
186 
187  # ... initialize it
188  cls.__init__( conf, *args, **kwargs )
189 
190  # update normal, per-class cache
191  if cls._useGlobalInstances:
192  cls.configurables[ name ] = conf
193 
194  # update generics super-cache
195  if name in cls.allConfigurables and conf.getType() != cls.allConfigurables[ name ].getType():
196  raise TypeError( 'attempt to redefine type of "%s" (was: %s, new: %s)' %
197  (name,cls.allConfigurables[ name ].getType(), conf.getType()) )
198  cls.allConfigurables[ name ] = conf
199 
200  return conf
201 
202  # constructor
203  def __init__( self, name = DefaultName ):
204  # check class readiness, all required overloads should be there now
205  klass = self.__class__
206 
207  # this is an abstract class
208  if klass == Configurable:
209  raise TypeError( "%s is an ABC and can not be instantiated" % str(Configurable))
210 
211  # for using this Configurable as a (Gaudi) sequence
212  self.__children = []
213 
214  # know who we are
215  if name == Configurable.DefaultName:
216  if hasattr( self.__class__, 'DefaultedName' ):
217  self._name = self.__class__.DefaultedName
218  else:
219  self._name = self.getType()
220  else:
221  self._name = name
222 
223  self._flags = 0
224 
225  # set to True when collecting defaults, False otherwise
226  self._flags &= ~self._fInSetDefaults
227 
228  # set to True when locked, False otherwise
229  self._flags &= ~self._fIsLocked
230 
231  # set to True when inside __str__ (volatile - not stored on file)
232  self._flags &= ~self._fIsPrinting
233 
234  # for later, in case __init__ itself is overridden
235  self._flags |= self._fInitOk
236 
237  # for debugging purposes (temporary (?))
238  self._flags &= ~self._fSetupOk
239 
240  # pickle support
241  def __getstate__( self ):
242  d = {}
243  for name, proxy in self._properties.items():
244  try:
245  d[ name ] = proxy.__get__( self )
246  except AttributeError:
247  pass
248 
249  d[ '_Configurable__children' ] = self.__children
250  d[ '_name' ] = self._name
251  if hasattr(self, '_jobOptName'):
252  d[ '_jobOptName' ] = self.getJobOptName()
253  d[ '_fIsLocked' ] = self.isLocked()
254 
255  return d
256 
257  def __setstate__( self, dct ):
258  # flags are set to neutral, not from pickle except for lockedness
259  self._flags = 0
260  self._flags |= self._fInitOk
261  self._flags &= ~self._fInSetDefaults
262  if '_fIsLocked' in dct:
263  if dct[ '_fIsLocked' ]:
264  self._flags &= self._fIsLocked
265  else:
266  self._flags &= ~self._fIsLocked
267  del dct['_fIsLocked']
268  self._flags &= ~self._fIsPrinting
269  for (n, v) in dct.items():
270  setattr( self, n, v )
271 
272  return
273 
274  def __getnewargs__( self ):
275  return (self._name,)
276 
277  # to allow a few basic sanity checks, as well as nice syntax
278  def __len__( self ):
279  return len( self.__children )
280 
281  def __iter__( self ):
282  return iter( self.__children )
283 
284  # ownership rules of self through copying
285  def __deepcopy__( self, memo ):
286  newconf = object.__new__( self.__class__ )
287  self.__class__.__init__( newconf, self.getName() )
288 
289  for proxy in self._properties.values():
290  try:
291  proxy.__set__( newconf, proxy.__get__( self ) )
292  except AttributeError:
293  pass # means property was not set for self
294 
295  for c in self.__children:
296  newconf += c # processes proper copy semantics
297 
298  return newconf
299 
300  # hierarchy building, and ownership rules of children
301  def __iadd__( self, configs, descr = None, index = None ):
302  if self.isLocked():
303  raise RuntimeError( f"cannot add children to locked configurable {self.getJobOptName()}" )
304 
305  if not type(configs) in (list,tuple):
306  configs = ( configs, )
307 
308  joname = self.getJobOptName()
309 
310  for cfg in configs:
311  # prevent type mismatches
312  if not isinstance( cfg, Configurable ):
313  raise TypeError( "'%s' is not a Configurable" % str(cfg) )
314 
315  cc = self.copyChildAndSetParent( cfg, joname )
316 
317  # filters dupes; usually "ok" (backdoor should catch them)
318  ccjo = cc.getJobOptName()
319  for c in self.__children:
320  if c.getJobOptName() == ccjo:
321  log.debug( 'attempt to add a duplicate (%s.%s) ... dupe ignored', joname or self.name(), ccjo )
322  break
323  else:
324  if index is None:
325  self.__children.append( cc )
326  else:
327  self.__children.insert( index, cc )
328 
329  try:
330  if descr: # support for tool properties
331  descr.__set__( self, cc )
332  else:
333  setattr( self, cc.getName(), cc )
334  except AttributeError:
335  pass # to allow free addition of tools/subalgorithms
336 
337  return self
338 
339  def __getattr__( self, attr ): # until ToolProperties exist ...
340  if attr[0] == "_":
341  return super( Configurable, self ).__getattribute__(attr)
342  for c in self.__children:
343  if c.getName() == attr:
344  return c
345 
346  raise AttributeError( "'%s' object has no attribute '%s'" % (self.__class__,attr) )
347 
348  def __delattr__( self, attr ):
349  # remove as property, otherwise try as child
350  try:
351  # remove history etc., then reset to default (in case set before)
352  prop = self._properties[ attr ]
353  prop.__delete__( self )
354  prop.__set__( self, prop.default )
355  return # reaches here? was property: done now
356  except KeyError:
357  pass
358 
359  # otherwise, remove child, if one is so named
360  for c in self.__children:
361  if c.getName() == attr:
362  self.__children.remove( c )
363 
364  # potentially, there are left over caches (certain user derived classes)
365  try:
366  del self.__dict__[ attr ]
367  except (AttributeError,KeyError):
368  pass
369 
370  def remove( self, items ):
371  if not isinstance(items, (list, tuple)):
372  items = [ items ]
373 
374  self.__children = [ e for e in self.__children if e not in items ]
375 
376  def removeAll( self ):
377  self.remove( self.__children )
378 
379  # to copy a full configuration
380  def clone( self, newname ):
381  if newname == self.getName():
382  log.error( 'not cloning %s, because new name given is same as old name', self.getName() )
383  return None
384 
385  return self.__class__( newname, **self.getValuedProperties() )
386 
387  # called by __iadd__; determines child copy semantics
388  def copyChild( self, child ):
389  return copy.deepcopy( child )
390 
391  def setParent( self, parentName ):
392  pass
393 
394  def getParent( self ):
395  return ""
396 
397  def hasParent( self, parent ):
398  return False
399 
400  def copyChildAndSetParent(self,cfg,parent):
401  cc = self.copyChild( cfg )
402 
403  if hasattr( cc, 'setParent' ) and parent:
404  cc.setParent( parent )
405 
406  return cc
407 
408  def getChildren( self ):
409  return self.__children[:] # read only
410 
411  def overwriteChild( self, idx, newChild ):
412  self.__children[idx] = newChild
413 
414  def getAllChildren( self ):
415  """Get all (private) configurable children, both explicit ones (added with +=)
416  and the ones in the private GaudiHandle properties"""
417  childs = []
418  # add private configurable properties (also inside handles)
419  for proxy in self._properties.values():
420  try:
421  c = proxy.__get__( self )
422  except AttributeError:
423  pass
424  else:
425  if isinstance(c,Configurable) and not c.isPublic():
426  childs.append(c)
427  elif isinstance(c,GaudiHandles.GaudiHandle):
428  try:
429  conf = c.configurable
430  except AttributeError:
431  pass
432  else:
433  if not conf.isPublic():
434  childs.append(conf)
435  elif isinstance(c,GaudiHandles.GaudiHandleArray):
436  # only setup private arrays
437  if not c.isPublic():
438  for ci in c:
439  if isinstance(ci,Configurable):
440  childs.append(ci)
441  else:
442  try:
443  conf = ci.configurable
444  except AttributeError:
445  pass
446  else:
447  childs.append(conf)
448 
449  # add explicit children
450  childs += self.__children
451  return childs
452 
453  def getSequence( self ):
454  elems = []
455  for c in self.__children:
456  elems.append( c.getFullName() )
457  return elems
458 
459  def setup( self ):
460  # make sure base class init has been called
461  if not hasattr(self,'_fInitOk') or not self._fInitOk:
462  # could check more, but this is the only explanation
463  raise TypeError("Configurable.__init__ not called in %s override" % self.__class__.__name__)
464 
465  # setup self: this collects all values on the python side
466  self.__setupDlls()
467  self.__setupDefaults()
468 
469  # setup children
470  for c in self.getAllChildren():
471  c.setup()
472 
473  # now get handle to work with for moving properties into the catalogue
474  handle = self.getHandle()
475  if not handle:
476  log.debug( 'no handle for %s: not transporting properties', self._name )
477  return # allowed, done early
478 
479  # pass final set of properties on to handle on the C++ side or JobOptSvc
480  for name in self._properties.keys():
481  if hasattr( self, name ): # means property has python-side value/default
482  setattr( handle, name, getattr(self,name) )
483 
484  # for debugging purposes
485  self._flags |= self._fSetupOk
486 
487  def lock( self ):
488  # prevent any further changes, unless unlocked
489  self._flags |= self._fIsLocked
490 
491  # same for any of its private ToolHandle properties
492  for k, v in self.getProperties().items():
493  if isinstance( v, Configurable ):
494  v.lock()
495 
496  # leave children alone ... most likely are public (and can't check otherwise)
497 
498  def unlock( self ):
499  # allow again changes to be made
500  import sys, traceback
501  stack = traceback.extract_stack( sys._getframe(1), 1 )
502  log.warning( 'unlock() called on configurable "%s" in %s', self.getJobOptName(), stack[0][0] )
503  self._flags &= ~self._fIsLocked
504 
505  # note that unlock() does not unlock the children; do that individually
506 
507  def isLocked( self ):
508  # check whether this configurable is currently locked
509  return self._flags & self._fIsLocked
510 
511  def isPrinting( self ):
512  # check whether this configurable is currently being printed (see PropertyProxy.py)
513  return self._flags & self._fIsPrinting
514 
515  def getProperties( self ):
516  props = {}
517  for name, proxy in self._properties.items():
518  try:
519  props[ name ] = proxy.__get__( self )
520  except AttributeError:
521  props[ name ] = Configurable.propertyNoValue
522 
523  return props
524 
525  def getValuedProperties( self ):
526  props = {}
527  for name, proxy in self._properties.items():
528  try:
529  value = proxy.__get__( self )
530  if hasattr(value, 'getFullName') :
531  value = value.getFullName()
532  elif type(value) is list and len(value) > 0 and hasattr(value[0], 'getFullName'):
533  value = [ i.getFullName() for i in value ]
534  props[ name ] = value
535  except AttributeError:
536  pass
537 
538  return props
539 
540  def properties( self ):
541  return self.getProperties() # compatibility
542 
543  @classmethod
545 
546  # user provided defaults
548  cls.setDefaults( c )
549 
550  # defaults from C++
551  for k,v in cls._properties.items():
552  if k not in c.__dict__ and hasattr( v, 'default' ):
553  c.__dict__[ k ] = v.default
554 
555  return c.__dict__
556 
557  @classmethod
558  def getDefaultProperty( cls, name ):
559 
560  # user provided defaults
562  cls.setDefaults( c )
563 
564  if name in c.__dict__:
565  return c.__dict__[ name ]
566 
567  # defaults from C++
568  try:
569  v = cls._properties[name]
570  if hasattr( v, 'default' ):
571  return v.default
572  except KeyError:
573  pass
574 
575  return None
576 
577  def getType( cls ):
578  return cls.__name__
579 
580  def getName( self ):
581  return self._name
582 
583  def name( self ):
584  return self.getName()
585 
586  def getJobOptName( self ): # full hierachical name
587  return self.getName()
588 
589  def isPublic( self ):
590  return True
591 
592  # for a couple of existing uses out there
593  def getFullName( self ) :
594  return str( self.getType() + '/' + self.getName() )
595 
596  def getFullJobOptName( self ):
597  return "%s/%s" % (self.getType(),self.getJobOptName() or self.getName())
598 
599  def getPrintTitle(self):
600  return self.getGaudiType() + ' ' + self.getTitleName()
601 
602  def getTitleName( self ):
603  if log.isEnabledFor( logging.DEBUG ):
604  return self.getFullJobOptName()
605  else:
606  return self.getFullName()
607 
608  def setDefaults( cls, handle ):
609  pass
610 
611  def _isInSetDefaults( self ):
612  return self._flags & self._fInSetDefaults
613 
614  def __setupDlls( self ):
615  dlls = self.getDlls()
616  if not dlls:
617  dlls = []
618  elif isinstance(dlls, str):
619  dlls = [ dlls ]
620 
621  from AthenaCommon.AppMgr import theApp
622  dlls = filter( lambda d: d not in theApp.Dlls, dlls )
623  if dlls: theApp.Dlls += dlls
624 
625  def __setupDefaults( self ):
626  # set handle defaults flags to inform __setattr__ that it is being
627  # called during setDefaults of the concrete Configurable
628  self._flags |= self._fInSetDefaults
629  self.setDefaults( self )
630  self._flags &= ~self._fInSetDefaults
631 
632  @staticmethod
633  def _printHeader( indentStr, title ):
634  preLen = Configurable.printHeaderPre
635  postLen = Configurable.printHeaderWidth - preLen - 3 - len(title)# - len(indentStr)
636  postLen = max(preLen,postLen)
637  return indentStr + '/%s %s %s' % (preLen*'*',title,postLen*'*')
638 
639  @staticmethod
640  def _printFooter( indentStr, title ):
641  preLen = Configurable.printHeaderPre
642  postLen = Configurable.printHeaderWidth - preLen - 12 - len(title)# - len(indentStr)
643  postLen = max(preLen,postLen)
644  return indentStr + '\\%s (End of %s) %s' % (preLen*'-',title,postLen*'-')
645 
646  def __repr__( self ):
647  return '<%s at %s>' % (self.getFullJobOptName(),hex(id(self)))
648 
649  def __str__( self, indent = 0, headerLastIndentUnit=indentUnit ):
650  def _sorted_repr_set(value):
651  """Helper to print sorted set representation"""
652  return "{" + repr(sorted(value))[1:-1] + "}" if value else "set()"
653 
654  indentStr = indent*Configurable.indentUnit
655  # print header
656  title = self.getPrintTitle()
657 
658  # if run under WARNING and hight only, stick with title
659  if logging.WARNING <= log.level:
660  if not Configurable._printOnce:
661  Configurable._printOnce = 1
662  return "Reduced Configurable printout; change log level for more details, e.g.:\n import AthenaCommon.Configurable as Configurable\n Configurable.log.setLevel( INFO )\n" + title
663  else:
664  return title
665 
666  # avoid auto-setting private AlgTools while doing printout
667  self._flags |= self._fIsPrinting
668 
669  # print line to easily see start-of-configurable
670  if indent > 0:
671  headerIndent = (indent-1)*Configurable.indentUnit + headerLastIndentUnit
672  else:
673  headerIndent = ''
674  rep = Configurable._printHeader( headerIndent, title )
675  rep += os.linesep
676  # print own properties
677  props = self.getProperties()
678  defs = self.getDefaultProperties()
679  if not props:
680  rep += indentStr + '|-<no properties>' + os.linesep
681  else:
682  # get property name with
683  nameWidth = 0
684  for p in props.keys():
685  nameWidth=max(nameWidth,len(p))
686  propNames = sorted(props.keys())
687  for p in propNames:
688  v = props[p]
689  # start with indent and property name
690  prefix = indentStr + '|-%-*s' % (nameWidth,p)
691  # add memory address for debugging (not for defaults)
692  if log.isEnabledFor( logging.DEBUG ):
693  if v != Configurable.propertyNoValue:
694  address = ' @%11s' % hex(id(v))
695  else:
696  address = 13*' '
697  prefix += address
698  # add value and default
699  default = defs.get(p)
700 
701  if not isinstance(v,MutableSequence) and v == Configurable.propertyNoValue:
702  # show default value as value, and no extra 'default'
703  strVal = repr(default)
704  strDef = None
705  else:
706  # convert configurable to handle
707  if isinstance(v,Configurable):
708  vv = v.getGaudiHandle()
709  else:
710  vv = v
711  if isinstance(vv,(GaudiHandles.GaudiHandle,
712  GaudiHandles.GaudiHandleArray,
713  DataHandle.DataHandle)):
714  strVal = repr(vv)
715  strDef = repr(default.toStringProperty())
716  if strDef == repr(vv.toStringProperty()):
717  strDef = None
718  elif isinstance(vv, set):
719  strVal = _sorted_repr_set(vv)
720  strDef = _sorted_repr_set(default)
721  else:
722  strVal = repr(vv)
723  strDef = repr(default)
724  # add the value
725  line = prefix + ' = ' + strVal
726  # add default if present
727  if strDef is not None:
728  # put default on new line if too big
729  if len(line) + len(strDef) > Configurable.printHeaderWidth:
730  line += os.linesep + indentStr + '| ' + (len(prefix)-len(indentStr)-3)*' '
731  line += ' (default: %s)' % (strDef,)
732  # add the line to the total string
733  rep += line + os.linesep
734 
735  # print configurables + their properties, or loop over sequence
736  childNotToSort = []
737  childToSort = []
738  for c in self.getAllChildren():
739  if isinstance(c, ConfigurableAlgorithm): childNotToSort.append(c)
740  else: childToSort.append(c)
741  # sort the non-algs
742  childToSort.sort(key=lambda x : x.getName())
743  for cfg in childToSort + childNotToSort:
744  rep += cfg.__str__( indent + 1, '|=' ) + os.linesep
745 
746  # print line to easily see end-of-configurable. Note: No linesep!
747  rep += Configurable._printFooter( indentStr, title )
748 
749  self._flags &= ~self._fIsPrinting
750  return rep
751 
752  # hash method for set/dict operations
753  # first attempt, assuming need to recurse into child properties
754  # if too much overhead, could attempt to cache with python
755  # properties, but hard to propagate changes upwards to parents
756 
758  self._flags |= self._fIsPrinting
759  properties = self.getValuedProperties()
760  propstr = ""
761  for key,val in sorted(properties.items()):
762  if isinstance(val, (GaudiHandles.PublicToolHandle, GaudiHandles.PrivateToolHandle)):
763  propstr += val.getFullName()
764  elif isinstance(val,Configurable):
765  propstr += "({0}:{1})".format(key,val.getFlattenedProperties())
766  elif isinstance(val, (GaudiHandles.PublicToolHandleArray, GaudiHandles.PrivateToolHandleArray)):
767  for th in val:
768  # Handle ToolHandles that have just been set as strings(?)
769  if isinstance(th,Configurable):
770  propstr += "({0}:{1}".format(th.getFullName(), th.getFlattenedProperties())
771  else:
772  propstr += th.getFullName()
773  else:
774  propstr += "({0}:{1})".format(key,str(val))
775  self._flags &= ~self._fIsPrinting
776  return propstr
777 
778  def getStrDescriptor(self):
779 
780  descr = ""
781  if hasattr( self,"_name" ):
782  propstr = self.getFlattenedProperties()
783  descr = (self.getFullName(), propstr)
784  else: # Not yet initialised?
785  descr = self.getType()
786 
787  return descr
788 
789  # # (in)equality operators, based on hash
790  def __eq__(self,rhs):
791  # Check identity first
792  if self is rhs: return True
793  # Avoid comparing against None...
794  if not rhs: return False
795  # Class check
796  if not isinstance(rhs,Configurable): return False
797  # Type/Name check
798  if self.getFullName() != rhs.getFullName(): return False
799  # If identical types and names, then go the whole hog and test children
800  # Could be sped up by testing property by property...
801  return self.getStrDescriptor() == rhs.getStrDescriptor()
802  def __ne__(self,rhs):
803  return (not self.__eq__(rhs))
804 
805  __hash__ = object.__hash__
806 
807  def __bool__ (self):
808  return True
809 
810 
811 
812 
814  __slots__ = { '_jobOptName' : 0, 'OutputLevel' : 0, \
815  'Enable' : 1, 'ErrorMax' : 1, 'ErrorCounter' : 0, 'AuditAlgorithms' : 0, \
816  'AuditInitialize' : 0, 'AuditReinitialize' : 0, 'AuditExecute' : 0, \
817  'AuditFinalize' : 0 }
818 
819  def __init__( self, name = Configurable.DefaultName ):
820  super( ConfigurableAlgorithm, self ).__init__( name )
821  name = self.getName()
822  self._jobOptName = name[ name.find('/')+1 : ] # strips class
823 
824  def __deepcopy__( self, memo ):
825  return self # algorithms are always shared
826 
827  def getHandle( self ):
828  try:
829  from GaudiPython.Bindings import iAlgorithm
830  except ImportError:
831  from gaudimodule import iAlgorithm
832  return iAlgorithm( self.getJobOptName() )
833 
834  def getGaudiType( self ):
835  return 'Algorithm'
836 
837  def getJobOptName( self ):
838  return self._jobOptName
839 
840 
841 
843  __slots__ = { 'OutputLevel' : 0, \
844  'AuditServices' : 0, 'AuditInitialize' : 0, 'AuditFinalize' : 0 }
845 
846  def __deepcopy__( self, memo ):
847  return self # services are always shared
848 
849  def copyChild( self, child ):
850  # Copy private tools but all else is shared
851  if isinstance(child, ConfigurableAlgTool) and not child.isPublic():
852  return copy.deepcopy( child )
853  else:
854  return child
855 
856  def getHandle( self ):
857  try:
858  from GaudiPython.Bindings import iService
859  except ImportError:
860  from gaudimodule import iService
861  return iService( self._name )
862 
863  def getGaudiType( self ):
864  return 'Service'
865 
866  def getGaudiHandle( self ):
867  return GaudiHandles.ServiceHandle( self.toStringProperty() )
868 
869  def toStringProperty( self ):
870  # called on conversion to a string property for the jocat
871  return self.getName()
872 
873 
874 
876  __slots__ = { '_jobOptName' : '', 'OutputLevel' : 0, \
877  'AuditTools' : 0, 'AuditInitialize' : 0, 'AuditFinalize' : 0 }
878 
879  def __init__( self, name = Configurable.DefaultName ):
880  super( ConfigurableAlgTool, self ).__init__( name )
881  name = self.getName()
882  name = name[ name.find('/')+1 : ] # strips class, if any
883  self._jobOptName = name
884 
885  def getHandle( self ):
886  # iAlgTool isn't useful, unless one knows for sure that the tool exists
887  try:
888  from GaudiPython.Bindings import iProperty
889  except ImportError:
890  from gaudimodule import iProperty
891  return iProperty( self.getJobOptName() )
892 
893  def getGaudiType( self ):
894  return 'AlgTool'
895 
896  def getGaudiHandle( self ):
897  if self.isPublic():
898  return GaudiHandles.PublicToolHandle( self.toStringProperty() )
899  else:
900  return GaudiHandles.PrivateToolHandle( self.toStringProperty() )
901 
902  def getPrintTitle(self):
903  if self.isPublic():
904  pop = 'Public '
905  else:
906  pop = 'Private '
907  return pop + Configurable.getPrintTitle(self)
908 
909  def setParent( self, parentName ):
910 # print "ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName)
911 # print "Calling stack:"
912 # import traceback
913 # traceback.print_stack()
914  # propagate parent to AlgTools in children
915  for c in self.getAllChildren():
916  if isinstance(c,ConfigurableAlgTool): c.setParent( parentName )
917 
918  # update my own parent
919  self._jobOptName = parentName + '.' + self._jobOptName
920 
921 
922  def getParent( self ):
923  dot = self._jobOptName.rfind('.')
924  if dot != -1:
925  return self._jobOptName[:dot]
926  else:
927  return ""
928 
929  def getDirectParent( self ):
930  parent = self.getParent()
931  dot = parent.rfind('.')
932  if dot != -1:
933  return parent[dot+1:]
934  else:
935  return parent
936 
937  def hasParent( self, parent ):
938  return self._jobOptName.startswith( parent + '.' )
939 
940  def getJobOptName( self ):
941  return self._jobOptName
942 
943  def isPublic( self ):
944  return self.isInToolSvc()
945 
946  def isInToolSvc( self ):
947  return self.getParent() == 'ToolSvc'
948 
949  def toStringProperty( self ):
950  # called on conversion to a string property for the jocat
951  return self.getType() + '/' + self.getName()
952 
953 
954 
956  __slots__ = { '_jobOptName' : 0, 'OutputLevel' : 0, \
957  'Enable' : 1 }
958 
959  def __init__( self, name = Configurable.DefaultName ):
960  super( ConfigurableAuditor, self ).__init__( name )
961  name = self.getName()
962  name = name[ name.find('/')+1 : ] # strips class, if any
963  self._jobOptName = name
964 
965  def getHandle( self ):
966  # Auditor handles don't exist ... use iProperty
967  try:
968  from GaudiPython.Bindings import iProperty
969  except ImportError:
970  from gaudimodule import iProperty
971  return iProperty( self.getJobOptName() )
972 
973  def getGaudiType( self ):
974  return 'Auditor'
975 
976  def getJobOptName( self ):
977  return self._jobOptName
978 
979  def toStringProperty( self ):
980  # called on conversion to a string property for the jocat
981  return self.getType() + '/' + self.getName()
982 
983  pass # class ConfigurableAuditor
984 
985 
986 
988  def __init__( self, name, **kwargs ):
989  super( ConfigurableAlgorithm, self ).__init__( name )
990  self._jobOptName = name
991 
992  for n, v in kwargs.items():
993  setattr(self, n, v)
994 
995  def getDlls( self ):
996  return None
997 
998  def getHandle( self ):
999  return None
1000 
1001 
1002 
1004  __slots__ = {}
1005 
1006  def __init__( self, name = Configurable.DefaultName, **kwargs ):
1007  super( ConfigurableUser, self ).__init__( name )
1008  for n, v in kwargs.items():
1009  setattr(self, n, v)
1010 
1011  def getGaudiType( self ):
1012  return 'User'
1013 
1014  def getDlls( self ):
1015  return None
1016 
1017  def getHandle( self ):
1018  return None
python.Configurable.ConfigurableCABehavior._previous_state
_previous_state
Definition: Configurable.py:37
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
python.Configurable.ConfigurableUser.getHandle
def getHandle(self)
Definition: Configurable.py:1017
python.Configurable.Configurable.isPublic
def isPublic(self)
Definition: Configurable.py:589
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
python.Configurable.Configurable.__repr__
def __repr__(self)
Definition: Configurable.py:646
python.Configurable.ConfigurableUser
Definition: Configurable.py:1003
python.Configurable.ConfigurableService.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:846
python.Configurable.Configurable.getDefaultProperties
def getDefaultProperties(cls)
Definition: Configurable.py:544
python.Configurable.Configurable.getProperties
def getProperties(self)
Definition: Configurable.py:515
python.Configurable.ConfigurableAlgTool.getHandle
def getHandle(self)
Definition: Configurable.py:885
vtune_athena.format
format
Definition: vtune_athena.py:14
python.Configurable.Configurable.DefaultName
Definition: Configurable.py:54
python.Configurable.Configurable.__getstate__
def __getstate__(self)
Definition: Configurable.py:241
python.Configurable.ConfigurableAuditor.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:973
python.Configurable.ConfigurableAuditor
Definition: Configurable.py:955
python.Configurable.Configurable._printHeader
def _printHeader(indentStr, title)
Definition: Configurable.py:633
index
Definition: index.py:1
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
python.Configurable.Configurable.lock
def lock(self)
Definition: Configurable.py:487
python.Configurable.ConfigurableAlgTool
Definition: Configurable.py:875
python.Configurable.ConfigurableAlgorithm.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:824
python.Configurable.Configurable.getFullJobOptName
def getFullJobOptName(self)
Definition: Configurable.py:596
python.Configurable.ConfigurablePyAlgorithm.getHandle
def getHandle(self)
Definition: Configurable.py:998
python.Configurable.ConfigurablePyAlgorithm.__init__
def __init__(self, name, **kwargs)
Definition: Configurable.py:988
python.Configurable.Configurable.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:285
python.Configurable.Configurable.__new__
def __new__(cls, *args, **kwargs)
Definition: Configurable.py:89
python.Configurable.ConfigurableAuditor.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:959
python.Configurable.ConfigurableAlgTool.setParent
def setParent(self, parentName)
Definition: Configurable.py:909
python.Configurable.Configurable.copyChild
def copyChild(self, child)
Definition: Configurable.py:388
python.Configurable.ConfigurableAuditor.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:979
python.Configurable.ConfigurableAlgTool.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:879
python.Configurable.ConfigurableService
Definition: Configurable.py:842
python.Configurable.Configurable.__setupDefaults
def __setupDefaults(self)
Definition: Configurable.py:625
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.Configurable.Configurable.setParent
def setParent(self, parentName)
Definition: Configurable.py:391
python.Configurable.ConfigurableAuditor.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:976
python.Configurable.ConfigurableAlgorithm.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:834
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
python.Configurable.Configurable.properties
def properties(self)
Definition: Configurable.py:540
python.Configurable.Configurable._fIsPrinting
int _fIsPrinting
Definition: Configurable.py:68
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:808
python.Configurable.Configurable._isInSetDefaults
def _isInSetDefaults(self)
Definition: Configurable.py:611
python.Configurable.ConfigurableService.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:869
python.Configurable.Configurable.overwriteChild
def overwriteChild(self, idx, newChild)
Definition: Configurable.py:411
covarianceTool.filter
filter
Definition: covarianceTool.py:514
python.Configurable.Configurable.__setupDlls
def __setupDlls(self)
Definition: Configurable.py:614
python.Configurable.ConfigurableService.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:866
python.Configurable.ConfigurableAuditor.getHandle
def getHandle(self)
Definition: Configurable.py:965
python.Configurable.ConfigurableService.getHandle
def getHandle(self)
Definition: Configurable.py:856
python.Configurable.ConfigurableAlgorithm._jobOptName
_jobOptName
Definition: Configurable.py:822
python.Configurable.Configurable.setup
def setup(self)
Definition: Configurable.py:459
python.Configurable.ConfigurableUser.getDlls
def getDlls(self)
Definition: Configurable.py:1014
python.Configurable.Configurable._printFooter
def _printFooter(indentStr, title)
Definition: Configurable.py:640
python.Configurable.ConfigurableCABehavior._target_state
_target_state
Definition: Configurable.py:36
python.Configurable.ConfigurableCABehavior.__init__
def __init__(self, target_state=True)
Definition: Configurable.py:35
python.Configurable.ConfigurableAlgTool._jobOptName
_jobOptName
Definition: Configurable.py:883
python.Configurable.ConfigurableAlgTool.hasParent
def hasParent(self, parent)
Definition: Configurable.py:937
python.Configurable.Configurable.DefaultCollector
Definition: Configurable.py:58
python.Configurable.Configurable.getPrintTitle
def getPrintTitle(self)
Definition: Configurable.py:599
python.Configurable.ConfigurablePyAlgorithm.getDlls
def getDlls(self)
Definition: Configurable.py:995
python.Configurable.Configurable.getTitleName
def getTitleName(self)
Definition: Configurable.py:602
python.Configurable.ConfigurableCABehavior.__enter__
def __enter__(self)
Definition: Configurable.py:38
python.Configurable.ConfigurableAlgorithm.getHandle
def getHandle(self)
Definition: Configurable.py:827
python.Configurable.ConfigurableService.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:863
python.Configurable.ConfigurableAlgTool.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:893
python.Configurable.ConfigurableAlgorithm.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:819
python.Configurable.Configurable.removeAll
def removeAll(self)
Definition: Configurable.py:376
python.Configurable.Configurable.name
def name(self)
Definition: Configurable.py:583
PyAthena::repr
std::string repr(PyObject *o)
returns the string representation of a python object equivalent of calling repr(o) in python
Definition: PyAthenaUtils.cxx:106
python.Configurable.ConfigurableAlgTool.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:940
python.Configurable.Configurable._fInSetDefaults
int _fInSetDefaults
Definition: Configurable.py:66
python.Configurable.Configurable.unlock
def unlock(self)
Definition: Configurable.py:498
python.Configurable.Configurable.__setstate__
def __setstate__(self, dct)
Definition: Configurable.py:257
python.Configurable.Configurable.getFullName
def getFullName(self)
Definition: Configurable.py:593
python.Configurable.Configurable.__init__
def __init__(self, name=DefaultName)
Definition: Configurable.py:203
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.Configurable.Configurable.getSequence
def getSequence(self)
Definition: Configurable.py:453
python.Configurable.Configurable.getDefaultProperty
def getDefaultProperty(cls, name)
Definition: Configurable.py:558
python.Configurable.ConfigurableAlgorithm
Definition: Configurable.py:813
python.Configurable.Configurable.__str__
def __str__(self, indent=0, headerLastIndentUnit=indentUnit)
Definition: Configurable.py:649
python.Configurable.ConfigurableAlgTool.getPrintTitle
def getPrintTitle(self)
Definition: Configurable.py:902
python.Configurable.Configurable.clone
def clone(self, newname)
Definition: Configurable.py:380
python.Configurable.Configurable._name
_name
Definition: Configurable.py:217
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
python.Configurable.ConfigurableAlgTool.getParent
def getParent(self)
Definition: Configurable.py:922
python.Configurable.Configurable.__getnewargs__
def __getnewargs__(self)
Definition: Configurable.py:274
python.Configurable.Configurable.__ne__
def __ne__(self, rhs)
Definition: Configurable.py:802
python.Configurable.Configurable.getAllChildren
def getAllChildren(self)
Definition: Configurable.py:414
python.Configurable.ConfigurableUser.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1011
python.Configurable.Configurable.remove
def remove(self, items)
Definition: Configurable.py:370
python.Configurable.ConfigurableCABehavior.__exit__
def __exit__(self, exception_type, exception_value, traceback)
Definition: Configurable.py:42
python.Configurable.ConfigurableAlgTool.isPublic
def isPublic(self)
Definition: Configurable.py:943
python.Configurable.ConfigurableUser.__init__
def __init__(self, name=Configurable.DefaultName, **kwargs)
Definition: Configurable.py:1006
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.Configurable.Configurable._fInitOk
int _fInitOk
Definition: Configurable.py:69
python.Configurable.Configurable.getChildren
def getChildren(self)
Definition: Configurable.py:408
python.Configurable.Configurable.getName
def getName(self)
Definition: Configurable.py:580
python.Configurable.Configurable.isPrinting
def isPrinting(self)
Definition: Configurable.py:511
python.Configurable.Configurable.__children
__children
Definition: Configurable.py:212
python.Configurable.ConfigurableAuditor._jobOptName
_jobOptName
Definition: Configurable.py:963
python.Configurable.Configurable.copyChildAndSetParent
def copyChildAndSetParent(self, cfg, parent)
Definition: Configurable.py:400
python.Configurable.ConfigurableAlgorithm.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:837
python.Configurable.Configurable.getType
def getType(cls)
Definition: Configurable.py:577
python.Configurable.ConfigurableAlgTool.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:896
python.Configurable.ConfigurableService.copyChild
def copyChild(self, child)
Definition: Configurable.py:849
python.Configurable.Configurable
Definition: Configurable.py:47
python.Configurable.Configurable.__getattr__
def __getattr__(self, attr)
Definition: Configurable.py:339
python.Configurable.ConfigurableAlgTool.isInToolSvc
def isInToolSvc(self)
Definition: Configurable.py:946
python.Configurable.Configurable.__iter__
def __iter__(self)
Definition: Configurable.py:281
python.Configurable.Configurable.getValuedProperties
def getValuedProperties(self)
Definition: Configurable.py:525
python.Configurable.Configurable.hasParent
def hasParent(self, parent)
Definition: Configurable.py:397
str
Definition: BTagTrackIpAccessor.cxx:11
python.Configurable.Configurable.isLocked
def isLocked(self)
Definition: Configurable.py:507
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:801
python.Configurable.Configurable.getStrDescriptor
def getStrDescriptor(self)
Definition: Configurable.py:778
python.Configurable.Configurable.setDefaults
def setDefaults(cls, handle)
Definition: Configurable.py:608
python.Configurable.Configurable.__iadd__
def __iadd__(self, configs, descr=None, index=None)
Definition: Configurable.py:301
python.Configurable.Configurable.getFlattenedProperties
def getFlattenedProperties(self)
Definition: Configurable.py:757
python.Configurable.Configurable._flags
_flags
Definition: Configurable.py:223
python.Configurable.Configurable._fIsLocked
int _fIsLocked
Definition: Configurable.py:67
python.Configurable.Configurable.__len__
def __len__(self)
Definition: Configurable.py:278
python.Configurable.Configurable.__bool__
def __bool__(self)
Definition: Configurable.py:807
python.Configurable.ConfigurablePyAlgorithm
Definition: Configurable.py:987
python.Configurable.ConfigurableAlgTool.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:949
python.Configurable.Configurable._fSetupOk
int _fSetupOk
Definition: Configurable.py:70
python.Configurable.ConfigurableCABehavior
Definition: Configurable.py:34
python.Configurable.Configurable.__delattr__
def __delattr__(self, attr)
Definition: Configurable.py:348
python.Configurable.Configurable.__eq__
def __eq__(self, rhs)
Definition: Configurable.py:790
python.ConfigurableMeta.ConfigurableMeta
this metaclass installs PropertyProxy descriptors for Gaudi properties
Definition: ConfigurableMeta.py:22
python.Configurable.Configurable.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:586
python.Configurable.Configurable.getParent
def getParent(self)
Definition: Configurable.py:394
python.Configurable.ConfigurableAlgTool.getDirectParent
def getDirectParent(self)
Definition: Configurable.py:929