def __init__(self): """ Creates MainTree which wraps and a main view without filters """ self.__tree = MainTree() self.__fbank = FiltersBank(self.__tree) self.__views = {} self.__viewscount = {} self.__views['main'] = ViewTree(self, self.__tree, self.__fbank, static=True)
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)
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)
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)
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