Skip to content

Commit

Permalink
Merge branch 'UmanShahzad-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
caesar0301 committed Mar 27, 2017
2 parents c063a7b + 4d79bc0 commit ea2f6a8
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
13 changes: 12 additions & 1 deletion tests/test_treelib.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from io import BytesIO
import unittest
from treelib import Tree, Node
from treelib.tree import NodeIDAbsentError
from treelib.tree import NodeIDAbsentError, LoopError

def encode(value):
if sys.version_info[0] == 2:
Expand Down Expand Up @@ -367,6 +367,17 @@ def test_filter_nodes(self):
self.assertEqual(tuple(new_tree.filter_nodes(lambda n: not n.is_root())), (nodes[1],))
self.assertTrue(set(new_tree.filter_nodes(lambda n: True)), set(nodes))

def test_loop(self):
tree = Tree()
tree.create_node('a', 'a')
tree.create_node('b', 'b', parent='a')
tree.create_node('c', 'c', parent='b')
tree.create_node('d', 'd', parent='c')
try:
tree.move_node('b', 'd')
except LoopError, e:
pass

def suite():
suites = [NodeCase, TreeCase]
suite = unittest.TestSuite()
Expand Down
6 changes: 3 additions & 3 deletions treelib/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def bpointer(self, nid):
if nid is not None:
self._bpointer = nid
else:
# print("WARNNING: the bpointer of node %s " \
# print("WARNING: the bpointer of node %s " \
# "is set to None" % self._identifier)
self._bpointer = None

Expand Down Expand Up @@ -93,7 +93,7 @@ def identifier(self):
def identifier(self, value):
"""Set the value of `_identifier`."""
if value is None:
print("WARNNING: node ID can not be None")
print("WARNING: node ID can not be None")
else:
self._set_identifier(value)

Expand Down Expand Up @@ -133,7 +133,7 @@ def update_fpointer(self, nid, mode=ADD):
if nid in self._fpointer:
self._fpointer.remove(nid)
elif mode is self.INSERT: # deprecate to ADD mode
print("WARNNING: INSERT is deprecated to ADD mode")
print("WARNING: INSERT is deprecated to ADD mode")
self.update_fpointer(nid)

def __repr__(self):
Expand Down
24 changes: 24 additions & 0 deletions treelib/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ class NodeIDAbsentError(Exception):
"""Exception throwed if a node's identifier is unknown"""
pass


class NodePropertyAbsentError(Exception):
"""Exception throwed if a node's data property is not specified"""
pass


class MultipleRootError(Exception):
"""Exception throwed if more than one root exists in a tree."""
pass
Expand All @@ -52,6 +54,15 @@ class LinkPastRootNodeError(Exception):
class InvalidLevelNumber(Exception):
pass


class LoopError(Exception):
"""
Exception thrown if trying to move node B to node A's position
while A is B's ancestor.
"""
pass


def python_2_unicode_compatible(klass):
"""
(slightly modified from :
Expand Down Expand Up @@ -463,12 +474,25 @@ def move_node(self, source, destination):
"""
if not self.contains(source) or not self.contains(destination):
raise NodeIDAbsentError
elif self.is_ancestor(source, destination):
raise LoopError

parent = self[source].bpointer
self.__update_fpointer(parent, source, Node.DELETE)
self.__update_fpointer(destination, source, Node.ADD)
self.__update_bpointer(source, destination)

def is_ancestor(self, ancestor, grandchild):
parent = self[grandchild].bpointer
child = grandchild
while parent is not None:
if parent == ancestor:
return True
else:
child = self[child].bpointer
parent = self[child].bpointer
return False

@property
def nodes(self):
"""Return a dict form of nodes in a tree: {id: node_instance}"""
Expand Down

0 comments on commit ea2f6a8

Please sign in to comment.