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 type(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:
498 if attr
in self._properties:
499 if isinstance(self._properties[attr].__get__(self), DataHandle):
500 return self._properties[attr].__get__(self)
503 if c.getName() == attr:
506 raise AttributeError(
507 "'%s' object has no attribute '%s'" % (self.__class__, attr)
513 "%s: Configuration cannot be modified after the ApplicationMgr has been started."
518 except AttributeError:
519 raise AttributeError(
520 "Configurable '%s' does not have property '%s'."
521 % (self.__class__.__name__, name)
528 prop = self._properties[attr]
529 prop.__delete__(self)
530 prop.__set__(self, prop.default)
540 if c.getName() == attr:
545 del self.__dict__[attr]
546 except (AttributeError, KeyError):
553 __nonzero__ = __bool__
556 if type(items) != list
and type(items) != tuple:
566 return copy.deepcopy(child)
580 if hasattr(cc,
"setParent")
and parent:
583 except RuntimeError
as e:
585 log.error(str(e) +
"%s", error_explanation)
586 ccbd = cc.configurables[cc.getJobOptName()]
589 for proxy
in self._properties.values():
590 if cc
in proxy.history:
591 proxy.__set__(ccbd, proxy.__get__(cc))
604 log.error(
"children() is deprecated, use getChildren() instead for consistency")
606 "getChildren() returns a copy; to add a child, use 'parent += child'%s",
612 """Get all (private) configurable children, both explicit ones (added with +=)
613 and the ones in the private GaudiHandle properties"""
616 for proxy
in self._properties.values():
618 c = proxy.__get__(self)
619 except AttributeError:
622 if isinstance(c, Configurable)
and not c.isPublic():
624 elif isinstance(c, GaudiHandle):
626 conf = c.configurable
627 except AttributeError:
630 if not conf.isPublic():
632 elif isinstance(c, GaudiHandleArray):
636 if isinstance(ci, Configurable):
640 conf = ci.configurable
641 except AttributeError:
653 elems.append(c.getFullName())
658 if not hasattr(self,
"_initok")
or not self.
_initok:
661 "Configurable.__init__ not called in %s override"
662 % self.__class__.__name__
677 handle = self.getHandle()
679 log.debug(
"no handle for %s: not transporting properties", self.
_name)
683 for name
in self._properties.
keys():
684 if hasattr(self, name):
685 setattr(handle, name, getattr(self, name))
692 for name, proxy
in self._properties.
items():
694 props[name] = proxy.__get__(self)
695 except AttributeError:
696 props[name] = Configurable.propertyNoValue
701 """Get all properties with their description string as { name : (value, desc) }."""
703 for name, proxy
in self._properties.
items():
705 props[name] = (proxy.__get__(self), proxy.__doc__)
706 except AttributeError:
707 props[name] = (Configurable.propertyNoValue, proxy.__doc__)
712 for name, proxy
in self._properties.
items():
714 value = proxy.__get__(self)
715 if hasattr(value,
"getFullName"):
716 value = value.getFullName()
717 elif type(value)
in [list, tuple]:
720 if hasattr(i,
"getFullName"):
721 new_value.append(i.getFullName())
724 value =
type(value)(new_value)
725 elif type(value)
is dict:
728 if hasattr(value[i],
"getFullName"):
731 new_value[i] = value[i]
750 for k, v
in cls._properties.
items():
751 if k
not in c.__dict__
and hasattr(v,
"default"):
752 c.__dict__[k] = v.default
765 if name
in c.__dict__:
766 return c.__dict__[name]
770 v = cls._properties[name]
771 if hasattr(v,
"default"):
779 """Returns the value of the given property."""
780 if hasattr(self, name):
781 return getattr(self, name)
786 """Set the value of a given property"""
787 return setattr(self, name, value)
790 """Tell if the property 'name' has been set or not.
792 Because of a problem with list and dictionary properties, in those cases
793 if the value is equal to the default, the property is considered as not
796 if not hasattr(self, name):
799 if isinstance(default, (list, dict, DataHandle)):
800 value = getattr(self, name)
801 return value != default
822 "jobOptName() is deprecated, use getJobOptName() instead for consistency%s",
837 if log.isEnabledFor(logging.DEBUG):
845 def clone(self, name=None, **kwargs):
847 if hasattr(self,
"DefaultedName"):
848 name = self.DefaultedName
850 name = self.getType()
852 newconf = Configurable.__new__(self.__class__, name)
853 self.__class__.
__init__(newconf, name)
855 for proxy
in self._properties.values():
857 value = proxy.__get__(self)
858 if type(value)
in [str, list, dict, tuple]:
860 value =
type(value)(value)
861 proxy.__set__(newconf, value)
862 except AttributeError:
865 for c
in self.__children:
868 for n, t
in self.__tools.
items():
869 newconf.addTool(t, n)
871 for name, value
in kwargs.items():
872 setattr(newconf, name, value)
878 dot = fullname.find(
".")
880 parentname = fullname[:dot]
881 longname = fullname[dot + 1 :]
885 dot = longname.find(
".")
887 name = longname[:dot]
890 return parentname, name, longname
893 if isclass(tool)
and issubclass(tool, ConfigurableAlgTool):
897 elif isinstance(tool, ConfigurableAlgTool):
899 name = tool.splitName()[1]
900 priv_tool = tool.clone(self.
getName() +
"." + name)
903 classname = tool.__name__
905 classname =
type(tool).__name__
907 "addTool requires AlgTool configurable. Got %s type" % classname
912 setattr(self, name, self.
__tools[name])
928 handle = __main__.Service(svc)
933 if hasattr(self,
"configure" + svc):
934 eval(
"self.configure" + svc +
"( handle )")
937 dlls = self.getDlls()
940 elif isinstance(dlls, types.StringType):
943 from __main__
import theApp
945 dlls = filter(
lambda d: d
not in theApp.Dlls, dlls)
958 preLen = Configurable.printHeaderPre
960 Configurable.printHeaderWidth - preLen - 3 - len(title)
962 postLen =
max(preLen, postLen)
963 return indentStr +
"/%s %s %s" % (preLen *
"*", title, postLen *
"*")
967 preLen = Configurable.printHeaderPre
969 Configurable.printHeaderWidth - preLen - 12 - len(title)
971 postLen =
max(preLen, postLen)
972 return indentStr +
"\\%s (End of %s) %s" % (preLen *
"-", title, postLen *
"-")
975 return "{0}({1!r})".
format(self.__class__.__name__, self.
name())
977 def __str__(self, indent=0, headerLastIndentUnit=indentUnit):
979 indentStr = indent * Configurable.indentUnit
984 headerIndent = (indent - 1) * Configurable.indentUnit + headerLastIndentUnit
987 rep = Configurable._printHeader(headerIndent, title)
993 rep += indentStr +
"|-<no properties>" + os.linesep
997 for p
in props.keys():
998 nameWidth =
max(nameWidth, len(p))
999 for p, v
in props.items():
1001 prefix = indentStr +
"|-%-*s" % (nameWidth, p)
1003 if log.isEnabledFor(logging.DEBUG):
1004 if v != Configurable.propertyNoValue:
1005 address =
" @%11s" %
hex(id(v))
1010 default = defs.get(p)
1011 if v == Configurable.propertyNoValue:
1013 strVal = repr(default)
1017 if hasattr(v,
"getGaudiHandle"):
1018 vv = v.getGaudiHandle()
1021 if isinstance(vv, (GaudiHandle, GaudiHandleArray, DataHandle)):
1024 if hasattr(default,
"toStringProperty"):
1025 strDef = repr(default.toStringProperty())
1027 strDef = repr(default)
1028 if strDef == repr(vv.toStringProperty()):
1032 strDef = repr(default)
1034 line = prefix +
" = " + strVal
1036 if strDef
is not None:
1038 if len(line) + len(strDef) > Configurable.printHeaderWidth:
1043 + (len(prefix) - len(indentStr) - 3) *
" "
1045 line +=
" (default: %s)" % (strDef,)
1047 rep += line + os.linesep
1059 rep += cfg.__str__(indent + 1,
"|=") + os.linesep
1062 rep += Configurable._printFooter(indentStr, title)
1067 Return True is the instance can be "applied".
1068 Always False for plain Configurable instances
1069 (i.e. not ConfigurableUser).
1085 object.__setattr__(obj, self.
__name__, value)
1092 Configurable.__init__(self, name)
1101 return "GenericComponent"
1112 super(ConfigurableGeneric, self).
__setattr__(name, value)
1116 if isinstance(value, Configurable):
1117 self.__dict__[name] = value
1121 if name
not in self._properties:
1123 self._properties[name].__set__(self, value)
1137 "AuditAlgorithms": 0,
1138 "AuditInitialize": 0,
1139 "AuditReinitialize": 0,
1145 super(ConfigurableAlgorithm, self).
__init__(name)
1168 elif rhs
is CFFalse:
1194 return repr(self) == repr(other)
1197 """Return a unique identifier for this object.
1199 As we use the `repr` of this object to check for equality, we use it
1200 here to define uniqueness.
1203 return hash((repr(self),))
1211 "AuditInitialize": 0,
1220 if isinstance(child, ConfigurableAlgTool)
and not child.isPublic():
1221 return copy.deepcopy(child)
1226 return iService(self.
_name)
1245 "AuditInitialize": 0,
1250 super(ConfigurableAlgTool, self).
__init__(name)
1251 if "." not in self.
_name:
1255 name = name[name.find(
"/") + 1 :]
1279 return pop + Configurable.getPrintTitle(self)
1288 if isinstance(c, ConfigurableAlgTool):
1289 c.setParent(parentName)
1293 name = name[name.rfind(
".") + 1 :]
1314 return parent ==
"ToolSvc"
1325 name = name[name.rfind(
".") + 1 :]
1326 return str(self.
getType() +
"/" + name)
1333 __slots__ = {
"_jobOptName": 0,
"OutputLevel": 0,
"Enable": 1}
1336 super(ConfigurableAuditor, self).
__init__(name)
1338 name = name[name.find(
"/") + 1 :]
1362 "__used_instances__": [],
1374 __used_configurables__ = []
1377 __queried_configurables__ = []
1379 def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs):
1380 super(ConfigurableUser, self).
__init__(name)
1381 for n, v
in kwargs.items():
1399 if type(used)
is tuple:
1400 used, used_name = used
1404 if type(used)
is str:
1405 used_class = confDbGetConfigurable(used)
1410 inst = used_class(name=used_name, _enabled=
False)
1411 except AttributeError:
1415 inst = used_class(name=used_name)
1419 if type(queried)
is str:
1420 queried = confDbGetConfigurable(queried)
1421 inst = queried(_enabled=
False)
1422 except AttributeError:
1428 Declare that we are going to modify the Configurable 'other' in our
1429 __apply_configuration__.
1432 if hasattr(other,
"__users__"):
1433 other.__users__.append(self)
1437 Declare that we are going to retrieve property values from the
1438 ConfigurableUser 'other' in our __apply_configuration__.
1440 if not isinstance(other, ConfigurableUser):
1442 "'%s': Cannot make passive use of '%s', it is not a ConfigurableUser"
1443 % (self.
name(), other.name())
1445 other.__addActiveUseOf(self)
1459 Remove this ConfigurableUser instance from the users list of the used
1463 if hasattr(used,
"__users__"):
1464 used.__users__.remove(self)
1468 Propagate the property 'name' (if set) to other configurables (if possible).
1471 propagate to all the entries in __used_configurables__
1472 a configurable instance:
1473 propagate only to it
1474 list of configurable instances:
1475 propagate to all of them.
1479 - if the local property is set, the other property will be overwritten
1480 - local property not set and other set => keep other
1481 - local property not set and other not set => overwrite the default for
1482 ConfigurableUser instances and set the property for Configurables
1487 elif type(others)
not in [list, tuple]:
1493 for other
in [o
for o
in others
if name
in o.__slots__]:
1496 if other.isPropertySet(name):
1498 "Property '%(prop)s' is set in both '%(self)s' and '%(other)s', using '%(self)s.%(prop)s'"
1499 % {
"self": self.
name(),
"other": other.name(),
"prop": name}
1501 other.setProp(name, value)
1503 elif not other.isPropertySet(name):
1504 if isinstance(other, ConfigurableUser):
1505 otherType =
type(other._properties[name].getDefault())
1506 other._properties[name].setDefault(value)
1507 if otherType
in [list, dict]:
1510 other.setProp(name, otherType(value))
1512 other.setProp(name, value)
1517 Call propagateProperty for each property listed in 'names'.
1518 If 'names' is None, all the properties are propagated.
1522 names = [p
for p
in self.
__slots__ if not p.startswith(
"_")]
1528 Function to be overridden to convert the high level configuration into a
1530 The default implementation calls applyConf, which is the method defined
1531 in some ConfigurableUser implementations.
1537 Function to be overridden to convert the high level configuration into a
1544 Function used to define the name of the private instance of a given class
1546 This method is used when the __used_configurables_property__ declares the
1547 need of a private used configurable without specifying the name.
1549 if type(cls)
is str:
1552 clName = cls.__name__
1553 return "%s_%s" % (self.name(), clName)
1557 Return the used instance with a given name.
1560 if i.name() == name:
1561 if hasattr(i,
"_enabled"):
1566 raise KeyError(name)
1570 Return True is the instance can be "applied".
1576 postConfigActions = []
1581 Add a new callable ('function') to the list of post-configuration actions.
1582 If the callable is already in the list, it is moved to the end of the list.
1583 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1586 postConfigActions.remove(function)
1589 postConfigActions.append(function)
1594 Remove a callable from the list of post-config actions.
1595 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1597 postConfigActions.remove(function)
1600 _appliedConfigurableUsers_ =
False
1605 Call the apply method of all the ConfigurableUser instances respecting the
1606 dependencies. First the C.U.s that are not used by anybody, then the used
1607 ones, when they are not used anymore.
1610 global _appliedConfigurableUsers_, postConfigActions
1611 if _appliedConfigurableUsers_:
1613 _appliedConfigurableUsers_ =
True
1615 def applicableConfUsers():
1617 Generator returning all the configurables that can be applied in the
1618 order in which they can be applied.
1633 for c
in Configurable.allConfigurables.values()
1636 except StopIteration:
1639 debugApplyOrder =
"GAUDI_DUBUG_CONF_USER" in os.environ
1640 for c
in applicableConfUsers():
1642 log.info(
"applying configuration of %s", c.name())
1644 sys.stderr.write(
"applying %r" % c)
1645 c.__apply_configuration__()
1648 log.info(
"skipping configuration of %s", c.name())
1650 if hasattr(c,
"__detach_used__"):
1657 for c
in Configurable.allConfigurables.values()
1658 if hasattr(c,
"__apply_configuration__")
and c._enabled
and not c._applied
1663 "Detected loop in the ConfigurableUser"
1664 " dependencies: %r" % [c.name()
for c
in leftConfUsers]
1668 unknown = set(Configurable.allConfigurables)
1672 log.debug(
"new configurable created automatically: %s", k)
1674 Configurable.allConfigurables[k].
properties()
1678 for action
in postConfigActions:
1684 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1685 backward compatibility for configurations that where relying (implicitly) on
1686 bug #103803, or on a specific (non guaranteed) order of execution.
1688 @see applyConfigurableUsers()
1691 global _appliedConfigurableUsers_, postConfigActions
1692 if _appliedConfigurableUsers_:
1694 _appliedConfigurableUsers_ =
True
1696 debugApplyOrder =
"GAUDI_DUBUG_CONF_USER" in os.environ
1699 for c
in Configurable.allConfigurables.values()
1700 if hasattr(c,
"__apply_configuration__")
1703 while applied
and confUsers:
1707 if hasattr(c,
"__users__")
and c.__users__:
1708 newConfUsers.append(c)
1713 enabled = (
not hasattr(c,
"_enabled"))
or c._enabled
1715 log.info(
"applying configuration of %s", c.name())
1717 sys.stderr.write(
"applying %r" % c)
1718 c.__apply_configuration__()
1721 log.info(
"skipping configuration of %s", c.name())
1722 if hasattr(c,
"__detach_used__"):
1725 confUsers = newConfUsers
1729 "Detected loop in the ConfigurableUser "
1730 " dependencies: %r" % [c.name()
for c
in confUsers]
1734 unknown = set(Configurable.allConfigurables)
1738 log.debug(
"new configurable created automatically: %s", k)
1740 Configurable.allConfigurables[k].
properties()
1744 for action
in postConfigActions:
1750 Function to select all and only the configurables that have to be used in
1751 GaudiPython.AppMgr constructor.
1752 This is needed because in Athena the implementation have to be different (the
1753 configuration is used in a different moment).
1757 for k, v
in Configurable.allConfigurables.items()
1758 if v.getGaudiType() !=
"User"
1764 Clean up all configurations and configurables.
1766 for c
in Configurable.allConfigurables.values():
1767 c.__class__.configurables.clear()
1768 Configurable.allConfigurables.clear()
1771 ConfigurableGeneric.configurables.clear()
1775 from .ProcessJobOptions
import _included_files
1777 for file
in _included_files:
1778 dirname, basname = os.path.split(file)
1779 basname, ext = os.path.splitext(basname)
1780 if basname
in sys.modules:
1781 del sys.modules[basname]
1782 _included_files.clear()
1791 return self.
stack[-1]
1800 name = prefix + str(cnt)
1801 while name
in allConfigurables:
1803 name = prefix + str(cnt)
1807 from Configurables
import GaudiSequencer
1813 if visitee
in (CFTrue, CFFalse):
1814 stack.append(self.
_newSeq(Invert=visitee
is CFFalse))
1815 elif isinstance(visitee, (ControlFlowLeaf, ConfigurableAlgorithm)):
1816 stack.append(visitee)
1817 elif isinstance(visitee, (OrNode, AndNode, OrderedNode)):
1822 ModeOR=isinstance(visitee, OrNode),
1823 ShortCircuit=
not isinstance(visitee, OrderedNode),
1827 elif isinstance(visitee, ignore):
1828 if hasattr(stack[-1],
"IgnoreFilterPassed"):
1829 stack[-1].IgnoreFilterPassed =
True
1832 self.
_newSeq(Members=[stack.pop()], IgnoreFilterPassed=
True)
1834 elif isinstance(visitee, InvertNode):
1835 if hasattr(stack[-1],
"Invert"):
1836 stack[-1].Invert =
True
1838 stack.append(self.
_newSeq(Members=[stack.pop()], Invert=
True))
1843 Convert a control flow expression to nested GaudiSequencers.
1845 if not isinstance(expression, ControlFlowNode):
1847 "ControlFlowNode instance expected, got %s" %
type(expression).__name__
1850 expression.visitNode(visitor)
1851 return visitor.sequence
1856 Helper class to use a ControlFlowNode as an algorithm configurable
1863 if name
in Configurable.allConfigurables:
1864 instance = Configurable.allConfigurables[name]
1865 assert type(instance)
is cls, (
1866 "trying to reuse {0!r} as name of a {1} instance while it"
1868 "already used for an instance of {2}"
1869 ).
format(name, cls.__name__,
type(instance).__name__)
1872 instance = super(SuperAlgorithm, cls).
__new__(cls)
1873 Configurable.allConfigurables[name] = instance
1880 setattr(self, key, kwargs[key])
1905 Instantiate and algorithm of type 'typ' with a name suitable for use
1906 inside a SuperAlgorithm.
1908 name =
"{0}_{1}".
format(self.
name, kwargs.pop(
"name", typ.getType()))
1909 return typ(name, **kwargs)
1912 raise NotImplementedError()
1922 super(SuperAlgorithm, self).
__setattr__(name, value)
1923 if name
in (
"_name",
"graph"):
1927 class PropSetter(object):
1928 def enter(self, node):
1930 setattr(node, name, value)
1931 except (ValueError, AttributeError):
1935 def leave(self, node):
1938 self._visitSubNodes(PropSetter())