19from inspect
import isclass
21from GaudiConfig.ControlFlow
import (
56 "ConfigurableAlgorithm",
57 "ConfigurableAlgTool",
58 "ConfigurableAuditor",
59 "ConfigurableService",
67 "appendPostConfigAction",
68 "removePostConfigAction",
79log = logging.getLogger(
"Configurable")
84 Expand environment variables "data".
85 Data can be string, list, tuple and dictionary. For collection, all the
86 contained strings will be manipulated (recursively).
92 return os.path.expandvars(data)
93 elif typ
in [list, tuple]:
108 Error occurred in the configuration process.
117class PropertyReference:
122 return f
"@{self.name}"
127 refname, refprop = self.
name.rsplit(
".", 1)
128 if refname
in Configurable.allConfigurables:
129 conf = Configurable.allConfigurables[refname]
130 retval = getattr(conf, refprop)
131 if hasattr(retval,
"getFullName"):
132 retval = retval.getFullName()
134 raise NameError(f
"name '{refname}' not found resolving '{self}'")
138 """This function allow transparent integration with
139 Configurable.getValuedProperties.
146 except AttributeError:
155 """Base class for Gaudi components that implement the IProperty interface.
156 Provides most of the boilerplate code, but the actual useful classes
157 are its derived ConfigurableAlgorithm, ConfigurableService, and
158 ConfigurableAlgTool."""
164 propertyNoValue =
"<no value>"
166 printHeaderWidth = 100
179 allConfigurables = {}
180 configurableServices = {}
183 _configurationLocked =
False
186 """To Gaudi, any object with the same type/name is the same object. Hence,
187 this is mimicked in the configuration: instantiating a new Configurable
188 of a type with the same name will return the same instance."""
192 func_defaults = cls.
__init__.__defaults__
196 name = kwargs[
"name"]
197 elif "name" in func_code.co_varnames:
199 index = list(func_code.co_varnames).index(
"name")
202 name = args[index - 1]
205 name = func_defaults[index - (len(args) + 1)]
210 except (IndexError, TypeError):
212 f
'no "name" argument while instantiating "{cls.__name__}"'
217 if hasattr(cls,
"DefaultedName"):
218 name = cls.DefaultedName
221 elif not name
or not isinstance(name, str):
224 f
"could not retrieve name from {cls.__name__}.__init__ arguments"
229 if issubclass(cls, ConfigurableAlgTool)
and "." not in name:
230 name =
"ToolSvc." + name
245 for n, v
in kwargs.items():
250 and "_enabled" not in kwargs
251 and isinstance(conf, ConfigurableUser)
255 setattr(conf,
"_enabled",
True)
259 spos = name.find(
"/")
262 ti_name = f
"{name}/{name}"
270 if i_name == name[spos + 1 :]
and i_name
in cls.
configurables:
280 and i_name == name[spos + 1 :]
285 if conf.__class__
is ConfigurableGeneric:
289 newconf = object.__new__(cls)
290 cls.
__init__(newconf, *args, **kwargs)
295 for n
in newconf.__slots__:
297 for n
in conf._properties:
298 if names[n.lower()] != n:
300 f
"Option '{n}' was used for {name}, but the correct spelling is '{names[n.lower()]}'"
302 setattr(newconf, names[n.lower()], getattr(conf, n))
303 for n, v
in kwargs.items():
304 setattr(newconf, n, v)
311 'attempt to redefine type of "%s" (was: %s, new: %s)%s',
313 conf.__class__.__name__,
321 for n, v
in kwargs.items():
326 conf = object.__new__(cls)
333 if base.__name__ ==
"ConfigurableService":
348 if klass == Configurable:
349 raise TypeError(f
"{Configurable} is an ABC and can not be instantiated")
360 for meth, nArgs
in meths.items():
362 f = getattr(klass, meth)
363 except AttributeError:
364 raise NotImplementedError(f
"{meth} is missing in class {klass}")
367 nargcount = f.__code__.co_argcount
368 fdefaults = f.__defaults__
369 ndefaults = fdefaults
and len(fdefaults)
or 0
370 if not nargcount - ndefaults <= nArgs <= nargcount:
371 raise TypeError(f
"{klass}.{meth} requires exactly {nArgs} arguments")
403 dict[name] = proxy.__get__(self)
404 except AttributeError:
407 dict[
"_Configurable__children"] = self.
__children
408 dict[
"_Configurable__tools"] = self.
__tools
409 dict[
"_name"] = self.
_name
417 from contextlib
import contextmanager
428 for n, v
in dict.items():
445 proxy.__set__(newconf, proxy.__get__(self))
446 except AttributeError:
456 if not isinstance(configs, (list, tuple)):
463 if not isinstance(cfg, Configurable):
464 raise TypeError(f
"'{cfg}' is not a Configurable")
469 ccjo = cc.getJobOptName()
471 if c.getJobOptName() == ccjo:
473 "attempt to add a duplicate ... dupe ignored%s",
482 descr.__set__(self, cc)
484 setattr(self, cc.getName(), cc)
485 except AttributeError:
497 (DataHandle, DataHandleVector),
502 if c.getName() == attr:
505 raise AttributeError(f
"'{self.__class__}' object has no attribute '{attr}'")
510 f
"{self.name()}: Configuration cannot be modified after the ApplicationMgr has been started."
514 except AttributeError:
515 raise AttributeError(
516 f
"Configurable '{self.__class__.__name__}' does not have property '{name}'."
524 prop.__delete__(self)
525 prop.__set__(self, prop.default)
535 if c.getName() == attr:
540 del self.__dict__[attr]
541 except (AttributeError, KeyError):
548 if not isinstance(items, (list, tuple)):
558 return copy.deepcopy(child)
572 if hasattr(cc,
"setParent")
and parent:
575 except RuntimeError
as e:
577 log.error(str(e) +
"%s", error_explanation)
578 ccbd = cc.configurables[cc.getJobOptName()]
582 if cc
in proxy.history:
583 proxy.__set__(ccbd, proxy.__get__(cc))
596 log.error(
"children() is deprecated, use getChildren() instead for consistency")
598 "getChildren() returns a copy; to add a child, use 'parent += child'%s",
604 """Get all (private) configurable children, both explicit ones (added with +=)
605 and the ones in the private GaudiHandle properties"""
610 c = proxy.__get__(self)
611 except AttributeError:
614 if isinstance(c, Configurable)
and not c.isPublic():
616 elif isinstance(c, GaudiHandle):
618 conf = c.configurable
619 except AttributeError:
622 if not conf.isPublic():
624 elif isinstance(c, GaudiHandleArray):
628 if isinstance(ci, Configurable):
632 conf = ci.configurable
633 except AttributeError:
645 elems.append(c.getFullName())
650 if not hasattr(self,
"_initok")
or not self.
_initok:
653 f
"Configurable.__init__ not called in {self.__class__.__name__} override"
668 handle = self.getHandle()
670 log.debug(
"no handle for %s: not transporting properties", self.
_name)
675 if hasattr(self, name):
676 setattr(handle, name, getattr(self, name))
685 props[name] = proxy.__get__(self)
686 except AttributeError:
687 props[name] = Configurable.propertyNoValue
692 """Get all properties with their description string as { name : (value, desc) }."""
696 props[name] = (proxy.__get__(self), proxy.__doc__)
697 except AttributeError:
698 props[name] = (Configurable.propertyNoValue, proxy.__doc__)
705 value = proxy.__get__(self)
706 if hasattr(value,
"getFullName"):
707 value = value.getFullName()
708 elif isinstance(value, (list, set, tuple)):
711 if hasattr(i,
"getFullName"):
712 new_value.append(i.getFullName())
715 value = type(value)(new_value)
716 elif isinstance(value, dict):
719 if hasattr(value[i],
"getFullName"):
722 new_value[i] = value[i]
739 if k
not in c.__dict__
and hasattr(v,
"default"):
740 c.__dict__[k] = v.default
750 if name
in c.__dict__:
751 return c.__dict__[name]
756 if hasattr(v,
"default"):
764 """Returns the value of the given property."""
765 if hasattr(self, name):
766 return getattr(self, name)
771 """Set the value of a given property"""
772 return setattr(self, name, value)
775 """Tell if the property 'name' has been set or not.
777 Because of a problem with list and dictionary properties, in those cases
778 if the value is equal to the default, the property is considered as not
781 if not hasattr(self, name):
786 (list, dict, set, DataHandle, DataHandleVector, GaudiHandleArray),
788 value = getattr(self, name)
789 return value != default
810 "jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
819 return f
"{self.getType()}/{self.getJobOptName() or self.getName()}"
825 if log.isEnabledFor(logging.DEBUG):
833 def clone(self, name=None, **kwargs):
835 if hasattr(self,
"DefaultedName"):
836 name = self.DefaultedName
838 name = self.getType()
840 newconf = Configurable.__new__(self.__class__, name)
841 self.__class__.
__init__(newconf, name)
843 for proxy
in self._properties.values():
845 value = proxy.__get__(self)
846 if isinstance(value, (str, list, dict, tuple, set)):
848 value = type(value)(value)
849 proxy.__set__(newconf, value)
850 except AttributeError:
853 for c
in self.__children:
856 for n, t
in self.__tools.items():
857 newconf.addTool(t, n)
859 for name, value
in kwargs.items():
860 setattr(newconf, name, value)
866 dot = fullname.find(
".")
868 parentname = fullname[:dot]
869 longname = fullname[dot + 1 :]
873 dot = longname.find(
".")
875 name = longname[:dot]
878 return parentname, name, longname
881 if isclass(tool)
and issubclass(tool, ConfigurableAlgTool):
884 priv_tool = tool(self.
getName() +
"." + name)
885 elif isinstance(tool, ConfigurableAlgTool):
887 name = tool.splitName()[1]
888 priv_tool = tool.clone(self.
getName() +
"." + name)
891 classname = tool.__name__
893 classname = type(tool).__name__
895 f
"addTool requires AlgTool configurable. Got {classname} type"
900 setattr(self, name, self.
__tools[name])
916 handle = __main__.Service(svc)
921 if hasattr(self,
"configure" + svc):
922 eval(
"self.configure" + svc +
"( handle )")
925 dlls = self.getDlls()
928 elif isinstance(dlls, types.StringType):
931 from __main__
import theApp
933 dlls = filter(
lambda d: d
not in theApp.Dlls, dlls)
946 preLen = Configurable.printHeaderPre
948 Configurable.printHeaderWidth - preLen - 3 - len(title)
950 postLen = max(preLen, postLen)
951 return indentStr +
"/{} {} {}".
format(preLen *
"*", title, postLen *
"*")
955 preLen = Configurable.printHeaderPre
957 Configurable.printHeaderWidth - preLen - 12 - len(title)
959 postLen = max(preLen, postLen)
960 return indentStr +
"\\{} (End of {}) {}".
format(
961 preLen *
"-", title, postLen *
"-"
965 return f
"{self.__class__.__name__}({self.name()!r})"
967 def __str__(self, indent=0, headerLastIndentUnit=indentUnit):
970 def _sorted_repr_set(value):
971 """Helper to print sorted set representation"""
972 return "{" + repr(sorted(value))[1:-1] +
"}" if value
else "set()"
974 indentStr = indent * Configurable.indentUnit
979 headerIndent = (indent - 1) * Configurable.indentUnit + headerLastIndentUnit
982 rep = Configurable._printHeader(headerIndent, title)
988 rep += f
"{indentStr}|-<no properties>{os.linesep}"
992 for p
in props.keys():
993 nameWidth = max(nameWidth, len(p))
994 for p, v
in props.items():
996 prefix = f
"{indentStr}|-{p:<{nameWidth}}"
998 if log.isEnabledFor(logging.DEBUG):
999 if v != Configurable.propertyNoValue:
1000 address = f
" @{id(v):#018x}"
1005 default = defs.get(p)
1006 if v == Configurable.propertyNoValue:
1008 strVal = repr(default)
1012 if hasattr(v,
"getGaudiHandle"):
1013 vv = v.getGaudiHandle()
1016 if isinstance(vv, (GaudiHandle, GaudiHandleArray, DataHandle)):
1019 if hasattr(default,
"toStringProperty"):
1020 strDef = repr(default.toStringProperty())
1022 strDef = repr(default)
1023 if strDef == repr(vv.toStringProperty()):
1025 elif isinstance(vv, set):
1026 strVal = _sorted_repr_set(vv)
1027 strDef = _sorted_repr_set(default)
1030 strDef = repr(default)
1032 line = prefix +
" = " + strVal
1034 if strDef
is not None:
1036 if len(line) + len(strDef) > Configurable.printHeaderWidth:
1041 + (len(prefix) - len(indentStr) - 3) *
" "
1043 line += f
" (default: {strDef})"
1045 rep += line + os.linesep
1057 rep += cfg.__str__(indent + 1,
"|=") + os.linesep
1060 rep += Configurable._printFooter(indentStr, title)
1065 Return True is the instance can be "applied".
1066 Always False for plain Configurable instances
1067 (i.e. not ConfigurableUser).
1083 object.__setattr__(obj, self.
__name__, value)
1090 Configurable.__init__(self, name)
1099 return "GenericComponent"
1114 if isinstance(value, Configurable):
1115 self.__dict__[name] = value
1119 if name
not in self._properties:
1121 self._properties[name].__set__(self, value)
1157 elif rhs
is CFFalse:
1159 return AndNode(self, rhs)
1166 return OrNode(self, rhs)
1169 return InvertNode(self)
1172 return OrderedNode(self, rhs)
1183 return repr(self) == repr(other)
1186 """Return a unique identifier for this object.
1188 As we use the `repr` of this object to check for equality, we use it
1189 here to define uniqueness.
1192 return hash((repr(self),))
1198 "AuditInitialize": 0,
1207 if isinstance(child, ConfigurableAlgTool)
and not child.isPublic():
1208 return copy.deepcopy(child)
1231 "AuditInitialize": 0,
1241 name = name[name.find(
"/") + 1 :]
1265 return pop + Configurable.getPrintTitle(self)
1275 instance = name[name.rfind(
".") + 1 :]
1279 if isinstance(c, ConfigurableAlgTool):
1280 c.setParent(parentName +
"." + instance)
1303 return parent ==
"ToolSvc"
1314 name = name[name.rfind(
".") + 1 :]
1315 return str(self.
getType() +
"/" + name)
1322 __slots__ = {
"_jobOptName": 0,
"OutputLevel": 0,
"Enable": 1}
1327 name = name[name.find(
"/") + 1 :]
1351 "__used_instances__": [],
1363 __used_configurables__ = []
1366 __queried_configurables__ = []
1368 def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs):
1370 for n, v
in kwargs.items():
1388 if isinstance(used, tuple):
1389 used, used_name = used
1393 if isinstance(used, str):
1394 used_class = confDbGetConfigurable(used)
1399 inst = used_class(name=used_name, _enabled=
False)
1400 except AttributeError:
1404 inst = used_class(name=used_name)
1408 if isinstance(queried, str):
1409 queried = confDbGetConfigurable(queried)
1410 inst = queried(_enabled=
False)
1411 except AttributeError:
1417 Declare that we are going to modify the Configurable 'other' in our
1418 __apply_configuration__.
1421 if hasattr(other,
"__users__"):
1422 other.__users__.append(self)
1426 Declare that we are going to retrieve property values from the
1427 ConfigurableUser 'other' in our __apply_configuration__.
1429 if not isinstance(other, ConfigurableUser):
1431 f
"'{self.name()}': Cannot make passive use of '{other.name()}', it is not a ConfigurableUser"
1433 other.__addActiveUseOf(self)
1447 Remove this ConfigurableUser instance from the users list of the used
1451 if hasattr(used,
"__users__"):
1452 used.__users__.remove(self)
1456 Propagate the property 'name' (if set) to other configurables (if possible).
1459 propagate to all the entries in __used_configurables__
1460 a configurable instance:
1461 propagate only to it
1462 list of configurable instances:
1463 propagate to all of them.
1467 - if the local property is set, the other property will be overwritten
1468 - local property not set and other set => keep other
1469 - local property not set and other not set => overwrite the default for
1470 ConfigurableUser instances and set the property for Configurables
1475 elif type(others)
not in [list, tuple]:
1481 for other
in [o
for o
in others
if name
in o.__slots__]:
1484 if other.isPropertySet(name):
1486 "Property '{prop}' is set in both '{self}' and '{other}', using '{self}.{prop}'".
format(
1487 self=self.
name(), other=other.name(), prop=name
1490 other.setProp(name, value)
1492 elif not other.isPropertySet(name):
1493 if isinstance(other, ConfigurableUser):
1494 otherType = type(other._properties[name].getDefault())
1495 other._properties[name].setDefault(value)
1496 if otherType
in (list, dict, set):
1499 other.setProp(name, otherType(value))
1501 other.setProp(name, value)
1506 Call propagateProperty for each property listed in 'names'.
1507 If 'names' is None, all the properties are propagated.
1511 names = [p
for p
in self.
__slots__ if not p.startswith(
"_")]
1517 Function to be overridden to convert the high level configuration into a
1519 The default implementation calls applyConf, which is the method defined
1520 in some ConfigurableUser implementations.
1526 Function to be overridden to convert the high level configuration into a
1533 Function used to define the name of the private instance of a given class
1535 This method is used when the __used_configurables_property__ declares the
1536 need of a private used configurable without specifying the name.
1538 if isinstance(cls, str):
1541 clName = cls.__name__
1542 return f
"{self.name()}_{clName}"
1546 Return the used instance with a given name.
1549 if i.name() == name:
1550 if hasattr(i,
"_enabled"):
1555 raise KeyError(name)
1559 Return True is the instance can be "applied".
1565postConfigActions = []
1570 Add a new callable ('function') to the list of post-configuration actions.
1571 If the callable is already in the list, it is moved to the end of the list.
1572 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1575 postConfigActions.remove(function)
1578 postConfigActions.append(function)
1583 Remove a callable from the list of post-config actions.
1584 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1586 postConfigActions.remove(function)
1589_appliedConfigurableUsers_ =
False
1594 Call the apply method of all the ConfigurableUser instances respecting the
1595 dependencies. First the C.U.s that are not used by anybody, then the used
1596 ones, when they are not used anymore.
1599 global _appliedConfigurableUsers_, postConfigActions
1600 if _appliedConfigurableUsers_:
1602 _appliedConfigurableUsers_ =
True
1604 def applicableConfUsers():
1606 Generator returning all the configurables that can be applied in the
1607 order in which they can be applied.
1622 for c
in Configurable.allConfigurables.values()
1625 except StopIteration:
1628 debugApplyOrder =
"GAUDI_DUBUG_CONF_USER" in os.environ
1629 for c
in applicableConfUsers():
1631 log.info(
"applying configuration of %s", c.name())
1633 sys.stderr.write(f
"applying {c!r}")
1634 c.__apply_configuration__()
1637 log.info(
"skipping configuration of %s", c.name())
1639 if hasattr(c,
"__detach_used__"):
1646 for c
in Configurable.allConfigurables.values()
1647 if hasattr(c,
"__apply_configuration__")
and c._enabled
and not c._applied
1652 "Detected loop in the ConfigurableUser"
1653 " dependencies: %r" % [c.name()
for c
in leftConfUsers]
1657 unknown = set(Configurable.allConfigurables)
1661 log.debug(
"new configurable created automatically: %s", k)
1663 Configurable.allConfigurables[k].properties()
1667 for action
in postConfigActions:
1673 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1674 backward compatibility for configurations that where relying (implicitly) on
1675 bug #103803, or on a specific (non guaranteed) order of execution.
1677 @see applyConfigurableUsers()
1680 global _appliedConfigurableUsers_, postConfigActions
1681 if _appliedConfigurableUsers_:
1683 _appliedConfigurableUsers_ =
True
1685 debugApplyOrder =
"GAUDI_DUBUG_CONF_USER" in os.environ
1688 for c
in Configurable.allConfigurables.values()
1689 if hasattr(c,
"__apply_configuration__")
1692 while applied
and confUsers:
1696 if hasattr(c,
"__users__")
and c.__users__:
1697 newConfUsers.append(c)
1702 enabled = (
not hasattr(c,
"_enabled"))
or c._enabled
1704 log.info(
"applying configuration of %s", c.name())
1706 sys.stderr.write(f
"applying {c!r}")
1707 c.__apply_configuration__()
1710 log.info(
"skipping configuration of %s", c.name())
1711 if hasattr(c,
"__detach_used__"):
1714 confUsers = newConfUsers
1718 "Detected loop in the ConfigurableUser "
1719 " dependencies: %r" % [c.name()
for c
in confUsers]
1723 unknown = set(Configurable.allConfigurables)
1727 log.debug(
"new configurable created automatically: %s", k)
1729 Configurable.allConfigurables[k].properties()
1733 for action
in postConfigActions:
1739 Function to select all and only the configurables that have to be used in
1740 GaudiPython.AppMgr constructor.
1741 This is needed because in Athena the implementation have to be different (the
1742 configuration is used in a different moment).
1746 for k, v
in Configurable.allConfigurables.items()
1747 if v.getGaudiType() !=
"User"
1753 Clean up all configurations and configurables.
1755 for c
in Configurable.allConfigurables.values():
1756 c.__class__.configurables.clear()
1757 Configurable.allConfigurables.clear()
1760 ConfigurableGeneric.configurables.clear()
1764 from .ProcessJobOptions
import _included_files
1766 for file
in _included_files:
1767 dirname, basname = os.path.split(file)
1768 basname, ext = os.path.splitext(basname)
1769 if basname
in sys.modules:
1770 del sys.modules[basname]
1771 _included_files.clear()
1780 return self.
stack[-1]
1789 name = prefix + str(cnt)
1790 while name
in allConfigurables:
1792 name = prefix + str(cnt)
1796 from Configurables
import Gaudi__Sequencer
1802 if visitee
in (CFTrue, CFFalse):
1803 stack.append(self.
_newSeq(Invert=visitee
is CFFalse))
1804 elif isinstance(visitee, (ControlFlowLeaf, ConfigurableAlgorithm)):
1805 stack.append(visitee)
1806 elif isinstance(visitee, (OrNode, AndNode, OrderedNode)):
1811 ModeOR=isinstance(visitee, OrNode),
1812 ShortCircuit=
not isinstance(visitee, OrderedNode),
1815 elif isinstance(visitee, ignore):
1816 if hasattr(stack[-1],
"IgnoreFilterPassed"):
1817 stack[-1].IgnoreFilterPassed =
True
1820 self.
_newSeq(Members=[stack.pop()], IgnoreFilterPassed=
True)
1822 elif isinstance(visitee, InvertNode):
1823 if hasattr(stack[-1],
"Invert"):
1824 stack[-1].Invert =
True
1826 stack.append(self.
_newSeq(Members=[stack.pop()], Invert=
True))
1831 Convert a control flow expression to nested GaudiSequencers.
1833 if not isinstance(expression, ControlFlowNode):
1835 f
"ControlFlowNode instance expected, got {type(expression).__name__}"
1838 expression.visitNode(visitor)
1839 return visitor.sequence
1844 Helper class to use a ControlFlowNode as an algorithm configurable
1851 if name
in Configurable.allConfigurables:
1852 instance = Configurable.allConfigurables[name]
1853 assert type(instance)
is cls, (
1854 f
"trying to reuse {name!r} as name of a {cls.__name__} instance while it"
1856 f
"already used for an instance of {type(instance).__name__}"
1860 instance = super().
__new__(cls)
1861 Configurable.allConfigurables[name] = instance
1868 setattr(self, key, kwargs[key])
1893 Instantiate and algorithm of type 'typ' with a name suitable for use
1894 inside a SuperAlgorithm.
1896 name =
"{}_{}".
format(self.
name, kwargs.pop(
"name", typ.getType()))
1897 return typ(name, **kwargs)
1900 raise NotImplementedError()
1903 return f
"{self.getType()}({self.name!r})"
1907 self.
graph.visitNode(visitor)
1911 if name
in (
"_name",
"graph"):
1916 def enter(self, node):
1918 setattr(node, name, value)
1919 except (ValueError, AttributeError):
1923 def leave(self, node):
1926 self._visitSubNodes(PropSetter())
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
_visitSubNodes(self, visitor)
__init__(self, name=Configurable.DefaultName)
__init__(self, name=Configurable.DefaultName)
__init__(self, name=Configurable.DefaultName)
__setattr__(self, name, value)
getDefaultProperty(cls, name)
getPropertiesWithDescription(self)
isPropertySet(self, name)
copyChildAndSetParent(self, cfg, parent)
__iadd__(self, configs, descr=None)
getDefaultProperties(cls)
bool _configurationLocked
__str__(self, indent=0, headerLastIndentUnit=indentUnit)
dict configurableServices
clone(self, name=None, **kwargs)
_printFooter(indentStr, title)
_printHeader(indentStr, title)
__init__(self, name=DefaultName)
setProp(self, name, value)
addTool(self, tool, name=None)
__setattr__(self, name, value)
__new__(cls, *args, **kwargs)
setParent(self, parentName)
getValuedProperties(self)
list __queried_configurables__
__init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs)
__apply_configuration__(self)
propagateProperty(self, name, others=None, force=True)
__addActiveUseOf(self, other)
getUsedInstance(self, name)
propagateProperties(self, names=None, others=None, force=True)
__addPassiveUseOf(self, other)
list __used_configurables__
_getUniqueName(self, prefix)
_newSeq(self, prefix="seq_", **kwargs)
__get__(self, obj, type=None)
__set__(self, obj, value)
__setattr__(self, name, value)
__init__(self, name=None, **kwargs)
_visitSubNodes(self, visitor)
__new__(cls, name=None, **kwargs)
_makeAlg(self, typ, **kwargs)
removePostConfigAction(function)
makeSequences(expression)
appendPostConfigAction(function)
applyConfigurableUsers_old()