class Foo(HasTraits): t = This()
class Bar(Foo): t = This()
class B(A): tt = This() ttt = This()
class A(HasTraits): t = This() tt = This()
class Tree(HasTraits): value = Unicode() leaves = List(This())
class Component(HasTraitlets): __metaclass__ = MetaComponent # Traitlets are fun! config = Instance(Config, (), {}) parent = This() root = This() created = None def __init__(self, parent, name=None, config=None): """Create a component given a parent and possibly and name and config. Parameters ---------- parent : Component subclass The parent in the component graph. The parent is used to get the root of the component graph. name : str The unique name of the component. If empty, then a unique one will be autogenerated. config : Config If this is empty, self.config = parent.config, otherwise self.config = config and root.config is ignored. This argument should only be used to *override* the automatic inheritance of parent.config. If a caller wants to modify parent.config (not override), the caller should make a copy and change attributes and then pass the copy to this argument. Notes ----- Subclasses of Component must call the :meth:`__init__` method of :class:`Component` *before* doing anything else and using :func:`super`:: class MyComponent(Component): def __init__(self, parent, name=None, config=None): super(MyComponent, self).__init__(parent, name, config) # Then any other code you need to finish initialization. This ensures that the :attr:`parent`, :attr:`name` and :attr:`config` attributes are handled properly. """ super(Component, self).__init__() self._children = [] if name is None: self.name = ComponentNameGenerator() else: self.name = name self.root = self # This is the default, it is set when parent is set self.parent = parent if config is not None: self.config = config # We used to deepcopy, but for now we are trying to just save # by reference. This *could* have side effects as all components # will share config. # self.config = deepcopy(config) else: if self.parent is not None: self.config = self.parent.config # We used to deepcopy, but for now we are trying to just save # by reference. This *could* have side effects as all components # will share config. # self.config = deepcopy(self.parent.config) self.created = datetime.datetime.now() #------------------------------------------------------------------------- # Static traitlet notifiations #------------------------------------------------------------------------- def _parent_changed(self, name, old, new): if old is not None: old._remove_child(self) if new is not None: new._add_child(self) if new is None: self.root = self else: self.root = new.root def _root_changed(self, name, old, new): if self.parent is None: if not (new is self): raise ComponentError("Root not self, but parent is None.") else: if not self.parent.root is new: raise ComponentError("Error in setting the root attribute: " "root != parent.root") def _config_changed(self, name, old, new): """Update all the class traits having ``config=True`` as metadata. For any class traitlet with a ``config`` metadata attribute that is ``True``, we update the traitlet with the value of the corresponding config entry. """ # Get all traitlets with a config metadata entry that is True traitlets = self.traitlets(config=True) # We auto-load config section for this class as well as any parent # classes that are Component subclasses. This starts with Component # and works down the mro loading the config for each section. section_names = [cls.__name__ for cls in \ reversed(self.__class__.__mro__) if issubclass(cls, Component) and issubclass(self.__class__, cls)] for sname in section_names: # Don't do a blind getattr as that would cause the config to # dynamically create the section with name self.__class__.__name__. if new._has_section(sname): my_config = new[sname] for k, v in traitlets.items(): try: config_value = my_config[k] except KeyError: pass else: # print "Setting %s.%s from %s.%s=%r" % \ # (self.__class__.__name__,k,sname,k,config_value) setattr(self, k, config_value) @property def children(self): """A list of all my child components.""" return self._children def _remove_child(self, child): """A private method for removing children components.""" if child in self._children: index = self._children.index(child) del self._children[index] def _add_child(self, child): """A private method for adding children components.""" if child not in self._children: self._children.append(child) def __repr__(self): return "<%s('%s')>" % (self.__class__.__name__, self.name)
class Foo(HasTraitlets): this = This()