Example #1
0
 class Foo(HasTraits):
     t = This()
Example #2
0
 class Bar(Foo):
     t = This()
Example #3
0
 class B(A):
     tt = This()
     ttt = This()
Example #4
0
 class A(HasTraits):
     t = This()
     tt = This()
Example #5
0
 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)
Example #7
0
 class Foo(HasTraitlets):
     this = This()