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]:
52 Error occurred in the configuration process.
57 class PropertyReference(object):
61 return "@%s"%self.
name
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))
75 """This function allow transparent integration with
76 Configurable.getValuedProperties.
83 except AttributeError:
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>'
114 allConfigurables = {}
115 configurableServices = {}
118 _configurationLocked =
False
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__ )
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
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)
288 if hasattr(self.__class__,
'DefaultedName' ) :
289 self.
_name = self.__class__.DefaultedName
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
323 for n, v
in dict.items():
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:
352 if not type(configs)
in (list,tuple):
353 configs = ( configs, )
359 if not isinstance( cfg, Configurable ):
360 raise TypeError(
"'%s' is not a Configurable" % str(cfg) )
365 ccjo = cc.getJobOptName()
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:
388 if c.getName() == attr:
391 raise AttributeError(
"'%s' object has no attribute '%s'" % (self.__class__,attr) )
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) )
406 prop = self._properties[ attr ]
407 prop.__delete__( self )
408 prop.__set__( self, prop.default )
418 if c.getName() == attr:
419 self.__children.remove( c )
423 del self.__dict__[ attr ]
424 except (AttributeError,KeyError):
432 if type(items) != list
and type(items) != tuple:
442 return copy.deepcopy( child )
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 ) )
477 return self.__tools.values()
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",
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:
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__
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) )
564 for name, proxy
in self._properties.items():
566 props[ name ] = proxy.__get__( self )
567 except AttributeError:
568 props[ name ] = Configurable.propertyNoValue
574 for name, proxy
in self._properties.items():
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'):
593 new_value[i] = value[i]
595 props[ name ] = value
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
627 if name
in c.__dict__:
628 return c.__dict__[ name ]
632 v = cls._properties[name]
633 if hasattr( v,
'default' ):
641 """Returns the value of the given property.
643 if hasattr(self, name):
644 return getattr(self, name)
649 """Set the value of a given property
651 return setattr(self, name, value)
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):
665 if isinstance(default, (list, dict)):
666 value = getattr(self, name)
667 return value != default
689 log.error(
"jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
703 if log.isEnabledFor( logging.DEBUG ):
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)
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
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
774 setattr(self,name,self.
__tools[name])
788 handle = __main__.Service( svc )
793 if hasattr( self,
'configure' + svc ):
794 eval(
'self.configure' + svc +
'( handle )' )
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
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*
'*')
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*
'-')
831 def __str__( self, indent = 0, headerLastIndentUnit=indentUnit ):
833 indentStr = indent*Configurable.indentUnit
838 headerIndent = (indent-1)*Configurable.indentUnit + headerLastIndentUnit
841 rep = Configurable._printHeader( headerIndent, title )
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
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).
927 return getattr( obj, self.
__name__ )
930 object.__setattr__( obj, self.
__name__, value )
935 def __init__( self, name = Configurable.DefaultName ):
936 Configurable.__init__( self, name )
944 def getDlls( self ) :
pass
950 super( ConfigurableGeneric, self ).
__setattr__( name, value )
954 if isinstance( value, Configurable ):
955 self.__dict__[ name ] = value
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 )
992 __slots__ = {
'OutputLevel' : 0, \
993 'AuditServices' : 0,
'AuditInitialize' : 0,
'AuditFinalize' : 0 }
1002 return iService( self.
_name )
1016 __slots__ = {
'_jobOptName' :
'',
'OutputLevel' : 0, \
1017 'AuditTools' : 0,
'AuditInitialize' : 0,
'AuditFinalize' : 0 }
1020 super( ConfigurableAlgTool, self ).
__init__( name )
1021 if '.' not in self.
_name:
1025 name = name[ name.find(
'/')+1 : ]
1046 return pop + Configurable.getPrintTitle(self)
1055 if isinstance(c,ConfigurableAlgTool): c.setParent( parentName )
1059 name = name[name.rfind(
'.')+1:]
1063 dot = self._jobOptName.rfind(
'.')
1070 return self._jobOptName.startswith( parent +
'.' )
1079 return self._jobOptName.startswith(
'ToolSvc.')
1090 name = name[name.rfind(
'.')+1:]
1091 return str( self.
getType() +
'/' + name )
1098 __slots__ = {
'_jobOptName' : 0,
'OutputLevel' : 0, \
1102 super( ConfigurableAuditor, self ).
__init__( name )
1104 name = name[ name.find(
'/')+1 : ]
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():
1158 if type(used)
is tuple:
1159 used, used_name = 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)
1178 if type(queried)
is str:
1179 queried = confDbGetConfigurable(used)
1180 inst = queried(_enabled =
False)
1181 except AttributeError:
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)
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)
1209 Remove this ConfigurableUser instance from the users list of the used
1213 if hasattr(used,
"__users__"):
1214 used.__users__.remove(self)
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
1237 elif type(others)
not in [ list, tuple ] :
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)
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(
"_") ]
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.
1287 Function to be overridden to convert the high level configuration into a
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)
1307 Return the used instance with a given name.
1310 if i.name() == name:
1311 if hasattr(i,
"_enabled"):
1316 raise KeyError(name)
1320 Return True is the instance can be "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()
def copyChildAndSetParent
list __queried_configurables__
list of ConfigurableUser classes this one is going to query in the apply_configuration method ...
list __used_configurables__
list of ConfigurableUser classes this one is going to modify in the apply_configuration method...
def applyConfigurableUsers
def __apply_configuration__
def appendPostConfigAction
def getNeededConfigurables
iAlgorithm
The basic module.
def isApplicable
if isinstance(v,Configurable) and not v.isPublic(): rep += v.__str__( indent + 1 ) + os...
classes for generic Gaudi component ===========
def applyConfigurableUsers_old
def removePostConfigAction
for detecting the default name