Example #1
0
class Tree(object):
    """
    A thin wrapper to MainTree that adds filtering capabilities.
    It also provides a few methods to operate complex operation on the
    MainTree (e.g, move_node)
    """
    def __init__(self):
        """
        Creates MainTree which wraps and a main view without filters
        """
        self.__tree = MainTree()
        self.__fbank = FiltersBank(self.__tree)
        self.__views = {}
        self.__views['main'] = ViewTree(self,
                                        self.__tree,
                                        self.__fbank,
                                        static=True)

##### HANDLE NODES ############################################################

    def get_node(self, node_id):
        """
        Returns the object of node.
        If the node does not exists, a ValueError is raised.
        """
        return self.__tree.get_node(node_id)

    def has_node(self, node_id):
        """ Does the node exists in this tree? """
        return self.__tree.has_node(node_id)

    def add_node(self, node, parent_id=None, priority="low"):
        """
        Add a node to tree. If parent_id is set, put the node as a child of
        this node, otherwise put it as a child of the root node.
        """
        self.__tree.add_node(node, parent_id, priority)

    def del_node(self, node_id, recursive=False):
        """
        Remove node from tree and return whether it was successful or not.
        """
        return self.__tree.remove_node(node_id, recursive)

    def refresh_node(self, node_id, priority="low"):
        """
        Send a request for updating the node
        """
        self.__tree.modify_node(node_id, priority)

    def refresh_all(self):
        """
        Refresh all nodes
        """
        self.__tree.refresh_all()

    def move_node(self, node_id, new_parent_id=None):
        """
        Move the node to a new parent (dismissing all other parents)
        use pid None to move it to the root
        """
        if self.has_node(node_id):
            node = self.get_node(node_id)
            node.set_parent(new_parent_id)
            toreturn = True
        else:
            toreturn = False

        return toreturn

    def add_parent(self, node_id, new_parent_id=None):
        """
        Add the node to a new parent.

        Return whether operation was successful or not. If the node does not
        exists, return False
        """

        if self.has_node(node_id):
            node = self.get_node(node_id)
            return node.add_parent(new_parent_id)
        else:
            return False

##### VIEWS ###################################################################

    def get_main_view(self):
        """
        Return the special view "main" which is without any filters on it.
        """
        return self.__views['main']

    def get_viewtree(self, name=None, refresh=True):
        """
        :refresh: When False the view is not initialized.
                  This is useful as an optimization if you plan to apply a
                  filter.

        :returns: a viewtree by the name:

                  - a viewtree with that name exists => return it
                  - a viewtree with that name does not exist => create a new
                    one and return it
                  - name is None => create an anonymous tree
                    (do not remember it)
        """
        if name is not None and self.__views.has_key(name):
            view_tree = self.__views[name]
        else:
            view_tree = ViewTree(self,
                                 self.__tree,
                                 self.__fbank,
                                 name=name,
                                 refresh=refresh)
            if name is not None:
                self.__views[name] = view_tree
        return view_tree

##### FILTERS ##################################################################

    def list_filters(self):
        """ Return a list of all available filters by name """
        return self.__fbank.list_filters()

    def add_filter(self, filter_name, filter_func, parameters=None):
        """ Adds a filter to the filter bank.

        :filter_name: name to give to the filter
        :filter_func: the function that will filter the nodes
        :parameters: some default parameters fot that filter

        :returns: - True if the filter was added
                  - False if the *filter_name* was already in the bank
        """
        return self.__fbank.add_filter(filter_name, filter_func, parameters)

    def remove_filter(self, filter_name):
        """ Remove a filter from the bank. Only custom filters that were 
        added here can be removed. Return False if the filter was not removed.
        """
        return self.__fbank.remove_filter(filter_name)
Example #2
0
class Tree:
    """ A thin wrapper to MainTree that adds filtering capabilities.
    It also provides a few methods to operate complex operation on the
    MainTree (e.g, move_node) """ 

    def __init__(self):
        """ Creates MainTree which wraps and a main view without filters """
        self.__tree = MainTree()
        self.__fbank = FiltersBank(self.__tree)
        self.__views = {}
        self.__views['main'] = ViewTree(self, self.__tree, self.__fbank, static=True)

##### HANDLE NODES ############################################################

    def get_node(self, node_id):
        """ Returns the object of node.
        If the node does not exists, a ValueError is raised. """
        return self.__tree.get_node(node_id)

    def has_node(self, node_id):
        """ Does the node exists in this tree? """
        return self.__tree.has_node(node_id)

    def add_node(self, node, parent_id=None, priority="low"):
        """ Add a node to tree. If parent_id is set, put the node as a child of
        this node, otherwise put it as a child of the root node."""
        self.__tree.add_node(node, parent_id, priority)

    def del_node(self, node_id, recursive=False):
        """ Remove node from tree and return whether it was successful or not """
        return self.__tree.remove_node(node_id, recursive)

    def refresh_node(self, node_id, priority="low"):
        """ Send a request for updating the node """
        self.__tree.modify_node(node_id, priority)

    def refresh_all(self):
        """ Refresh all nodes """
        self.__tree.refresh_all()

    def move_node(self, node_id, new_parent_id=None):
        """ Move the node to a new parent (dismissing all other parents)
        use pid None to move it to the root """
        if self.has_node(node_id):
            node = self.get_node(node_id)
            node.set_parent(new_parent_id)
            toreturn = True
        else:
            toreturn = False

        return toreturn


    def add_parent(self, node_id, new_parent_id=None):
        """ Add the node to a new parent. Return whether operation was
        successful or not. If the node does not exists, return False """

        if self.has_node(node_id):
            node = self.get_node(node_id)
            return node.add_parent(new_parent_id)
        else:
            return False

##### VIEWS ###################################################################
    def get_main_view(self):
        """ Return the special view "main" which is without any filters on it."""
        return self.__views['main']

    def get_viewtree(self, name=None, refresh=True):
        """ Returns a viewtree by the name:
          * a viewtree with that name exists => return it
          * a viewtree with that name does not exist => create a new one and return it
          * name is None => create an anonymous tree (do not remember it)

        If refresh is False, the view is not initialized. This is useful as
        an optimization if you plan to apply a filter.
        """

        if name is not None and self.__views.has_key(name):
            view_tree = self.__views[name]
        else:
            view_tree = ViewTree(self,self.__tree,self.__fbank, name = name, refresh = refresh)
            if name is not None:
                self.__views[name] = view_tree
        return view_tree

##### FILTERS ##################################################################
    def list_filters(self):
        """ Return a list of all available filters by name """
        return self.__fbank.list_filters()

    def add_filter(self, filter_name, filter_func, parameters=None):
        """ Adds a filter to the filter bank.

        @filter_name : name to give to the filter
        @filter_func : the function that will filter the nodes
        @parameters : some default parameters fot that filter
        Return True if the filter was added
        Return False if the filter_name was already in the bank
        """
        return self.__fbank.add_filter(filter_name, filter_func, parameters)

    def remove_filter(self,filter_name):
        """ Remove a filter from the bank. Only custom filters that were 
        added here can be removed. Return False if the filter was not removed.
        """
        return self.__fbank.remove_filter(filter_name)
Example #3
0
class TestFilteredTree(unittest.TestCase):
    def setUp(self):
        self.added_nodes = 0
        self.deleted_nodes = 0
        self.tree = MainTree()
        self.filtersbank = FiltersBank(self.tree)
        self.filtered_tree = FilteredTree(self.tree, self.filtersbank)
        self.tree.add_node(_Node(node_id="apple"))
        self.tree.add_node(_Node(node_id="google"))

        self.filtered_tree.set_callback('deleted', self.deleted)
        self.filtered_tree.set_callback('added', self.added)

    def search_filter(self, node, parameters):
        return node.get_id() == parameters['node_id']

    def true_filter(self, node):
        return True

    def test_refresh_every_time_with_parameters(self):
        self.filtersbank.add_filter("search_filter", self.search_filter)
        self.assertTrue(self.filtered_tree.is_displayed(node_id="apple"))
        self.assertTrue(self.filtered_tree.is_displayed(node_id="apple"))

        self.filtered_tree.apply_filter("search_filter",
                                        parameters={'node_id': 'apple'})
        self.assertTrue(self.filtered_tree.is_displayed(node_id="apple"))
        self.assertFalse(self.filtered_tree.is_displayed(node_id="google"))

        # Due to self.refilter() implementation, all nodes are deleted
        # at first and then only those satisfying the filter are added back.
        self.assertEqual(2, self.deleted_nodes)
        self.assertEqual(1, self.added_nodes)

        self.reset_counters()

        self.filtered_tree.apply_filter("search_filter",
                                        parameters={'node_id': 'google'})
        self.assertFalse(self.filtered_tree.is_displayed(node_id="apple"))
        self.assertTrue(self.filtered_tree.is_displayed(node_id="google"))

        self.assertEqual(1, self.deleted_nodes)
        self.assertEqual(1, self.added_nodes)

    def test_refresh_only_with_new_filter(self):
        self.filtersbank.add_filter("true_filter", self.true_filter)

        self.reset_counters()

        self.filtered_tree.apply_filter("true_filter")

        self.assertEqual(2, self.deleted_nodes)
        self.assertEqual(2, self.added_nodes)

        self.reset_counters()

        self.filtered_tree.apply_filter("true_filter")

        self.assertEqual(0, self.deleted_nodes)
        self.assertEqual(0, self.added_nodes)

    def added(self, node_id, path):
        self.added_nodes += 1

    def deleted(self, node_id, path):
        self.deleted_nodes += 1

    def reset_counters(self):
        self.added_nodes, self.deleted_nodes = 0, 0