14 from __future__
import absolute_import
20 from inspect
import isclass
57 "ConfigurableAlgorithm",
58 "ConfigurableAlgTool",
59 "ConfigurableAuditor",
60 "ConfigurableService",
68 "appendPostConfigAction",
69 "removePostConfigAction",
75 log = logging.getLogger(
"Configurable")
80 Expand environment variables "data".
81 Data can be string, list, tuple and dictionary. For collection, all the
82 contained strings will be manipulated (recursively).
88 return os.path.expandvars(data)
89 elif typ
in [list, tuple]:
104 Error occurred in the configuration process.
113 class PropertyReference(object):
118 return "@%s" % self.
name
123 refname, refprop = self.
name.rsplit(
".", 1)
124 if refname
in Configurable.allConfigurables:
125 conf = Configurable.allConfigurables[refname]
126 retval = getattr(conf, refprop)
127 if hasattr(retval,
"getFullName"):
128 retval = retval.getFullName()
130 raise NameError(
"name '%s' not found resolving '%s'" % (refname, self))
134 """This function allow transparent integration with
135 Configurable.getValuedProperties.
142 except AttributeError:
151 """Base class for Gaudi components that implement the IProperty interface.
152 Provides most of the boilerplate code, but the actual useful classes
153 are its derived ConfigurableAlgorithm, ConfigurableService, and
154 ConfigurableAlgTool."""
160 propertyNoValue =
"<no value>"
162 printHeaderWidth = 100
175 allConfigurables = {}
176 configurableServices = {}
179 _configurationLocked =
False
182 """To Gaudi, any object with the same type/name is the same object. Hence,
183 this is mimicked in the configuration: instantiating a new Configurable
184 of a type with the same name will return the same instance."""
187 func_code = six.get_function_code(cls.
__init__)
188 func_defaults = six.get_function_defaults(cls.
__init__)
192 name = kwargs[
"name"]
193 elif "name" in func_code.co_varnames:
195 index = list(func_code.co_varnames).index(
"name")
198 name = args[index - 1]
201 name = func_defaults[index - (len(args) + 1)]
206 except (IndexError, TypeError):
208 'no "name" argument while instantiating "%s"' % cls.__name__
213 if hasattr(cls,
"DefaultedName"):
214 name = cls.DefaultedName
217 elif not name
or not isinstance(name, str):
220 "could not retrieve name from %s.__init__ arguments" % cls.__name__
225 if issubclass(cls, ConfigurableAlgTool)
and "." not in name:
226 name =
"ToolSvc." + name
236 if name
in cls.configurables:
237 conf = cls.configurables[name]
239 cls.configurables[conf.getType()] = conf
241 for n, v
in kwargs.items():
246 and "_enabled" not in kwargs
247 and isinstance(conf, ConfigurableUser)
251 setattr(conf,
"_enabled",
True)
255 spos = name.find(
"/")
258 ti_name =
"%s/%s" % (name, name)
259 if ti_name
in cls.configurables:
261 return cls.configurables[ti_name]
266 if i_name == name[spos + 1 :]
and i_name
in cls.configurables:
268 return cls.configurables[i_name]
276 and i_name == name[spos + 1 :]
281 if conf.__class__
is ConfigurableGeneric:
285 newconf = object.__new__(cls)
286 cls.
__init__(newconf, *args, **kwargs)
291 for n
in newconf.__slots__:
293 for n
in conf._properties:
294 if names[n.lower()] != n:
296 "Option '%s' was used for %s, but the correct spelling is '%s'"
297 % (n, name, names[n.lower()])
299 setattr(newconf, names[n.lower()], getattr(conf, n))
300 for n, v
in kwargs.items():
301 setattr(newconf, n, v)
302 cls.configurables[name] = newconf
308 'attempt to redefine type of "%s" (was: %s, new: %s)%s',
310 conf.__class__.__name__,
318 for n, v
in kwargs.items():
323 conf = object.__new__(cls)
327 cls.configurables[name] = conf
329 for base
in cls.__bases__:
330 if base.__name__ ==
"ConfigurableService":
342 klass = self.__class__
345 if klass == Configurable:
347 "%s is an ABC and can not be instantiated" % str(Configurable)
359 for meth, nArgs
in meths.items():
361 f = six.get_unbound_function(getattr(klass, meth))
362 except AttributeError:
363 raise NotImplementedError(
364 "%s is missing in class %s" % (meth, str(klass))
368 nargcount = six.get_function_code(f).co_argcount
369 fdefaults = six.get_function_defaults(f)
370 ndefaults = fdefaults
and len(fdefaults)
or 0
371 if not nargcount - ndefaults <= nArgs <= nargcount:
373 "%s.%s requires exactly %d arguments" % (klass, meth, nArgs)
382 if hasattr(self.__class__,
"DefaultedName"):
383 self.
_name = self.__class__.DefaultedName
404 for name, proxy
in self._properties.
items():
406 dict[name] = proxy.__get__(self)
407 except AttributeError:
410 dict[
"_Configurable__children"] = self.
__children
411 dict[
"_Configurable__tools"] = self.
__tools
412 dict[
"_name"] = self.
_name
420 from contextlib
import contextmanager
431 for n, v
in dict.items():
443 newconf = object.__new__(self.__class__)
446 for proxy
in self._properties.values():
448 proxy.__set__(newconf, proxy.__get__(self))
449 except AttributeError:
459 if not type(configs)
in (list, tuple):
466 if not isinstance(cfg, Configurable):
467 raise TypeError(
"'%s' is not a Configurable" % str(cfg))
472 ccjo = cc.getJobOptName()
474 if c.getJobOptName() == ccjo:
476 "attempt to add a duplicate ... dupe ignored%s",
485 descr.__set__(self, cc)
487 setattr(self, cc.getName(), cc)
488 except AttributeError:
497 if attr
in self._properties:
498 if isinstance(self._properties[attr].__get__(self), DataHandle):
499 return self._properties[attr].__get__(self)
502 if c.getName() == attr:
505 raise AttributeError(
506 "'%s' object has no attribute '%s'" % (self.__class__, attr)
512 "%s: Configuration cannot be modified after the ApplicationMgr has been started."
517 except AttributeError:
518 raise AttributeError(
519 "Configurable '%s' does not have property '%s'."
520 % (self.__class__.__name__, name)
527 prop = self._properties[attr]
528 prop.__delete__(self)
529 prop.__set__(self, prop.default)
539 if c.getName() == attr:
544 del self.__dict__[attr]
545 except (AttributeError, KeyError):
552 __nonzero__ = __bool__
555 if not isinstance(items, (list, tuple)):
565 return copy.deepcopy(child)
579 if hasattr(cc,
"setParent")
and parent:
582 except RuntimeError
as e:
584 log.error(str(e) +
"%s", error_explanation)
585 ccbd = cc.configurables[cc.getJobOptName()]
588 for proxy
in self._properties.values():
589 if cc
in proxy.history:
590 proxy.__set__(ccbd, proxy.__get__(cc))
603 log.error(
"children() is deprecated, use getChildren() instead for consistency")
605 "getChildren() returns a copy; to add a child, use 'parent += child'%s",
611 """Get all (private) configurable children, both explicit ones (added with +=)
612 and the ones in the private GaudiHandle properties"""
615 for proxy
in self._properties.values():
617 c = proxy.__get__(self)
618 except AttributeError:
621 if isinstance(c, Configurable)
and not c.isPublic():
623 elif isinstance(c, GaudiHandle):
625 conf = c.configurable
626 except AttributeError:
629 if not conf.isPublic():
631 elif isinstance(c, GaudiHandleArray):
635 if isinstance(ci, Configurable):
639 conf = ci.configurable
640 except AttributeError:
652 elems.append(c.getFullName())
657 if not hasattr(self,
"_initok")
or not self.
_initok:
660 "Configurable.__init__ not called in %s override"
661 % self.__class__.__name__
676 handle = self.getHandle()
678 log.debug(
"no handle for %s: not transporting properties", self.
_name)
682 for name
in self._properties.
keys():
683 if hasattr(self, name):
684 setattr(handle, name, getattr(self, name))
691 for name, proxy
in self._properties.
items():
693 props[name] = proxy.__get__(self)
694 except AttributeError:
695 props[name] = Configurable.propertyNoValue
700 """Get all properties with their description string as { name : (value, desc) }."""
702 for name, proxy
in self._properties.
items():
704 props[name] = (proxy.__get__(self), proxy.__doc__)
705 except AttributeError:
706 props[name] = (Configurable.propertyNoValue, proxy.__doc__)
711 for name, proxy
in self._properties.
items():
713 value = proxy.__get__(self)
714 if hasattr(value,
"getFullName"):
715 value = value.getFullName()
716 elif type(value)
in [list, tuple]:
719 if hasattr(i,
"getFullName"):
720 new_value.append(i.getFullName())
723 value =
type(value)(new_value)
724 elif type(value)
is dict:
727 if hasattr(value[i],
"getFullName"):
730 new_value[i] = value[i]
749 for k, v
in cls._properties.
items():
750 if k
not in c.__dict__
and hasattr(v,
"default"):
751 c.__dict__[k] = v.default
764 if name
in c.__dict__:
765 return c.__dict__[name]
769 v = cls._properties[name]
770 if hasattr(v,
"default"):
778 """Returns the value of the given property."""
779 if hasattr(self, name):
780 return getattr(self, name)
785 """Set the value of a given property"""
786 return setattr(self, name, value)
789 """Tell if the property 'name' has been set or not.
791 Because of a problem with list and dictionary properties, in those cases
792 if the value is equal to the default, the property is considered as not
795 if not hasattr(self, name):
798 if isinstance(default, (list, dict, DataHandle)):
799 value = getattr(self, name)
800 return value != default
821 "jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
836 if log.isEnabledFor(logging.DEBUG):
844 def clone(self, name=None, **kwargs):
846 if hasattr(self,
"DefaultedName"):
847 name = self.DefaultedName
849 name = self.getType()
851 newconf = Configurable.__new__(self.__class__, name)
852 self.__class__.
__init__(newconf, name)
854 for proxy
in self._properties.values():
856 value = proxy.__get__(self)
857 if type(value)
in [str, list, dict, tuple]:
859 value =
type(value)(value)
860 proxy.__set__(newconf, value)
861 except AttributeError:
864 for c
in self.__children:
867 for n, t
in self.__tools.
items():
868 newconf.addTool(t, n)
870 for name, value
in kwargs.items():
871 setattr(newconf, name, value)
877 dot = fullname.find(
".")
879 parentname = fullname[:dot]
880 longname = fullname[dot + 1 :]
884 dot = longname.find(
".")
886 name = longname[:dot]
889 return parentname, name, longname
892 if isclass(tool)
and issubclass(tool, ConfigurableAlgTool):
896 elif isinstance(tool, ConfigurableAlgTool):
898 name = tool.splitName()[1]
899 priv_tool = tool.clone(self.
getName() +
"." + name)
902 classname = tool.__name__
904 classname =
type(tool).__name__
906 "addTool requires AlgTool configurable. Got %s type" % classname
911 setattr(self, name, self.
__tools[name])
927 handle = __main__.Service(svc)
932 if hasattr(self,
"configure" + svc):
933 eval(
"self.configure" + svc +
"( handle )")
936 dlls = self.getDlls()
939 elif isinstance(dlls, types.StringType):
942 from __main__
import theApp
944 dlls = filter(
lambda d: d
not in theApp.Dlls, dlls)
957 preLen = Configurable.printHeaderPre
959 Configurable.printHeaderWidth - preLen - 3 - len(title)
961 postLen =
max(preLen, postLen)
962 return indentStr +
"/%s %s %s" % (preLen *
"*", title, postLen *
"*")
966 preLen = Configurable.printHeaderPre
968 Configurable.printHeaderWidth - preLen - 12 - len(title)
970 postLen =
max(preLen, postLen)
971 return indentStr +
"\\%s (End of %s) %s" % (preLen *
"-", title, postLen *
"-")
974 return "{0}({1!r})".
format(self.__class__.__name__, self.
name())
976 def __str__(self, indent=0, headerLastIndentUnit=indentUnit):
978 indentStr = indent * Configurable.indentUnit
983 headerIndent = (indent - 1) * Configurable.indentUnit + headerLastIndentUnit
986 rep = Configurable._printHeader(headerIndent, title)
992 rep += indentStr +
"|-<no properties>" + os.linesep
996 for p
in props.keys():
997 nameWidth =
max(nameWidth, len(p))
998 for p, v
in props.items():
1000 prefix = indentStr +
"|-%-*s" % (nameWidth, p)
1002 if log.isEnabledFor(logging.DEBUG):
1003 if v != Configurable.propertyNoValue:
1004 address =
" @%11s" %
hex(id(v))
1009 default = defs.get(p)
1010 if v == Configurable.propertyNoValue:
1012 strVal = repr(default)
1016 if hasattr(v,
"getGaudiHandle"):
1017 vv = v.getGaudiHandle()
1020 if isinstance(vv, (GaudiHandle, GaudiHandleArray, DataHandle)):
1023 if hasattr(default,
"toStringProperty"):
1024 strDef = repr(default.toStringProperty())
1026 strDef = repr(default)
1027 if strDef == repr(vv.toStringProperty()):
1031 strDef = repr(default)
1033 line = prefix +
" = " + strVal
1035 if strDef
is not None:
1037 if len(line) + len(strDef) > Configurable.printHeaderWidth:
1042 + (len(prefix) - len(indentStr) - 3) *
" "
1044 line +=
" (default: %s)" % (strDef,)
1046 rep += line + os.linesep
1058 rep += cfg.__str__(indent + 1,
"|=") + os.linesep
1061 rep += Configurable._printFooter(indentStr, title)
1066 Return True is the instance can be "applied".
1067 Always False for plain Configurable instances
1068 (i.e. not ConfigurableUser).
1084 object.__setattr__(obj, self.
__name__, value)
1091 Configurable.__init__(self, name)
1100 return "GenericComponent"
1111 super(ConfigurableGeneric, self).
__setattr__(name, value)
1115 if isinstance(value, Configurable):
1116 self.__dict__[name] = value
1120 if name
not in self._properties:
1122 self._properties[name].__set__(self, value)
1136 "AuditAlgorithms": 0,
1137 "AuditInitialize": 0,
1138 "AuditReinitialize": 0,
1144 super(ConfigurableAlgorithm, self).
__init__(name)
1167 elif rhs
is CFFalse:
1193 return repr(self) == repr(other)
1196 """Return a unique identifier for this object.
1198 As we use the `repr` of this object to check for equality, we use it
1199 here to define uniqueness.
1202 return hash((repr(self),))
1209 "AuditInitialize": 0,
1218 if isinstance(child, ConfigurableAlgTool)
and not child.isPublic():
1219 return copy.deepcopy(child)
1224 return iService(self.
_name)
1243 "AuditInitialize": 0,
1248 super(ConfigurableAlgTool, self).
__init__(name)
1249 if "." not in self.
_name:
1253 name = name[name.find(
"/") + 1 :]
1277 return pop + Configurable.getPrintTitle(self)
1286 if isinstance(c, ConfigurableAlgTool):
1287 c.setParent(parentName)
1291 name = name[name.rfind(
".") + 1 :]
1312 return parent ==
"ToolSvc"
1323 name = name[name.rfind(
".") + 1 :]
1324 return str(self.
getType() +
"/" + name)
1331 __slots__ = {
"_jobOptName": 0,
"OutputLevel": 0,
"Enable": 1}
1334 super(ConfigurableAuditor, self).
__init__(name)
1336 name = name[name.find(
"/") + 1 :]
1360 "__used_instances__": [],
1372 __used_configurables__ = []
1375 __queried_configurables__ = []
1377 def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs):
1378 super(ConfigurableUser, self).
__init__(name)
1379 for n, v
in kwargs.items():
1397 if type(used)
is tuple:
1398 used, used_name = used
1402 if type(used)
is str:
1403 used_class = confDbGetConfigurable(used)
1408 inst = used_class(name=used_name, _enabled=
False)
1409 except AttributeError:
1413 inst = used_class(name=used_name)
1417 if type(queried)
is str:
1418 queried = confDbGetConfigurable(queried)
1419 inst = queried(_enabled=
False)
1420 except AttributeError:
1426 Declare that we are going to modify the Configurable 'other' in our
1427 __apply_configuration__.
1430 if hasattr(other,
"__users__"):
1431 other.__users__.append(self)
1435 Declare that we are going to retrieve property values from the
1436 ConfigurableUser 'other' in our __apply_configuration__.
1438 if not isinstance(other, ConfigurableUser):
1440 "'%s': Cannot make passive use of '%s', it is not a ConfigurableUser"
1441 % (self.
name(), other.name())
1443 other.__addActiveUseOf(self)
1457 Remove this ConfigurableUser instance from the users list of the used
1461 if hasattr(used,
"__users__"):
1462 used.__users__.remove(self)
1466 Propagate the property 'name' (if set) to other configurables (if possible).
1469 propagate to all the entries in __used_configurables__
1470 a configurable instance:
1471 propagate only to it
1472 list of configurable instances:
1473 propagate to all of them.
1477 - if the local property is set, the other property will be overwritten
1478 - local property not set and other set => keep other
1479 - local property not set and other not set => overwrite the default for
1480 ConfigurableUser instances and set the property for Configurables
1485 elif type(others)
not in [list, tuple]:
1491 for other
in [o
for o
in others
if name
in o.__slots__]:
1494 if other.isPropertySet(name):
1496 "Property '%(prop)s' is set in both '%(self)s' and '%(other)s', using '%(self)s.%(prop)s'"
1497 % {
"self": self.
name(),
"other": other.name(),
"prop": name}
1499 other.setProp(name, value)
1501 elif not other.isPropertySet(name):
1502 if isinstance(other, ConfigurableUser):
1503 otherType =
type(other._properties[name].getDefault())
1504 other._properties[name].setDefault(value)
1505 if otherType
in [list, dict]:
1508 other.setProp(name, otherType(value))
1510 other.setProp(name, value)
1515 Call propagateProperty for each property listed in 'names'.
1516 If 'names' is None, all the properties are propagated.
1520 names = [p
for p
in self.
__slots__ if not p.startswith(
"_")]
1526 Function to be overridden to convert the high level configuration into a
1528 The default implementation calls applyConf, which is the method defined
1529 in some ConfigurableUser implementations.
1535 Function to be overridden to convert the high level configuration into a
1542 Function used to define the name of the private instance of a given class
1544 This method is used when the __used_configurables_property__ declares the
1545 need of a private used configurable without specifying the name.
1547 if type(cls)
is str:
1550 clName = cls.__name__
1551 return "%s_%s" % (self.name(), clName)
1555 Return the used instance with a given name.
1558 if i.name() == name:
1559 if hasattr(i,
"_enabled"):
1564 raise KeyError(name)
1568 Return True is the instance can be "applied".
1574 postConfigActions = []
1579 Add a new callable ('function') to the list of post-configuration actions.
1580 If the callable is already in the list, it is moved to the end of the list.
1581 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1584 postConfigActions.remove(function)
1587 postConfigActions.append(function)
1592 Remove a callable from the list of post-config actions.
1593 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1595 postConfigActions.remove(function)
1598 _appliedConfigurableUsers_ =
False
1603 Call the apply method of all the ConfigurableUser instances respecting the
1604 dependencies. First the C.U.s that are not used by anybody, then the used
1605 ones, when they are not used anymore.
1608 global _appliedConfigurableUsers_, postConfigActions
1609 if _appliedConfigurableUsers_:
1611 _appliedConfigurableUsers_ =
True
1613 def applicableConfUsers():
1615 Generator returning all the configurables that can be applied in the
1616 order in which they can be applied.
1631 for c
in Configurable.allConfigurables.values()
1634 except StopIteration:
1637 debugApplyOrder =
"GAUDI_DUBUG_CONF_USER" in os.environ
1638 for c
in applicableConfUsers():
1640 log.info(
"applying configuration of %s", c.name())
1642 sys.stderr.write(
"applying %r" % c)
1643 c.__apply_configuration__()
1646 log.info(
"skipping configuration of %s", c.name())
1648 if hasattr(c,
"__detach_used__"):
1655 for c
in Configurable.allConfigurables.values()
1656 if hasattr(c,
"__apply_configuration__")
and c._enabled
and not c._applied
1661 "Detected loop in the ConfigurableUser"
1662 " dependencies: %r" % [c.name()
for c
in leftConfUsers]
1666 unknown = set(Configurable.allConfigurables)
1670 log.debug(
"new configurable created automatically: %s", k)
1672 Configurable.allConfigurables[k].
properties()
1676 for action
in postConfigActions:
1682 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1683 backward compatibility for configurations that where relying (implicitly) on
1684 bug #103803, or on a specific (non guaranteed) order of execution.
1686 @see applyConfigurableUsers()
1689 global _appliedConfigurableUsers_, postConfigActions
1690 if _appliedConfigurableUsers_:
1692 _appliedConfigurableUsers_ =
True
1694 debugApplyOrder =
"GAUDI_DUBUG_CONF_USER" in os.environ
1697 for c
in Configurable.allConfigurables.values()
1698 if hasattr(c,
"__apply_configuration__")
1701 while applied
and confUsers:
1705 if hasattr(c,
"__users__")
and c.__users__:
1706 newConfUsers.append(c)
1711 enabled = (
not hasattr(c,
"_enabled"))
or c._enabled
1713 log.info(
"applying configuration of %s", c.name())
1715 sys.stderr.write(
"applying %r" % c)
1716 c.__apply_configuration__()
1719 log.info(
"skipping configuration of %s", c.name())
1720 if hasattr(c,
"__detach_used__"):
1723 confUsers = newConfUsers
1727 "Detected loop in the ConfigurableUser "
1728 " dependencies: %r" % [c.name()
for c
in confUsers]
1732 unknown = set(Configurable.allConfigurables)
1736 log.debug(
"new configurable created automatically: %s", k)
1738 Configurable.allConfigurables[k].
properties()
1742 for action
in postConfigActions:
1748 Function to select all and only the configurables that have to be used in
1749 GaudiPython.AppMgr constructor.
1750 This is needed because in Athena the implementation have to be different (the
1751 configuration is used in a different moment).
1755 for k, v
in Configurable.allConfigurables.items()
1756 if v.getGaudiType() !=
"User"
1762 Clean up all configurations and configurables.
1764 for c
in Configurable.allConfigurables.values():
1765 c.__class__.configurables.clear()
1766 Configurable.allConfigurables.clear()
1769 ConfigurableGeneric.configurables.clear()
1773 from .ProcessJobOptions
import _included_files
1775 for file
in _included_files:
1776 dirname, basname = os.path.split(file)
1777 basname, ext = os.path.splitext(basname)
1778 if basname
in sys.modules:
1779 del sys.modules[basname]
1780 _included_files.clear()
1789 return self.
stack[-1]
1798 name = prefix + str(cnt)
1799 while name
in allConfigurables:
1801 name = prefix + str(cnt)
1805 from Configurables
import Gaudi__Sequencer
1811 if visitee
in (CFTrue, CFFalse):
1812 stack.append(self.
_newSeq(Invert=visitee
is CFFalse))
1813 elif isinstance(visitee, (ControlFlowLeaf, ConfigurableAlgorithm)):
1814 stack.append(visitee)
1815 elif isinstance(visitee, (OrNode, AndNode, OrderedNode)):
1820 ModeOR=isinstance(visitee, OrNode),
1821 ShortCircuit=
not isinstance(visitee, OrderedNode),
1824 elif isinstance(visitee, ignore):
1825 if hasattr(stack[-1],
"IgnoreFilterPassed"):
1826 stack[-1].IgnoreFilterPassed =
True
1829 self.
_newSeq(Members=[stack.pop()], IgnoreFilterPassed=
True)
1831 elif isinstance(visitee, InvertNode):
1832 if hasattr(stack[-1],
"Invert"):
1833 stack[-1].Invert =
True
1835 stack.append(self.
_newSeq(Members=[stack.pop()], Invert=
True))
1840 Convert a control flow expression to nested GaudiSequencers.
1842 if not isinstance(expression, ControlFlowNode):
1844 "ControlFlowNode instance expected, got %s" %
type(expression).__name__
1847 expression.visitNode(visitor)
1848 return visitor.sequence
1853 Helper class to use a ControlFlowNode as an algorithm configurable
1860 if name
in Configurable.allConfigurables:
1861 instance = Configurable.allConfigurables[name]
1862 assert type(instance)
is cls, (
1863 "trying to reuse {0!r} as name of a {1} instance while it"
1865 "already used for an instance of {2}"
1866 ).
format(name, cls.__name__,
type(instance).__name__)
1869 instance = super(SuperAlgorithm, cls).
__new__(cls)
1870 Configurable.allConfigurables[name] = instance
1877 setattr(self, key, kwargs[key])
1902 Instantiate and algorithm of type 'typ' with a name suitable for use
1903 inside a SuperAlgorithm.
1905 name =
"{0}_{1}".
format(self.
name, kwargs.pop(
"name", typ.getType()))
1906 return typ(name, **kwargs)
1909 raise NotImplementedError()
1919 super(SuperAlgorithm, self).
__setattr__(name, value)
1920 if name
in (
"_name",
"graph"):
1924 class PropSetter(object):
1925 def enter(self, node):
1927 setattr(node, name, value)
1928 except (ValueError, AttributeError):
1932 def leave(self, node):
1935 self._visitSubNodes(PropSetter())