ATLAS Offline Software
Configurable.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 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 ) or isinstance( classtree, 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  global log # to print some info depending on output level
651 
652  def _sorted_repr_set(value):
653  """Helper to print sorted set representation"""
654  return "{" + repr(sorted(value))[1:-1] + "}" if value else "set()"
655 
656  indentStr = indent*Configurable.indentUnit
657  # print header
658  title = self.getPrintTitle()
659 
660  # if run under WARNING and hight only, stick with title
661  if logging.WARNING <= log.level:
662  if not Configurable._printOnce:
663  Configurable._printOnce = 1
664  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
665  else:
666  return title
667 
668  # avoid auto-setting private AlgTools while doing printout
669  self._flags |= self._fIsPrinting
670 
671  # print line to easily see start-of-configurable
672  if indent > 0:
673  headerIndent = (indent-1)*Configurable.indentUnit + headerLastIndentUnit
674  else:
675  headerIndent = ''
676  rep = Configurable._printHeader( headerIndent, title )
677  rep += os.linesep
678  # print own properties
679  props = self.getProperties()
680  defs = self.getDefaultProperties()
681  if not props:
682  rep += indentStr + '|-<no properties>' + os.linesep
683  else:
684  # get property name with
685  nameWidth = 0
686  for p in props.keys():
687  nameWidth=max(nameWidth,len(p))
688  propNames = sorted(props.keys())
689  for p in propNames:
690  v = props[p]
691  # start with indent and property name
692  prefix = indentStr + '|-%-*s' % (nameWidth,p)
693  # add memory address for debugging (not for defaults)
694  if log.isEnabledFor( logging.DEBUG ):
695  if v != Configurable.propertyNoValue:
696  address = ' @%11s' % hex(id(v))
697  else:
698  address = 13*' '
699  prefix += address
700  # add value and default
701  default = defs.get(p)
702 
703  if not isinstance(v,MutableSequence) and v == Configurable.propertyNoValue:
704  # show default value as value, and no extra 'default'
705  strVal = repr(default)
706  strDef = None
707  else:
708  # convert configurable to handle
709  if isinstance(v,Configurable):
710  vv = v.getGaudiHandle()
711  else:
712  vv = v
713  if isinstance(vv,(GaudiHandles.GaudiHandle,
714  GaudiHandles.GaudiHandleArray,
715  DataHandle.DataHandle)):
716  strVal = repr(vv)
717  strDef = repr(default.toStringProperty())
718  if strDef == repr(vv.toStringProperty()):
719  strDef = None
720  elif isinstance(vv, set):
721  strVal = _sorted_repr_set(vv)
722  strDef = _sorted_repr_set(default)
723  else:
724  strVal = repr(vv)
725  strDef = repr(default)
726  # add the value
727  line = prefix + ' = ' + strVal
728  # add default if present
729  if strDef is not None:
730  # put default on new line if too big
731  if len(line) + len(strDef) > Configurable.printHeaderWidth:
732  line += os.linesep + indentStr + '| ' + (len(prefix)-len(indentStr)-3)*' '
733  line += ' (default: %s)' % (strDef,)
734  # add the line to the total string
735  rep += line + os.linesep
736 
737  # print configurables + their properties, or loop over sequence
738  childNotToSort = []
739  childToSort = []
740  for c in self.getAllChildren():
741  if isinstance(c, ConfigurableAlgorithm): childNotToSort.append(c)
742  else: childToSort.append(c)
743  # sort the non-algs
744  childToSort.sort(key=lambda x : x.getName())
745  for cfg in childToSort + childNotToSort:
746  rep += cfg.__str__( indent + 1, '|=' ) + os.linesep
747 
748  # print line to easily see end-of-configurable. Note: No linesep!
749  rep += Configurable._printFooter( indentStr, title )
750 
751  self._flags &= ~self._fIsPrinting
752  return rep
753 
754  # hash method for set/dict operations
755  # first attempt, assuming need to recurse into child properties
756  # if too much overhead, could attempt to cache with python
757  # properties, but hard to propagate changes upwards to parents
758 
760  self._flags |= self._fIsPrinting
761  properties = self.getValuedProperties()
762  propstr = ""
763  for key,val in sorted(properties.items()):
764  if isinstance(val,GaudiHandles.PublicToolHandle) or isinstance(val,GaudiHandles.PrivateToolHandle):
765  propstr += val.getFullName()
766  elif isinstance(val,Configurable):
767  propstr += "({0}:{1})".format(key,val.getFlattenedProperties())
768  elif isinstance(val,GaudiHandles.PublicToolHandleArray) or isinstance(val,GaudiHandles.PrivateToolHandleArray):
769  for th in val:
770  # Handle ToolHandles that have just been set as strings(?)
771  if isinstance(th,Configurable):
772  propstr += "({0}:{1}".format(th.getFullName(), th.getFlattenedProperties())
773  else:
774  propstr += th.getFullName()
775  else:
776  propstr += "({0}:{1})".format(key,str(val))
777  self._flags &= ~self._fIsPrinting
778  return propstr
779 
780  def getStrDescriptor(self):
781 
782  descr = ""
783  if hasattr( self,"_name" ):
784  propstr = self.getFlattenedProperties()
785  descr = (self.getFullName(), propstr)
786  else: # Not yet initialised?
787  descr = self.getType()
788 
789  return descr
790 
791  # # (in)equality operators, based on hash
792  def __eq__(self,rhs):
793  # Check identity first
794  if self is rhs: return True
795  # Avoid comparing against None...
796  if not rhs: return False
797  # Class check
798  if not isinstance(rhs,Configurable): return False
799  # Type/Name check
800  if self.getFullName() != rhs.getFullName(): return False
801  # If identical types and names, then go the whole hog and test children
802  # Could be sped up by testing property by property...
803  return self.getStrDescriptor() == rhs.getStrDescriptor()
804  def __ne__(self,rhs):
805  return (not self.__eq__(rhs))
806 
807  __hash__ = object.__hash__
808 
809  def __bool__ (self):
810  return True
811 
812 
813 
814 
816  __slots__ = { '_jobOptName' : 0, 'OutputLevel' : 0, \
817  'Enable' : 1, 'ErrorMax' : 1, 'ErrorCounter' : 0, 'AuditAlgorithms' : 0, \
818  'AuditInitialize' : 0, 'AuditReinitialize' : 0, 'AuditExecute' : 0, \
819  'AuditFinalize' : 0 }
820 
821  def __init__( self, name = Configurable.DefaultName ):
822  super( ConfigurableAlgorithm, self ).__init__( name )
823  name = self.getName()
824  self._jobOptName = name[ name.find('/')+1 : ] # strips class
825 
826  def __deepcopy__( self, memo ):
827  return self # algorithms are always shared
828 
829  def getHandle( self ):
830  try:
831  from GaudiPython.Bindings import iAlgorithm
832  except ImportError:
833  from gaudimodule import iAlgorithm
834  return iAlgorithm( self.getJobOptName() )
835 
836  def getGaudiType( self ):
837  return 'Algorithm'
838 
839  def getJobOptName( self ):
840  return self._jobOptName
841 
842 
843 
845  __slots__ = { 'OutputLevel' : 0, \
846  'AuditServices' : 0, 'AuditInitialize' : 0, 'AuditFinalize' : 0 }
847 
848  def __deepcopy__( self, memo ):
849  return self # services are always shared
850 
851  def copyChild( self, child ):
852  # Copy private tools but all else is shared
853  if isinstance(child, ConfigurableAlgTool) and not child.isPublic():
854  return copy.deepcopy( child )
855  else:
856  return child
857 
858  def getHandle( self ):
859  try:
860  from GaudiPython.Bindings import iService
861  except ImportError:
862  from gaudimodule import iService
863  return iService( self._name )
864 
865  def getGaudiType( self ):
866  return 'Service'
867 
868  def getGaudiHandle( self ):
869  return GaudiHandles.ServiceHandle( self.toStringProperty() )
870 
871  def toStringProperty( self ):
872  # called on conversion to a string property for the jocat
873  return self.getName()
874 
875 
876 
878  __slots__ = { '_jobOptName' : '', 'OutputLevel' : 0, \
879  'AuditTools' : 0, 'AuditInitialize' : 0, 'AuditFinalize' : 0 }
880 
881  def __init__( self, name = Configurable.DefaultName ):
882  super( ConfigurableAlgTool, self ).__init__( name )
883  name = self.getName()
884  name = name[ name.find('/')+1 : ] # strips class, if any
885  self._jobOptName = name
886 
887  def getHandle( self ):
888  # iAlgTool isn't useful, unless one knows for sure that the tool exists
889  try:
890  from GaudiPython.Bindings import iProperty
891  except ImportError:
892  from gaudimodule import iProperty
893  return iProperty( self.getJobOptName() )
894 
895  def getGaudiType( self ):
896  return 'AlgTool'
897 
898  def getGaudiHandle( self ):
899  if self.isPublic():
900  return GaudiHandles.PublicToolHandle( self.toStringProperty() )
901  else:
902  return GaudiHandles.PrivateToolHandle( self.toStringProperty() )
903 
904  def getPrintTitle(self):
905  if self.isPublic():
906  pop = 'Public '
907  else:
908  pop = 'Private '
909  return pop + Configurable.getPrintTitle(self)
910 
911  def setParent( self, parentName ):
912 # print "ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName)
913 # print "Calling stack:"
914 # import traceback
915 # traceback.print_stack()
916  # propagate parent to AlgTools in children
917  for c in self.getAllChildren():
918  if isinstance(c,ConfigurableAlgTool): c.setParent( parentName )
919 
920  # update my own parent
921  self._jobOptName = parentName + '.' + self._jobOptName
922 
923 
924  def getParent( self ):
925  dot = self._jobOptName.rfind('.')
926  if dot != -1:
927  return self._jobOptName[:dot]
928  else:
929  return ""
930 
931  def getDirectParent( self ):
932  parent = self.getParent()
933  dot = parent.rfind('.')
934  if dot != -1:
935  return parent[dot+1:]
936  else:
937  return parent
938 
939  def hasParent( self, parent ):
940  return self._jobOptName.startswith( parent + '.' )
941 
942  def getJobOptName( self ):
943  return self._jobOptName
944 
945  def isPublic( self ):
946  return self.isInToolSvc()
947 
948  def isInToolSvc( self ):
949  return self.getParent() == 'ToolSvc'
950 
951  def toStringProperty( self ):
952  # called on conversion to a string property for the jocat
953  return self.getType() + '/' + self.getName()
954 
955 
956 
958  __slots__ = { '_jobOptName' : 0, 'OutputLevel' : 0, \
959  'Enable' : 1 }
960 
961  def __init__( self, name = Configurable.DefaultName ):
962  super( ConfigurableAuditor, self ).__init__( name )
963  name = self.getName()
964  name = name[ name.find('/')+1 : ] # strips class, if any
965  self._jobOptName = name
966 
967  def getHandle( self ):
968  # Auditor handles don't exist ... use iProperty
969  try:
970  from GaudiPython.Bindings import iProperty
971  except ImportError:
972  from gaudimodule import iProperty
973  return iProperty( self.getJobOptName() )
974 
975  def getGaudiType( self ):
976  return 'Auditor'
977 
978  def getJobOptName( self ):
979  return self._jobOptName
980 
981  def toStringProperty( self ):
982  # called on conversion to a string property for the jocat
983  return self.getType() + '/' + self.getName()
984 
985  pass # class ConfigurableAuditor
986 
987 
988 
990  def __init__( self, name, **kwargs ):
991  super( ConfigurableAlgorithm, self ).__init__( name )
992  self._jobOptName = name
993 
994  for n, v in kwargs.items():
995  setattr(self, n, v)
996 
997  def getDlls( self ):
998  return None
999 
1000  def getHandle( self ):
1001  return None
1002 
1003 
1004 
1006  __slots__ = {}
1007 
1008  def __init__( self, name = Configurable.DefaultName, **kwargs ):
1009  super( ConfigurableUser, self ).__init__( name )
1010  for n, v in kwargs.items():
1011  setattr(self, n, v)
1012 
1013  def getGaudiType( self ):
1014  return 'User'
1015 
1016  def getDlls( self ):
1017  return None
1018 
1019  def getHandle( self ):
1020  return None
python.Configurable.ConfigurableCABehavior._previous_state
_previous_state
Definition: Configurable.py:37
python.Configurable.ConfigurableUser.getHandle
def getHandle(self)
Definition: Configurable.py:1019
python.Configurable.Configurable.isPublic
def isPublic(self)
Definition: Configurable.py:589
python.Configurable.Configurable.__repr__
def __repr__(self)
Definition: Configurable.py:646
python.Configurable.ConfigurableUser
Definition: Configurable.py:1005
python.Configurable.ConfigurableService.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:848
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:887
max
#define max(a, b)
Definition: cfImp.cxx:41
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:975
python.Configurable.ConfigurableAuditor
Definition: Configurable.py:957
python.Configurable.Configurable._printHeader
def _printHeader(indentStr, title)
Definition: Configurable.py:633
index
Definition: index.py:1
python.Configurable.Configurable.lock
def lock(self)
Definition: Configurable.py:487
python.Configurable.ConfigurableAlgTool
Definition: Configurable.py:877
python.Configurable.ConfigurableAlgorithm.__deepcopy__
def __deepcopy__(self, memo)
Definition: Configurable.py:826
python.Configurable.Configurable.getFullJobOptName
def getFullJobOptName(self)
Definition: Configurable.py:596
python.Configurable.ConfigurablePyAlgorithm.getHandle
def getHandle(self)
Definition: Configurable.py:1000
python.Configurable.ConfigurablePyAlgorithm.__init__
def __init__(self, name, **kwargs)
Definition: Configurable.py:990
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:961
python.Configurable.ConfigurableAlgTool.setParent
def setParent(self, parentName)
Definition: Configurable.py:911
python.Configurable.Configurable.copyChild
def copyChild(self, child)
Definition: Configurable.py:388
python.Configurable.ConfigurableAuditor.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:981
python.Configurable.ConfigurableAlgTool.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:881
python.Configurable.ConfigurableService
Definition: Configurable.py:844
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:978
python.Configurable.ConfigurableAlgorithm.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:836
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:797
python.Configurable.Configurable._isInSetDefaults
def _isInSetDefaults(self)
Definition: Configurable.py:611
python.Configurable.ConfigurableService.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:871
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:868
python.Configurable.ConfigurableAuditor.getHandle
def getHandle(self)
Definition: Configurable.py:967
python.Configurable.ConfigurableService.getHandle
def getHandle(self)
Definition: Configurable.py:858
python.Configurable.ConfigurableAlgorithm._jobOptName
_jobOptName
Definition: Configurable.py:824
python.Configurable.Configurable.setup
def setup(self)
Definition: Configurable.py:459
python.Configurable.ConfigurableUser.getDlls
def getDlls(self)
Definition: Configurable.py:1016
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:885
python.Configurable.ConfigurableAlgTool.hasParent
def hasParent(self, parent)
Definition: Configurable.py:939
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:997
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:829
python.Configurable.ConfigurableService.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:865
python.Configurable.ConfigurableAlgTool.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:895
python.Configurable.ConfigurableAlgorithm.__init__
def __init__(self, name=Configurable.DefaultName)
Definition: Configurable.py:821
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:942
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:815
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:904
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
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:194
python.Configurable.ConfigurableAlgTool.getParent
def getParent(self)
Definition: Configurable.py:924
python.Configurable.Configurable.__getnewargs__
def __getnewargs__(self)
Definition: Configurable.py:274
python.Configurable.Configurable.__ne__
def __ne__(self, rhs)
Definition: Configurable.py:804
python.Configurable.Configurable.getAllChildren
def getAllChildren(self)
Definition: Configurable.py:414
python.Configurable.ConfigurableUser.getGaudiType
def getGaudiType(self)
Definition: Configurable.py:1013
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:945
python.Configurable.ConfigurableUser.__init__
def __init__(self, name=Configurable.DefaultName, **kwargs)
Definition: Configurable.py:1008
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
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:965
python.Configurable.Configurable.copyChildAndSetParent
def copyChildAndSetParent(self, cfg, parent)
Definition: Configurable.py:400
python.Configurable.ConfigurableAlgorithm.getJobOptName
def getJobOptName(self)
Definition: Configurable.py:839
python.Configurable.Configurable.getType
def getType(cls)
Definition: Configurable.py:577
python.Configurable.ConfigurableAlgTool.getGaudiHandle
def getGaudiHandle(self)
Definition: Configurable.py:898
python.Configurable.ConfigurableService.copyChild
def copyChild(self, child)
Definition: Configurable.py:851
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
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:948
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:790
python.Configurable.Configurable.getStrDescriptor
def getStrDescriptor(self)
Definition: Configurable.py:780
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:759
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:809
python.Configurable.ConfigurablePyAlgorithm
Definition: Configurable.py:989
python.Configurable.ConfigurableAlgTool.toStringProperty
def toStringProperty(self)
Definition: Configurable.py:951
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:792
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:931