5 import copy, string, types, os
7 from inspect
import isclass
10 VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL
15 __all__ = [
'Configurable',
16 'ConfigurableAlgorithm',
17 'ConfigurableAlgTool',
18 'ConfigurableAuditor',
19 'ConfigurableService',
21 'VERBOSE',
'DEBUG',
'INFO',
'WARNING',
'ERROR',
'FATAL',
22 'appendPostConfigAction',
'removePostConfigAction' ]
26 log = logging.getLogger(
'Configurable' )
30 Expand environment variables "data".
31 Data can be string, list, tuple and dictionary. For collection, all the
32 contained strings will be manipulated (recursively).
37 return os.path.expandvars(data)
38 elif typ
in [list, tuple]:
50 class Error(RuntimeError):
52 Error occurred in the configuration process.
57 class PropertyReference(object):
58 def __init__(self,propname):
61 return "@%s"%self.name
62 def __resolve__(self):
65 refname, refprop = self.name.rsplit(
'.',1)
66 if refname
in Configurable.allConfigurables:
67 conf = Configurable.allConfigurables[refname]
68 retval = getattr(conf,refprop)
69 if hasattr(retval,
"getFullName"):
70 retval = retval.getFullName()
72 raise NameError(
"name '%s' not found resolving '%s'"%(refname,self))
74 def getFullName(self):
75 """This function allow transparent integration with
76 Configurable.getValuedProperties.
79 return self.__resolve__()
83 except AttributeError:
88 class Configurable( object ):
89 """Base class for Gaudi components that implement the IProperty interface.
90 Provides most of the boilerplate code, but the actual useful classes
91 are its derived ConfigurableAlgorithm, ConfigurableService, and
92 ConfigurableAlgTool."""
98 propertyNoValue =
'<no value>'
103 __metaclass__ = ConfigurableMeta.ConfigurableMeta
114 allConfigurables = {}
115 configurableServices = {}
118 _configurationLocked =
False
120 def __new__ ( cls, *args, **kwargs ):
121 """To Gaudi, any object with the same type/name is the same object. Hence,
122 this is mimicked in the configuration: instantiating a new Configurable
123 of a type with the same name will return the same instance."""
129 name = kwargs[
'name' ]
130 elif 'name' in cls.__init__.func_code.co_varnames:
132 index = list(cls.__init__.func_code.co_varnames).index(
'name' )
135 name = args[ index - 1 ]
138 name = cls.__init__.func_defaults[ index - (len(args)+1) ]
143 except (IndexError,TypeError):
144 raise TypeError(
'no "name" argument while instantiating "%s"' % cls.__name__ )
147 if name == Configurable.DefaultName :
148 if hasattr(cls,
'DefaultedName' ) :
149 name = cls.DefaultedName
152 elif not name
or type(name) != str:
154 raise TypeError(
'could not retrieve name from %s.__init__ arguments' % cls.__name__ )
158 if issubclass( cls, ConfigurableAlgTool)
and '.' not in name :
159 name =
'ToolSvc.' + name
169 if name
in cls.configurables:
170 conf = cls.configurables[ name ]
172 cls.configurables[ conf.getType() ] = conf
174 for n,v
in kwargs.items():
177 if not cls._configurationLocked
and not "_enabled" in kwargs
and isinstance(conf, ConfigurableUser):
180 setattr(conf,
"_enabled",
True)
184 spos = name.find(
'/' )
187 ti_name =
"%s/%s" % (name,name)
188 if ti_name
in cls.configurables:
190 return cls.configurables[ ti_name ]
195 if i_name == name[spos+1:]
and i_name
in cls.configurables:
197 return cls.configurables[ i_name ]
200 conf = cls.allConfigurables.get( name,
None )
or\
201 (spos < 0
and cls.allConfigurables.get( ti_name,
None ))
or\
202 (spos > 0
and i_name == name[spos+1:]
and cls.allConfigurables.get( i_name,
None ))
204 if conf.__class__
is ConfigurableGeneric :
208 newconf = object.__new__( cls )
209 cls.__init__( newconf, *args, **kwargs )
214 for n
in newconf.__slots__:
216 for n
in conf._properties:
217 if names[n.lower()] != n:
218 log.warning(
"Option '%s' was used for %s, but the correct spelling is '%s'"%(n,name,names[n.lower()]) )
219 setattr(newconf, names[n.lower()], getattr( conf, n ) )
220 for n,v
in kwargs.items():
221 setattr(newconf, n, v)
222 cls.configurables[ name ] = newconf
223 cls.allConfigurables[ name ] = newconf
227 log.error(
'attempt to redefine type of "%s" (was: %s, new: %s)%s',
228 name, conf.__class__.__name__, cls.__name__, error_explanation )
233 for n,v
in kwargs.items():
238 conf = object.__new__(cls)
239 cls.__init__( conf, *args, **kwargs )
242 cls.configurables[ name ] = conf
244 for base
in cls.__bases__:
245 if base.__name__ ==
'ConfigurableService':
246 cls.configurableServices[ name ] = conf
249 cls.allConfigurables[ name ] = conf
255 def __init__( self, name = DefaultName ):
257 klass = self.__class__
260 if klass == Configurable:
261 raise TypeError,
"%s is an ABC and can not be instantiated" % str(Configurable)
265 meths = {
'getDlls' : 1,
270 for meth, nArgs
in meths.items():
272 f = getattr( klass, meth ).im_func
273 except AttributeError:
274 raise NotImplementedError,
"%s is missing in class %s" % (meth,str(klass))
277 nargcount = f.func_code.co_argcount
278 ndefaults = f.func_defaults
and len(f.func_defaults)
or 0
279 if not nargcount - ndefaults <= nArgs <= nargcount:
280 raise TypeError,
"%s.%s requires exactly %d arguments" % (klass,meth,nArgs)
287 if name == Configurable.DefaultName :
288 if hasattr(self.__class__,
'DefaultedName' ) :
289 self._name = self.__class__.DefaultedName
291 self._name = self.getType()
296 self._inSetDefaults =
False
302 self._setupok =
False
305 def __getstate__ (self):
307 for name, proxy
in self._properties.items():
309 dict[ name ] = proxy.__get__( self )
310 except AttributeError:
313 dict[
'_Configurable__children' ] = self.__children
314 dict[
'_Configurable__tools' ] = self.__tools
315 dict[
'_name' ] = self._name
318 def __getnewargs__(self) :
321 def __setstate__ ( self, dict ):
323 for n, v
in dict.items():
329 return len( self.__children )
331 def __iter__( self ):
332 return iter( self.__children )
335 def __deepcopy__( self, memo ):
336 newconf = object.__new__( self.__class__ )
337 self.__class__.__init__( newconf, self.getName() )
339 for proxy
in self._properties.values():
341 proxy.__set__( newconf, proxy.__get__( self ) )
342 except AttributeError:
345 for c
in self.__children:
351 def __iadd__( self, configs, descr = None ):
352 if not type(configs)
in (list,tuple):
353 configs = ( configs, )
355 joname = self.getJobOptName()
359 if not isinstance( cfg, Configurable ):
360 raise TypeError(
"'%s' is not a Configurable" % str(cfg) )
362 cc = self.copyChildAndSetParent( cfg, joname )
365 ccjo = cc.getJobOptName()
366 for c
in self.__children:
367 if c.getJobOptName() == ccjo:
368 log.error(
'attempt to add a duplicate ... dupe ignored%s', error_explanation )
371 self.__children.append( cc )
375 descr.__set__( self, cc )
377 setattr( self, cc.getName(), cc )
378 except AttributeError:
383 def __getattr__( self, attr ):
385 if attr
in self.__tools :
return self.__tools[attr]
387 for c
in self.__children:
388 if c.getName() == attr:
391 raise AttributeError(
"'%s' object has no attribute '%s'" % (self.__class__,attr) )
393 def __setattr__( self, name, value ) :
394 if self._configurationLocked:
395 raise RuntimeError(
"%s: Configuration cannot be modified after the ApplicationMgr has been started."%self.name())
397 super( Configurable, self ).__setattr__( name, value )
398 except AttributeError:
399 raise AttributeError(
"Configurable '%s' does not have property '%s'."
400 % ( self.__class__.__name__, name) )
402 def __delattr__( self, attr ):
406 prop = self._properties[ attr ]
407 prop.__delete__( self )
408 prop.__set__( self, prop.default )
413 if attr
in self.__tools :
414 del self.__tools[attr]
417 for c
in self.__children:
418 if c.getName() == attr:
419 self.__children.remove( c )
423 del self.__dict__[ attr ]
424 except (AttributeError,KeyError):
427 def __nonzero__(self):
431 def remove( self, items ):
432 if type(items) != list
and type(items) != tuple:
435 self.__children = [ e
for e
in self.__children
if not e
in items ]
437 def removeAll( self ):
438 self.remove( self.__children )
441 def copyChild( self, child ):
442 return copy.deepcopy( child )
444 def setParent( self, parentName ):
447 def getParent( self ):
450 def hasParent( self, parent ):
453 def copyChildAndSetParent(self,cfg,parent):
454 cc = self.copyChild( cfg )
456 if hasattr( cc,
'setParent' )
and parent:
458 cc.setParent( parent )
459 except RuntimeError, e:
461 log.error( str(e) +
'%s', error_explanation )
462 ccbd = cc.configurables[ cc.getJobOptName() ]
465 for proxy
in self._properties.values():
466 if proxy.history.has_key( cc ):
467 proxy.__set__( ccbd, proxy.__get__( cc ) )
473 def getChildren( self ):
474 return self.__children[:]
476 def getTools( self ):
477 return self.__tools.values()
479 def children( self ):
480 log.error(
"children() is deprecated, use getChildren() instead for consistency" )
481 log.error(
"getChildren() returns a copy; to add a child, use 'parent += child'%s",
483 return self.__children
485 def getAllChildren( self ):
486 """Get all (private) configurable children, both explicit ones (added with +=)
487 and the ones in the private GaudiHandle properties"""
490 for proxy
in self._properties.values():
492 c = proxy.__get__( self )
493 except AttributeError:
496 if isinstance(c,Configurable)
and not c.isPublic():
498 elif isinstance(c,GaudiHandle):
500 conf = c.configurable
501 except AttributeError:
504 if not conf.isPublic():
506 elif isinstance(c,GaudiHandleArray):
510 if isinstance(ci,Configurable):
514 conf = ci.configurable
515 except AttributeError:
521 childs += self.__children
524 def getSequence( self ):
526 for c
in self.__children:
527 elems.append( c.getFullName() )
532 if not hasattr(self,
'_initok')
or not self._initok:
535 "Configurable.__init__ not called in %s override" % self.__class__.__name__
540 self.__setupServices()
542 self.__setupDefaults()
545 for c
in self.getAllChildren():
549 handle = self.getHandle()
551 log.debug(
'no handle for %s: not transporting properties', self._name )
555 for name
in self._properties.keys():
556 if hasattr( self, name ):
557 setattr( handle, name, getattr(self,name) )
562 def getProperties( self ):
564 for name, proxy
in self._properties.items():
566 props[ name ] = proxy.__get__( self )
567 except AttributeError:
568 props[ name ] = Configurable.propertyNoValue
572 def getPropertiesWithDescription( self ):
573 """Get all properties with their description string as { name : (value, desc) }."""
575 for name, proxy
in self._properties.items():
577 props[ name ] = ( proxy.__get__( self ), proxy.__doc__)
578 except AttributeError:
579 props[ name ] = ( Configurable.propertyNoValue, proxy.__doc__)
582 def getValuedProperties( self ):
584 for name, proxy
in self._properties.items():
585 if self.isPropertySet(name):
586 value = proxy.__get__( self )
587 if hasattr(value,
'getFullName') :
588 value = value.getFullName()
589 elif type(value)
in [list, tuple]:
592 if hasattr(i,
'getFullName'):
593 new_value.append(i.getFullName())
596 value =
type(value)(new_value)
597 elif type(value)
is dict:
600 if hasattr(value[i],
'getFullName'):
601 new_value[i] = value[i].getFullName()
603 new_value[i] = value[i]
605 props[ name ] = value
610 return self.getProperties()
613 def getDefaultProperties( cls ):
622 for k,v
in cls._properties.items():
623 if not k
in c.__dict__
and hasattr( v,
'default' ):
624 c.__dict__[ k ] = v.default
629 def getDefaultProperty( cls, name ):
637 if name
in c.__dict__:
638 return c.__dict__[ name ]
642 v = cls._properties[name]
643 if hasattr( v,
'default' ):
650 def getProp(self, name):
651 """Returns the value of the given property.
653 if hasattr(self, name):
654 return getattr(self, name)
656 return self.getDefaultProperties()[name]
658 def setProp(self, name, value):
659 """Set the value of a given property
661 return setattr(self, name, value)
663 def isPropertySet(self, name):
664 """Tell if the property 'name' has been set or not.
666 Because of a problem with list and dictionary properties, in those cases
667 if the value is equal to the default, the property is considered as not
670 if not hasattr(self, name):
674 default = self.getDefaultProperties()[name]
675 if isinstance(default, (list, dict)):
676 value = getattr(self, name)
677 return value != default
689 return self.getName()
691 def getJobOptName( self ):
692 return self.getName()
694 def isPublic( self ):
698 def jobOptName( self ):
699 log.error(
"jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
701 return self.getJobOptName()
703 def getFullName( self ) :
704 return str( self.getType() +
'/' + self.getName() )
706 def getFullJobOptName( self ):
707 return "%s/%s" % (self.getType(),self.getJobOptName()
or self.getName())
709 def getPrintTitle(self):
710 return self.getGaudiType() +
' ' + self.getTitleName()
712 def getTitleName( self ):
713 if log.isEnabledFor( logging.DEBUG ):
714 return self.getFullJobOptName()
716 return self.getFullName()
718 def setDefaults( cls, handle ):
721 def clone( self, name = None, **kwargs ) :
723 if hasattr(self,
'DefaultedName' ) : name = self.DefaultedName
724 else : name = self.getType()
726 newconf = Configurable.__new__( self.__class__, name )
727 self.__class__.__init__( newconf, name )
729 for proxy
in self._properties.values():
731 value = proxy.__get__( self )
732 if type(value)
in [ str, list, dict, tuple ]:
734 value =
type(value)(value)
735 proxy.__set__( newconf, value )
736 except AttributeError:
739 for c
in self.__children:
742 for n , t
in self.__tools.items():
743 newconf.addTool(t, n)
745 for name, value
in kwargs.items():
746 setattr(newconf, name, value)
750 def splitName( self ) :
751 fullname = self.getName()
752 dot = fullname.find(
'.')
754 parentname = fullname[:dot]
755 longname = fullname[dot+1:]
759 dot = longname.find(
'.')
761 name = longname[:dot]
764 return parentname, name, longname
766 def addTool( self, tool, name = None ) :
767 if isclass(tool)
and issubclass(tool, ConfigurableAlgTool):
770 priv_tool = tool( self.getName()+
'.' + name )
771 elif isinstance(tool, ConfigurableAlgTool):
773 name = tool.splitName()[1]
774 priv_tool = tool.clone( self.getName()+
'.' + name )
777 classname = tool.__name__
779 classname =
type(tool).__name__
780 raise TypeError,
"addTool requires AlgTool configurable. Got %s type" % classname
781 self.__tools[name] = priv_tool
782 if name
in self.__slots__:
784 setattr(self,name,self.__tools[name])
786 def _isInSetDefaults( self ):
787 return self._inSetDefaults
789 def __setupServices( self ):
798 handle = __main__.Service( svc )
803 if hasattr( self,
'configure' + svc ):
804 eval(
'self.configure' + svc +
'( handle )' )
806 def __setupDlls( self ):
807 dlls = self.getDlls()
810 elif type(dlls) == types.StringType:
813 from __main__
import theApp
814 dlls = filter(
lambda d: d
not in theApp.Dlls, dlls )
815 if dlls: theApp.Dlls += dlls
817 def __setupDefaults( self ):
820 self._inSetDefaults =
True
821 self.setDefaults( self )
822 self._inSetDefaults =
False
825 def _printHeader( indentStr, title ):
826 preLen = Configurable.printHeaderPre
827 postLen = Configurable.printHeaderWidth - preLen - 3 - len(title)
828 postLen = max(preLen,postLen)
829 return indentStr +
'/%s %s %s' % (preLen*
'*',title,postLen*
'*')
832 def _printFooter( indentStr, title ):
833 preLen = Configurable.printHeaderPre
834 postLen = Configurable.printHeaderWidth - preLen - 12 - len(title)
835 postLen = max(preLen,postLen)
836 return indentStr +
'\\%s (End of %s) %s' % (preLen*
'-',title,postLen*
'-')
838 def __repr__( self ):
839 return '<%s at %s>' % (self.getFullJobOptName(),hex(id(self)))
841 def __str__( self, indent = 0, headerLastIndentUnit=indentUnit ):
843 indentStr = indent*Configurable.indentUnit
845 title = self.getPrintTitle()
848 headerIndent = (indent-1)*Configurable.indentUnit + headerLastIndentUnit
851 rep = Configurable._printHeader( headerIndent, title )
854 props = self.getProperties()
855 defs = self.getDefaultProperties()
857 rep += indentStr +
'|-<no properties>' + os.linesep
861 for p
in props.keys():
862 nameWidth=max(nameWidth,len(p))
863 for p, v
in props.items():
865 prefix = indentStr +
'|-%-*s' % (nameWidth,p)
867 if log.isEnabledFor( logging.DEBUG ):
868 if v != Configurable.propertyNoValue:
869 address =
' @%11s' % hex(id(v))
874 default = defs.get(p)
875 if v == Configurable.propertyNoValue:
877 strVal = repr(default)
881 if hasattr(v,
"getGaudiHandle"):
882 vv = v.getGaudiHandle()
885 if isinstance(vv,GaudiHandle)
or isinstance(vv,GaudiHandleArray):
887 if hasattr(default,
"toStringProperty"):
888 strDef = repr(default.toStringProperty())
890 strDef = repr(default)
891 if strDef == repr(vv.toStringProperty()):
895 strDef = repr(default)
897 line = prefix +
' = ' + strVal
899 if strDef
is not None:
901 if len(line) + len(strDef) > Configurable.printHeaderWidth:
902 line += os.linesep + indentStr +
'| ' + (len(prefix)-len(indentStr)-3)*
' '
903 line +=
' (default: %s)' % (strDef,)
905 rep += line + os.linesep
916 for cfg
in self.getAllChildren():
917 rep += cfg.__str__( indent + 1,
'|=' ) + os.linesep
920 rep += Configurable._printFooter( indentStr, title )
925 Return True is the instance can be "applied".
926 Always False for plain Configurable instances
927 (i.e. not ConfigurableUser).
932 class DummyDescriptor( object ):
933 def __init__( self, name ):
936 def __get__( self, obj, type = None ):
937 return getattr( obj, self.__name__ )
939 def __set__( self, obj, value ):
940 object.__setattr__( obj, self.__name__, value )
942 class ConfigurableGeneric( Configurable ):
945 def __init__( self, name = Configurable.DefaultName ):
946 Configurable.__init__( self, name )
948 self._properties = {}
950 def __deepcopy__( self, memo ):
953 def getGaudiType( self ):
return 'GenericComponent'
954 def getDlls( self ) :
pass
955 def getHandle( self ) :
pass
957 def __setattr__( self, name, value ):
960 super( ConfigurableGeneric, self ).__setattr__( name, value )
964 if isinstance( value, Configurable ):
965 self.__dict__[ name ] = value
969 if not name
in self._properties:
970 self._properties[ name ] = PropertyProxy( DummyDescriptor( name ) )
971 self._properties[ name ].__set__( self, value )
973 def getJobOptName( self ):
return None
977 class ConfigurableAlgorithm( Configurable ):
978 __slots__ = {
'_jobOptName' : 0,
'OutputLevel' : 0, \
979 'Enable' : 1,
'ErrorMax' : 1,
'ErrorCount' : 0,
'AuditAlgorithms' : 0, \
980 'AuditInitialize' : 0,
'AuditReinitialize' : 0,
'AuditExecute' : 0, \
981 'AuditFinalize' : 0,
'AuditBeginRun' : 0,
'AuditEndRun' : 0 }
983 def __init__( self, name = Configurable.DefaultName ):
984 super( ConfigurableAlgorithm, self ).__init__( name )
985 name = self.getName()
986 self._jobOptName = name[ name.find(
'/')+1 : ]
988 def __deepcopy__( self, memo ):
991 def getHandle( self ):
994 def getGaudiType( self ):
997 def getJobOptName( self ):
998 return self._jobOptName
1001 class ConfigurableService( Configurable ):
1002 __slots__ = {
'OutputLevel' : 0, \
1003 'AuditServices' : 0,
'AuditInitialize' : 0,
'AuditFinalize' : 0 }
1005 def __deepcopy__( self, memo ):
1008 def copyChild( self, child ):
1011 def getHandle( self ):
1012 return iService( self._name )
1014 def getGaudiType( self ):
1017 def getGaudiHandle( self ):
1020 def toStringProperty( self ):
1022 return self.getName()
1025 class ConfigurableAlgTool( Configurable ):
1026 __slots__ = {
'_jobOptName' :
'',
'OutputLevel' : 0, \
1027 'AuditTools' : 0,
'AuditInitialize' : 0,
'AuditFinalize' : 0 }
1029 def __init__( self, name = Configurable.DefaultName ):
1030 super( ConfigurableAlgTool, self ).__init__( name )
1031 if '.' not in self._name:
1033 self._name =
"ToolSvc." + self._name
1034 name = self.getName()
1035 name = name[ name.find(
'/')+1 : ]
1036 self._jobOptName = name
1038 def getHandle( self ):
1040 return iProperty( self.getJobOptName() )
1042 def getGaudiType( self ):
1045 def getGaudiHandle( self ):
1047 return PublicToolHandle( self.toStringProperty() )
1049 return PrivateToolHandle( self.toStringProperty() )
1051 def getPrintTitle(self):
1056 return pop + Configurable.getPrintTitle(self)
1058 def setParent( self, parentName ):
1064 for c
in self.getAllChildren():
1065 if isinstance(c,ConfigurableAlgTool): c.setParent( parentName )
1068 name = self.getName()
1069 name = name[name.rfind(
'.')+1:]
1070 self._jobOptName = self._name = parentName +
'.' + name
1072 def getParent( self ):
1073 dot = self._jobOptName.rfind(
'.')
1075 return self._jobOptName[:dot]
1079 def hasParent( self, parent ):
1080 return self._jobOptName.startswith( parent +
'.' )
1082 def getJobOptName( self ):
1083 return self._jobOptName
1085 def isPublic( self ):
1086 return self.isInToolSvc()
1088 def isInToolSvc( self ):
1089 return self._jobOptName.startswith(
'ToolSvc.')
1091 def toStringProperty( self ):
1093 return self.getFullName()
1095 def getFullName( self ) :
1098 name = self.getName()
1100 name = name[name.rfind(
'.')+1:]
1101 return str( self.getType() +
'/' + name )
1107 class ConfigurableAuditor( Configurable ):
1108 __slots__ = {
'_jobOptName' : 0,
'OutputLevel' : 0, \
1111 def __init__( self, name = Configurable.DefaultName ):
1112 super( ConfigurableAuditor, self ).__init__( name )
1113 name = self.getName()
1114 name = name[ name.find(
'/')+1 : ]
1115 self._jobOptName = name
1117 def getHandle( self ):
1119 return iProperty( self.getJobOptName() )
1121 def getGaudiType( self ):
1124 def getJobOptName( self ):
1125 return self._jobOptName
1127 def toStringProperty( self ):
1129 return self.getType() +
'/' + self.getName()
1131 class ConfigurableUser( Configurable ):
1132 __slots__ = {
"__users__": [],
1133 "__used_instances__": [],
1144 __used_configurables__ = []
1147 __queried_configurables__ = []
1148 def __init__( self, name = Configurable.DefaultName, _enabled = True, **kwargs ):
1149 super( ConfigurableUser, self ).__init__( name )
1150 for n, v
in kwargs.items():
1152 self._enabled = _enabled
1154 self._applied =
False
1162 self.__used_instances__ = []
1163 for used
in self.__used_configurables__:
1166 used_name = Configurable.DefaultName
1168 if type(used)
is tuple:
1169 used, used_name = used
1171 used_name = self._instanceName(used)
1173 if type(used)
is str:
1174 used_class = confDbGetConfigurable(used)
1179 inst = used_class(name = used_name, _enabled =
False)
1180 except AttributeError:
1184 inst = used_class(name = used_name)
1185 self.__addActiveUseOf(inst)
1186 for queried
in self.__queried_configurables__:
1188 if type(queried)
is str:
1189 queried = confDbGetConfigurable(queried)
1190 inst = queried(_enabled =
False)
1191 except AttributeError:
1193 self.__addPassiveUseOf(inst)
1194 def __addActiveUseOf(self, other):
1196 Declare that we are going to modify the Configurable 'other' in our
1197 __apply_configuration__.
1199 self.__used_instances__.append(other)
1200 if hasattr(other,
"__users__"):
1201 other.__users__.append(self)
1202 def __addPassiveUseOf(self, other):
1204 Declare that we are going to retrieve property values from the
1205 ConfigurableUser 'other' in our __apply_configuration__.
1207 if not isinstance(other, ConfigurableUser):
1208 raise Error(
"'%s': Cannot make passive use of '%s', it is not a ConfigurableUser" % (self.name(), other.name()))
1209 other.__addActiveUseOf(self)
1210 def getGaudiType( self ):
1212 def getDlls( self ):
1214 def getHandle( self ):
1217 def __detach_used__(self):
1219 Remove this ConfigurableUser instance from the users list of the used
1222 for used
in self.__used_instances__:
1223 if hasattr(used,
"__users__"):
1224 used.__users__.remove(self)
1226 def propagateProperty(self, name, others = None, force = True):
1228 Propagate the property 'name' (if set) to other configurables (if possible).
1231 propagate to all the entries in __used_configurables__
1232 a configurable instance:
1233 propagate only to it
1234 list of configurable instances:
1235 propagate to all of them.
1239 - if the local property is set, the other property will be overwritten
1240 - local property not set and other set => keep other
1241 - local property not set and other not set => overwrite the default for
1242 ConfigurableUser instances and set the property for Configurables
1246 others = self.__used_instances__
1247 elif type(others)
not in [ list, tuple ] :
1250 local_is_set = self.isPropertySet(name)
1251 value = self.getProp(name)
1253 for other
in [ o
for o
in others
if name
in o.__slots__ ]:
1256 if other.isPropertySet(name):
1257 log.warning(
"Property '%(prop)s' is set in both '%(self)s' and '%(other)s', using '%(self)s.%(prop)s'"%
1258 {
"self": self.name(),
1259 "other": other.name(),
1261 other.setProp(name, value)
1263 elif not other.isPropertySet(name):
1264 if isinstance(other,ConfigurableUser):
1265 otherType =
type(other._properties[name].getDefault())
1266 other._properties[name].setDefault(value)
1267 if otherType
in [list, dict]:
1270 other.setProp(name, otherType(value))
1272 other.setProp(name, value)
1275 def propagateProperties(self, names = None, others = None, force = True):
1277 Call propagateProperty for each property listed in 'names'.
1278 If 'names' is None, all the properties are propagated.
1282 names = [ p
for p
in self.__slots__
if not p.startswith(
"_") ]
1284 self.propagateProperty(n, others, force)
1286 def __apply_configuration__(self):
1288 Function to be overridden to convert the high level configuration into a
1290 The default implementation calls applyConf, which is the method defined
1291 in some ConfigurableUser implementations.
1293 return self.applyConf()
1295 def applyConf( self ):
1297 Function to be overridden to convert the high level configuration into a
1302 def _instanceName(self, cls):
1304 Function used to define the name of the private instance of a given class
1306 This method is used when the __used_configurables_property__ declares the
1307 need of a private used configurable without specifying the name.
1309 if type(cls)
is str:
1312 clName = cls.__name__
1313 return "%s_%s" % (self.name(), clName)
1315 def getUsedInstance(self, name):
1317 Return the used instance with a given name.
1319 for i
in self.__used_instances__:
1320 if i.name() == name:
1321 if hasattr(i,
"_enabled"):
1326 raise KeyError(name)
1330 Return True is the instance can be "applied".
1332 return (
not self.__users__)
and (
not self._applied)
1336 postConfigActions = []
1339 Add a new callable ('function') to the list of post-configuration actions.
1340 If the callable is already in the list, it is moved to the end of the list.
1341 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1344 postConfigActions.remove(function)
1347 postConfigActions.append(function)
1350 Remove a callable from the list of post-config actions.
1351 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1353 postConfigActions.remove(function)
1355 _appliedConfigurableUsers_ =
False
1358 Call the apply method of all the ConfigurableUser instances respecting the
1359 dependencies. First the C.U.s that are not used by anybody, then the used
1360 ones, when they are not used anymore.
1363 global _appliedConfigurableUsers_, postConfigActions
1364 if _appliedConfigurableUsers_:
1366 _appliedConfigurableUsers_ =
True
1368 def applicableConfUsers():
1370 Generator returning all the configurables that can be applied in the
1371 order in which they can be applied.
1383 yield (c
for c
in Configurable.allConfigurables.values()
1384 if c.isApplicable()).next()
1386 debugApplyOrder =
'GAUDI_DUBUG_CONF_USER' in os.environ
1387 for c
in applicableConfUsers():
1389 log.info(
"applying configuration of %s", c.name())
1391 sys.stderr.write(
'applying %r' % c)
1392 c.__apply_configuration__()
1395 log.info(
"skipping configuration of %s", c.name())
1397 if hasattr(c,
"__detach_used__"):
1402 leftConfUsers = [c
for c
in Configurable.allConfigurables.values()
1403 if hasattr(c,
'__apply_configuration__')
and
1404 c._enabled
and not c._applied]
1407 raise Error(
"Detected loop in the ConfigurableUser"
1408 " dependencies: %r" % [ c.name()
1409 for c
in leftConfUsers ])
1412 unknown = set(Configurable.allConfigurables)
1416 log.debug(
'new configurable created automatically: %s', k)
1418 Configurable.allConfigurables[k].
properties()
1422 for action
in postConfigActions:
1427 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1428 backward compatibility for configurations that where relying (implicitly) on
1429 bug #103803, or on a specific (non guaranteed) order of execution.
1431 @see applyConfigurableUsers()
1434 global _appliedConfigurableUsers_, postConfigActions
1435 if _appliedConfigurableUsers_:
1437 _appliedConfigurableUsers_ =
True
1439 debugApplyOrder =
'GAUDI_DUBUG_CONF_USER' in os.environ
1441 for c
in Configurable.allConfigurables.values()
1442 if hasattr(c,
"__apply_configuration__") ]
1444 while applied
and confUsers:
1448 if hasattr(c,
"__users__")
and c.__users__:
1449 newConfUsers.append(c)
1454 enabled = (
not hasattr(c,
"_enabled"))
or c._enabled
1456 log.info(
"applying configuration of %s", c.name())
1458 sys.stderr.write(
'applying %r' % c)
1459 c.__apply_configuration__()
1462 log.info(
"skipping configuration of %s", c.name())
1463 if hasattr(c,
"__detach_used__"):
1466 confUsers = newConfUsers
1469 raise Error(
"Detected loop in the ConfigurableUser "
1470 " dependencies: %r" % [ c.name()
1471 for c
in confUsers ])
1474 unknown = set(Configurable.allConfigurables)
1478 log.debug(
'new configurable created automatically: %s', k)
1480 Configurable.allConfigurables[k].
properties()
1484 for action
in postConfigActions:
1489 Function to select all and only the configurables that have to be used in
1490 GaudiPython.AppMgr constructor.
1491 This is needed because in Athena the implementation have to be different (the
1492 configuration is used in a different moment).
1495 for k, v
in Configurable.allConfigurables.items()
1496 if v.getGaudiType() !=
"User" ]
1500 Clean up all configurations and configurables.
1502 for c
in Configurable.allConfigurables.values():
1503 c.__class__.configurables.clear()
1504 Configurable.allConfigurables.clear()
1507 ConfigurableGeneric.configurables.clear()
1508 from ProcessJobOptions
import _included_files
1510 for file
in _included_files:
1511 dirname, basname = os.path.split(file)
1512 basname, ext = os.path.splitext(basname)
1513 if basname
in sys.modules:
1514 del sys.modules[basname]
1515 _included_files.clear()
Handle to be used in lieu of naked pointers to services.
def applyConfigurableUsers()
def appendPostConfigAction(function)
def isApplicable(self)
if isinstance(v,Configurable) and not v.isPublic(): rep += v.__str__( indent + 1 ) + os...
def applyConfigurableUsers_old()
iAlgorithm
The basic module.
def removePostConfigAction(function)
def getNeededConfigurables()