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 getValuedProperties( self ):
574 for name, proxy
in self._properties.items():
575 if self.isPropertySet(name):
576 value = proxy.__get__( self )
577 if hasattr(value,
'getFullName') :
578 value = value.getFullName()
579 elif type(value)
in [list, tuple]:
582 if hasattr(i,
'getFullName'):
583 new_value.append(i.getFullName())
586 value =
type(value)(new_value)
587 elif type(value)
is dict:
590 if hasattr(value[i],
'getFullName'):
591 new_value[i] = value[i].getFullName()
593 new_value[i] = value[i]
595 props[ name ] = value
599 def properties( self ):
600 return self.getProperties()
603 def getDefaultProperties( cls ):
612 for k,v
in cls._properties.items():
613 if not k
in c.__dict__
and hasattr( v,
'default' ):
614 c.__dict__[ k ] = v.default
619 def getDefaultProperty( cls, name ):
627 if name
in c.__dict__:
628 return c.__dict__[ name ]
632 v = cls._properties[name]
633 if hasattr( v,
'default' ):
640 def getProp(self, name):
641 """Returns the value of the given property.
643 if hasattr(self, name):
644 return getattr(self, name)
646 return self.getDefaultProperties()[name]
648 def setProp(self, name, value):
649 """Set the value of a given property
651 return setattr(self, name, value)
653 def isPropertySet(self, name):
654 """Tell if the property 'name' has been set or not.
656 Because of a problem with list and dictionary properties, in those cases
657 if the value is equal to the default, the property is considered as not
660 if not hasattr(self, name):
664 default = self.getDefaultProperties()[name]
665 if isinstance(default, (list, dict)):
666 value = getattr(self, name)
667 return value != default
679 return self.getName()
681 def getJobOptName( self ):
682 return self.getName()
684 def isPublic( self ):
688 def jobOptName( self ):
689 log.error(
"jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
691 return self.getJobOptName()
693 def getFullName( self ) :
694 return str( self.getType() +
'/' + self.getName() )
696 def getFullJobOptName( self ):
697 return "%s/%s" % (self.getType(),self.getJobOptName()
or self.getName())
699 def getPrintTitle(self):
700 return self.getGaudiType() +
' ' + self.getTitleName()
702 def getTitleName( self ):
703 if log.isEnabledFor( logging.DEBUG ):
704 return self.getFullJobOptName()
706 return self.getFullName()
708 def setDefaults( cls, handle ):
711 def clone( self, name = None, **kwargs ) :
713 if hasattr(self,
'DefaultedName' ) : name = self.DefaultedName
714 else : name = self.getType()
716 newconf = Configurable.__new__( self.__class__, name )
717 self.__class__.__init__( newconf, name )
719 for proxy
in self._properties.values():
721 value = proxy.__get__( self )
722 if type(value)
in [ str, list, dict, tuple ]:
724 value =
type(value)(value)
725 proxy.__set__( newconf, value )
726 except AttributeError:
729 for c
in self.__children:
732 for n , t
in self.__tools.items():
733 newconf.addTool(t, n)
735 for name, value
in kwargs.items():
736 setattr(newconf, name, value)
740 def splitName( self ) :
741 fullname = self.getName()
742 dot = fullname.find(
'.')
744 parentname = fullname[:dot]
745 longname = fullname[dot+1:]
749 dot = longname.find(
'.')
751 name = longname[:dot]
754 return parentname, name, longname
756 def addTool( self, tool, name = None ) :
757 if isclass(tool)
and issubclass(tool, ConfigurableAlgTool):
760 priv_tool = tool( self.getName()+
'.' + name )
761 elif isinstance(tool, ConfigurableAlgTool):
763 name = tool.splitName()[1]
764 priv_tool = tool.clone( self.getName()+
'.' + name )
767 classname = tool.__name__
769 classname =
type(tool).__name__
770 raise TypeError,
"addTool requires AlgTool configurable. Got %s type" % classname
771 self.__tools[name] = priv_tool
772 if name
in self.__slots__:
774 setattr(self,name,self.__tools[name])
776 def _isInSetDefaults( self ):
777 return self._inSetDefaults
779 def __setupServices( self ):
788 handle = __main__.Service( svc )
793 if hasattr( self,
'configure' + svc ):
794 eval(
'self.configure' + svc +
'( handle )' )
796 def __setupDlls( self ):
797 dlls = self.getDlls()
800 elif type(dlls) == types.StringType:
803 from __main__
import theApp
804 dlls = filter(
lambda d: d
not in theApp.Dlls, dlls )
805 if dlls: theApp.Dlls += dlls
807 def __setupDefaults( self ):
810 self._inSetDefaults =
True
811 self.setDefaults( self )
812 self._inSetDefaults =
False
815 def _printHeader( indentStr, title ):
816 preLen = Configurable.printHeaderPre
817 postLen = Configurable.printHeaderWidth - preLen - 3 - len(title)
818 postLen = max(preLen,postLen)
819 return indentStr +
'/%s %s %s' % (preLen*
'*',title,postLen*
'*')
822 def _printFooter( indentStr, title ):
823 preLen = Configurable.printHeaderPre
824 postLen = Configurable.printHeaderWidth - preLen - 12 - len(title)
825 postLen = max(preLen,postLen)
826 return indentStr +
'\\%s (End of %s) %s' % (preLen*
'-',title,postLen*
'-')
828 def __repr__( self ):
829 return '<%s at %s>' % (self.getFullJobOptName(),hex(id(self)))
831 def __str__( self, indent = 0, headerLastIndentUnit=indentUnit ):
833 indentStr = indent*Configurable.indentUnit
835 title = self.getPrintTitle()
838 headerIndent = (indent-1)*Configurable.indentUnit + headerLastIndentUnit
841 rep = Configurable._printHeader( headerIndent, title )
844 props = self.getProperties()
845 defs = self.getDefaultProperties()
847 rep += indentStr +
'|-<no properties>' + os.linesep
851 for p
in props.keys():
852 nameWidth=max(nameWidth,len(p))
853 for p, v
in props.items():
855 prefix = indentStr +
'|-%-*s' % (nameWidth,p)
857 if log.isEnabledFor( logging.DEBUG ):
858 if v != Configurable.propertyNoValue:
859 address =
' @%11s' % hex(id(v))
864 default = defs.get(p)
865 if v == Configurable.propertyNoValue:
867 strVal = repr(default)
871 if hasattr(v,
"getGaudiHandle"):
872 vv = v.getGaudiHandle()
875 if isinstance(vv,GaudiHandle)
or isinstance(vv,GaudiHandleArray):
877 if hasattr(default,
"toStringProperty"):
878 strDef = repr(default.toStringProperty())
880 strDef = repr(default)
881 if strDef == repr(vv.toStringProperty()):
885 strDef = repr(default)
887 line = prefix +
' = ' + strVal
889 if strDef
is not None:
891 if len(line) + len(strDef) > Configurable.printHeaderWidth:
892 line += os.linesep + indentStr +
'| ' + (len(prefix)-len(indentStr)-3)*
' '
893 line +=
' (default: %s)' % (strDef,)
895 rep += line + os.linesep
906 for cfg
in self.getAllChildren():
907 rep += cfg.__str__( indent + 1,
'|=' ) + os.linesep
910 rep += Configurable._printFooter( indentStr, title )
915 Return True is the instance can be "applied".
916 Always False for plain Configurable instances
917 (i.e. not ConfigurableUser).
922 class DummyDescriptor( object ):
923 def __init__( self, name ):
926 def __get__( self, obj, type = None ):
927 return getattr( obj, self.__name__ )
929 def __set__( self, obj, value ):
930 object.__setattr__( obj, self.__name__, value )
932 class ConfigurableGeneric( Configurable ):
935 def __init__( self, name = Configurable.DefaultName ):
936 Configurable.__init__( self, name )
938 self._properties = {}
940 def __deepcopy__( self, memo ):
943 def getGaudiType( self ):
return 'GenericComponent'
944 def getDlls( self ) :
pass
945 def getHandle( self ) :
pass
947 def __setattr__( self, name, value ):
950 super( ConfigurableGeneric, self ).__setattr__( name, value )
954 if isinstance( value, Configurable ):
955 self.__dict__[ name ] = value
959 if not name
in self._properties:
960 self._properties[ name ] = PropertyProxy( DummyDescriptor( name ) )
961 self._properties[ name ].__set__( self, value )
963 def getJobOptName( self ):
return None
967 class ConfigurableAlgorithm( Configurable ):
968 __slots__ = {
'_jobOptName' : 0,
'OutputLevel' : 0, \
969 'Enable' : 1,
'ErrorMax' : 1,
'ErrorCount' : 0,
'AuditAlgorithms' : 0, \
970 'AuditInitialize' : 0,
'AuditReinitialize' : 0,
'AuditExecute' : 0, \
971 'AuditFinalize' : 0,
'AuditBeginRun' : 0,
'AuditEndRun' : 0 }
973 def __init__( self, name = Configurable.DefaultName ):
974 super( ConfigurableAlgorithm, self ).__init__( name )
975 name = self.getName()
976 self._jobOptName = name[ name.find(
'/')+1 : ]
978 def __deepcopy__( self, memo ):
981 def getHandle( self ):
984 def getGaudiType( self ):
987 def getJobOptName( self ):
988 return self._jobOptName
991 class ConfigurableService( Configurable ):
992 __slots__ = {
'OutputLevel' : 0, \
993 'AuditServices' : 0,
'AuditInitialize' : 0,
'AuditFinalize' : 0 }
995 def __deepcopy__( self, memo ):
998 def copyChild( self, child ):
1001 def getHandle( self ):
1002 return iService( self._name )
1004 def getGaudiType( self ):
1007 def getGaudiHandle( self ):
1010 def toStringProperty( self ):
1012 return self.getName()
1015 class ConfigurableAlgTool( Configurable ):
1016 __slots__ = {
'_jobOptName' :
'',
'OutputLevel' : 0, \
1017 'AuditTools' : 0,
'AuditInitialize' : 0,
'AuditFinalize' : 0 }
1019 def __init__( self, name = Configurable.DefaultName ):
1020 super( ConfigurableAlgTool, self ).__init__( name )
1021 if '.' not in self._name:
1023 self._name =
"ToolSvc." + self._name
1024 name = self.getName()
1025 name = name[ name.find(
'/')+1 : ]
1026 self._jobOptName = name
1028 def getHandle( self ):
1030 return iProperty( self.getJobOptName() )
1032 def getGaudiType( self ):
1035 def getGaudiHandle( self ):
1037 return PublicToolHandle( self.toStringProperty() )
1039 return PrivateToolHandle( self.toStringProperty() )
1041 def getPrintTitle(self):
1046 return pop + Configurable.getPrintTitle(self)
1048 def setParent( self, parentName ):
1054 for c
in self.getAllChildren():
1055 if isinstance(c,ConfigurableAlgTool): c.setParent( parentName )
1058 name = self.getName()
1059 name = name[name.rfind(
'.')+1:]
1060 self._jobOptName = self._name = parentName +
'.' + name
1062 def getParent( self ):
1063 dot = self._jobOptName.rfind(
'.')
1065 return self._jobOptName[:dot]
1069 def hasParent( self, parent ):
1070 return self._jobOptName.startswith( parent +
'.' )
1072 def getJobOptName( self ):
1073 return self._jobOptName
1075 def isPublic( self ):
1076 return self.isInToolSvc()
1078 def isInToolSvc( self ):
1079 return self._jobOptName.startswith(
'ToolSvc.')
1081 def toStringProperty( self ):
1083 return self.getFullName()
1085 def getFullName( self ) :
1088 name = self.getName()
1090 name = name[name.rfind(
'.')+1:]
1091 return str( self.getType() +
'/' + name )
1097 class ConfigurableAuditor( Configurable ):
1098 __slots__ = {
'_jobOptName' : 0,
'OutputLevel' : 0, \
1101 def __init__( self, name = Configurable.DefaultName ):
1102 super( ConfigurableAuditor, self ).__init__( name )
1103 name = self.getName()
1104 name = name[ name.find(
'/')+1 : ]
1105 self._jobOptName = name
1107 def getHandle( self ):
1109 return iProperty( self.getJobOptName() )
1111 def getGaudiType( self ):
1114 def getJobOptName( self ):
1115 return self._jobOptName
1117 def toStringProperty( self ):
1119 return self.getType() +
'/' + self.getName()
1121 class ConfigurableUser( Configurable ):
1122 __slots__ = {
"__users__": [],
1123 "__used_instances__": [],
1134 __used_configurables__ = []
1137 __queried_configurables__ = []
1138 def __init__( self, name = Configurable.DefaultName, _enabled = True, **kwargs ):
1139 super( ConfigurableUser, self ).__init__( name )
1140 for n, v
in kwargs.items():
1142 self._enabled = _enabled
1144 self._applied =
False
1152 self.__used_instances__ = []
1153 for used
in self.__used_configurables__:
1156 used_name = Configurable.DefaultName
1158 if type(used)
is tuple:
1159 used, used_name = used
1161 used_name = self._instanceName(used)
1163 if type(used)
is str:
1164 used_class = confDbGetConfigurable(used)
1169 inst = used_class(name = used_name, _enabled =
False)
1170 except AttributeError:
1174 inst = used_class(name = used_name)
1175 self.__addActiveUseOf(inst)
1176 for queried
in self.__queried_configurables__:
1178 if type(queried)
is str:
1179 queried = confDbGetConfigurable(queried)
1180 inst = queried(_enabled =
False)
1181 except AttributeError:
1183 self.__addPassiveUseOf(inst)
1184 def __addActiveUseOf(self, other):
1186 Declare that we are going to modify the Configurable 'other' in our
1187 __apply_configuration__.
1189 self.__used_instances__.append(other)
1190 if hasattr(other,
"__users__"):
1191 other.__users__.append(self)
1192 def __addPassiveUseOf(self, other):
1194 Declare that we are going to retrieve property values from the
1195 ConfigurableUser 'other' in our __apply_configuration__.
1197 if not isinstance(other, ConfigurableUser):
1198 raise Error(
"'%s': Cannot make passive use of '%s', it is not a ConfigurableUser" % (self.name(), other.name()))
1199 other.__addActiveUseOf(self)
1200 def getGaudiType( self ):
1202 def getDlls( self ):
1204 def getHandle( self ):
1207 def __detach_used__(self):
1209 Remove this ConfigurableUser instance from the users list of the used
1212 for used
in self.__used_instances__:
1213 if hasattr(used,
"__users__"):
1214 used.__users__.remove(self)
1216 def propagateProperty(self, name, others = None, force = True):
1218 Propagate the property 'name' (if set) to other configurables (if possible).
1221 propagate to all the entries in __used_configurables__
1222 a configurable instance:
1223 propagate only to it
1224 list of configurable instances:
1225 propagate to all of them.
1229 - if the local property is set, the other property will be overwritten
1230 - local property not set and other set => keep other
1231 - local property not set and other not set => overwrite the default for
1232 ConfigurableUser instances and set the property for Configurables
1236 others = self.__used_instances__
1237 elif type(others)
not in [ list, tuple ] :
1240 local_is_set = self.isPropertySet(name)
1241 value = self.getProp(name)
1243 for other
in [ o
for o
in others
if name
in o.__slots__ ]:
1246 if other.isPropertySet(name):
1247 log.warning(
"Property '%(prop)s' is set in both '%(self)s' and '%(other)s', using '%(self)s.%(prop)s'"%
1248 {
"self": self.name(),
1249 "other": other.name(),
1251 other.setProp(name, value)
1253 elif not other.isPropertySet(name):
1254 if isinstance(other,ConfigurableUser):
1255 otherType =
type(other._properties[name].getDefault())
1256 other._properties[name].setDefault(value)
1257 if otherType
in [list, dict]:
1260 other.setProp(name, otherType(value))
1262 other.setProp(name, value)
1265 def propagateProperties(self, names = None, others = None, force = True):
1267 Call propagateProperty for each property listed in 'names'.
1268 If 'names' is None, all the properties are propagated.
1272 names = [ p
for p
in self.__slots__
if not p.startswith(
"_") ]
1274 self.propagateProperty(n, others, force)
1276 def __apply_configuration__(self):
1278 Function to be overridden to convert the high level configuration into a
1280 The default implementation calls applyConf, which is the method defined
1281 in some ConfigurableUser implementations.
1283 return self.applyConf()
1285 def applyConf( self ):
1287 Function to be overridden to convert the high level configuration into a
1292 def _instanceName(self, cls):
1294 Function used to define the name of the private instance of a given class
1296 This method is used when the __used_configurables_property__ declares the
1297 need of a private used configurable without specifying the name.
1299 if type(cls)
is str:
1302 clName = cls.__name__
1303 return "%s_%s" % (self.name(), clName)
1305 def getUsedInstance(self, name):
1307 Return the used instance with a given name.
1309 for i
in self.__used_instances__:
1310 if i.name() == name:
1311 if hasattr(i,
"_enabled"):
1316 raise KeyError(name)
1320 Return True is the instance can be "applied".
1322 return (
not self.__users__)
and (
not self._applied)
1326 postConfigActions = []
1329 Add a new callable ('function') to the list of post-configuration actions.
1330 If the callable is already in the list, it is moved to the end of the list.
1331 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1334 postConfigActions.remove(function)
1337 postConfigActions.append(function)
1340 Remove a callable from the list of post-config actions.
1341 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1343 postConfigActions.remove(function)
1345 _appliedConfigurableUsers_ =
False
1348 Call the apply method of all the ConfigurableUser instances respecting the
1349 dependencies. First the C.U.s that are not used by anybody, then the used
1350 ones, when they are not used anymore.
1353 global _appliedConfigurableUsers_, postConfigActions
1354 if _appliedConfigurableUsers_:
1356 _appliedConfigurableUsers_ =
True
1358 def applicableConfUsers():
1360 Generator returning all the configurables that can be applied in the
1361 order in which they can be applied.
1373 yield (c
for c
in Configurable.allConfigurables.values()
1374 if c.isApplicable()).next()
1376 debugApplyOrder =
'GAUDI_DUBUG_CONF_USER' in os.environ
1377 for c
in applicableConfUsers():
1379 log.info(
"applying configuration of %s", c.name())
1381 sys.stderr.write(
'applying %r' % c)
1382 c.__apply_configuration__()
1385 log.info(
"skipping configuration of %s", c.name())
1387 if hasattr(c,
"__detach_used__"):
1392 leftConfUsers = [c
for c
in Configurable.allConfigurables.values()
1393 if hasattr(c,
'__apply_configuration__')
and
1394 c._enabled
and not c._applied]
1397 raise Error(
"Detected loop in the ConfigurableUser"
1398 " dependencies: %r" % [ c.name()
1399 for c
in leftConfUsers ])
1402 unknown = set(Configurable.allConfigurables)
1406 log.debug(
'new configurable created automatically: %s', k)
1408 Configurable.allConfigurables[k].properties()
1412 for action
in postConfigActions:
1417 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1418 backward compatibility for configurations that where relying (implicitly) on
1419 bug #103803, or on a specific (non guaranteed) order of execution.
1421 @see applyConfigurableUsers()
1424 global _appliedConfigurableUsers_, postConfigActions
1425 if _appliedConfigurableUsers_:
1427 _appliedConfigurableUsers_ =
True
1429 debugApplyOrder =
'GAUDI_DUBUG_CONF_USER' in os.environ
1431 for c
in Configurable.allConfigurables.values()
1432 if hasattr(c,
"__apply_configuration__") ]
1434 while applied
and confUsers:
1438 if hasattr(c,
"__users__")
and c.__users__:
1439 newConfUsers.append(c)
1444 enabled = (
not hasattr(c,
"_enabled"))
or c._enabled
1446 log.info(
"applying configuration of %s", c.name())
1448 sys.stderr.write(
'applying %r' % c)
1449 c.__apply_configuration__()
1452 log.info(
"skipping configuration of %s", c.name())
1453 if hasattr(c,
"__detach_used__"):
1456 confUsers = newConfUsers
1459 raise Error(
"Detected loop in the ConfigurableUser "
1460 " dependencies: %r" % [ c.name()
1461 for c
in confUsers ])
1464 unknown = set(Configurable.allConfigurables)
1468 log.debug(
'new configurable created automatically: %s', k)
1470 Configurable.allConfigurables[k].properties()
1474 for action
in postConfigActions:
1479 Function to select all and only the configurables that have to be used in
1480 GaudiPython.AppMgr constructor.
1481 This is needed because in Athena the implementation have to be different (the
1482 configuration is used in a different moment).
1485 for k, v
in Configurable.allConfigurables.items()
1486 if v.getGaudiType() !=
"User" ]
1490 Clean up all configurations and configurables.
1492 for c
in Configurable.allConfigurables.values():
1493 c.__class__.configurables.clear()
1494 Configurable.allConfigurables.clear()
1497 ConfigurableGeneric.configurables.clear()
1498 from ProcessJobOptions
import _included_files
1500 for file
in _included_files:
1501 dirname, basname = os.path.split(file)
1502 basname, ext = os.path.splitext(basname)
1503 if basname
in sys.modules:
1504 del sys.modules[basname]
1505 _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()