def test_children_setter(): root = Node("root") s0 = Node("sub0") s1 = Node("sub0A") s0a = Node("sub0B") root.children = [s0, s1] s0.children = [s0a] eq_(root.descendants, (s0, s0a, s1)) with assert_raises( LoopError, "Cannot set parent. Node('/root/sub0') cannot be parent of itself." ): s0.children = [s0] # test whether tree is unchanged after LoopError eq_(root.descendants, (s0, s0a, s1)) with assert_raises( LoopError, "Cannot set parent. Node('/root/sub0') is parent of Node('/root/sub0/sub0B')." ): s0a.children = [s0] # test whether tree is unchanged after LoopError eq_(root.descendants, (s0, s0a, s1)) root.children = [s0, s1] s0.children = [s0a] s0a.children = [s1] eq_(root.descendants, (s0, s0a, s1))
def test_get(): """Get.""" top = at.Node("top", parent=None) sub0 = at.Node("sub0", parent=top) sub0sub0 = at.Node("sub0sub0", parent=sub0) sub0sub1 = at.Node("sub0sub1", parent=sub0) sub1 = at.Node("sub1", parent=top) r = at.Resolver('name') eq_(r.get(top, "sub0/sub0sub0"), sub0sub0) eq_(r.get(sub1, ".."), top) eq_(r.get(sub1, "../"), top) eq_(r.get(sub1, "../."), top) eq_(r.get(sub1, "../sub0/sub0sub1"), sub0sub1) eq_(r.get(sub1, "."), sub1) eq_(r.get(sub1, ""), sub1) with assert_raises( at.ChildResolverError, "Node('/top') has no child sub2. Children are: 'sub0', 'sub1'."): r.get(top, "sub2") eq_(r.get(sub0sub0, "/top"), top) eq_(r.get(sub0sub0, "/top/sub0"), sub0) with assert_raises(at.RootResolverError, "Cannot go above root node Node('/top')"): r.get(top, "..") with assert_raises(at.ResolverError, "root node missing. root is '/top'."): r.get(sub0sub0, "/") with assert_raises(at.ResolverError, "unknown root node '/bar'. root is '/top'."): r.get(sub0sub0, "/bar")
def test_readonly_pre(): """Read Only Use case, where Exceptions in _pre_{attach,detach} avoid modifications.""" class ReadonlyError(RuntimeError): pass class ReadonlyNode(Node): _is_readonly = False def _pre_attach(self, parent): if self._is_readonly: raise ReadonlyError() def _pre_detach(self, parent): if self._is_readonly: raise ReadonlyError() # construct and make readonly! root = ReadonlyNode("root") s0 = ReadonlyNode("sub0", parent=root) s0b = ReadonlyNode("sub0B", parent=s0) s0a = ReadonlyNode("sub0A", parent=s0) s1 = ReadonlyNode("sub1", parent=root) s1a = ReadonlyNode("sub1A", parent=s1) s1b = ReadonlyNode("sub1B", parent=s1) s1c = ReadonlyNode("sub1C", parent=s1) s1ca = ReadonlyNode("sub1Ca", parent=s1c) ReadonlyNode._is_readonly = True def check(): eq_(root.parent, None) eq_(root.children, tuple([s0, s1])) eq_(s0.parent, root) eq_(s0.children, tuple([s0b, s0a])) eq_(s0b.parent, s0) eq_(s0b.children, tuple()) eq_(s0a.parent, s0) eq_(s0a.children, tuple()) eq_(s1.parent, root) eq_(s1.children, tuple([s1a, s1b, s1c])) eq_(s1a.parent, s1) eq_(s1a.children, tuple()) eq_(s1b.parent, s1) eq_(s1b.children, tuple()) eq_(s1c.parent, s1) eq_(s1c.children, tuple([s1ca])) eq_(s1ca.parent, s1c) eq_(s1ca.children, tuple()) check() with assert_raises(ReadonlyError, ""): s1ca.parent = s0 check() with assert_raises(ReadonlyError, ""): s1ca.parent = None check() with assert_raises(ReadonlyError, ""): s0.children = [] check()
def test_tuple_as_children(): """Tuple as children.""" n = Node('foo') with assert_raises( TreeError, "Cannot add non-node object (0, 1, 2). It is not a subclass of 'NodeMixin'." ): n.children = [(0, 1, 2)]
def test_node_children_type(): root = Node("root") with assert_raises( TreeError, "Cannot add non-node object 'string'. It is not a subclass of 'NodeMixin'." ): root.children = ["string"]
def test_node_children_multiple(): root = Node("root") sub = Node("sub") with assert_raises( TreeError, "Cannot add node Node('/sub') multiple times as child."): root.children = [sub, sub]
def test_glob(): """Wildcard.""" top = at.Node("top", parent=None) sub0 = at.Node("sub0", parent=top) sub0sub0 = at.Node("sub0", parent=sub0) sub0sub1 = at.Node("sub1", parent=sub0) sub0sub1sub0 = at.Node("sub0", parent=sub0sub1) at.Node("sub1", parent=sub0sub1) sub1 = at.Node("sub1", parent=top) sub1sub0 = at.Node("sub0", parent=sub1) r = at.Resolver() eq_(r.glob(top, "sub0/sub0"), [sub0sub0]) eq_(r.glob(sub1, ".."), [top]) eq_(r.glob(sub1, "../"), [top]) eq_(r.glob(sub1, "../."), [top]) eq_(r.glob(sub1, "../././."), [top]) eq_(r.glob(sub1, ".././././sub0/.."), [top]) eq_(r.glob(sub1, "../sub0/sub1"), [sub0sub1]) eq_(r.glob(sub1, "."), [sub1]) eq_(r.glob(sub1, "./"), [sub1]) eq_(r.glob(sub1, ""), [sub1]) eq_(r.glob(sub1, "/top"), [top]) eq_(r.glob(sub1, "/*"), [top]) eq_(r.glob(top, "*/*/sub0"), [sub0sub1sub0]) eq_(r.glob(top, "sub0/sub?"), [sub0sub0, sub0sub1]) eq_(r.glob(sub1, ".././*"), [sub0, sub1]) eq_(r.glob(top, "*/*"), [sub0sub0, sub0sub1, sub1sub0]) eq_(r.glob(top, "*/sub0"), [sub0sub0, sub1sub0]) with assert_raises(at.RootResolverError, "Cannot go above root node Node('/top')"): r.glob(top, "..") with assert_raises(at.RootResolverError, "Cannot go above root node Node('/top')"): r.glob(sub1, ".././..") with assert_raises( at.ChildResolverError, "Node('/top/sub1') has no child sub1. Children are: 'sub0'."): r.glob(top, "sub1/sub1") with assert_raises(at.ResolverError, "unknown root node '/z*'. root is '/top'."): r.glob(sub1, "/z*")
def test_findall(): f = Node("f") b = Node("b", parent=f) a = Node("a", parent=b) d = Node("d", parent=b) c = Node("c", parent=d) e = Node("e", parent=d) eq_(findall(f, filter_=lambda node: node.name in ("a", "b")), (b, a)) eq_(findall(f, filter_=lambda node: d in node.path), (d, c, e)) with assert_raises(CountError, ( "Expecting at least 4 elements, but found 3. " "(Node('/f/b/d'), Node('/f/b/d/c'), Node('/f/b/d/e'))")): findall(f, filter_=lambda node: d in node.path, mincount=4) with assert_raises(CountError, ( "Expecting 2 elements at maximum, but found 3. " "(Node('/f/b/d'), Node('/f/b/d/c'), Node('/f/b/d/e'))")): findall(f, filter_=lambda node: d in node.path, maxcount=2)
def test_node_slots(): """__slots__ compatibility.""" class MyNode(NodeMixin): __slots__ = ('_name', ) def __init__(self, name): self._name = name n = MyNode('foo') with assert_raises(AttributeError, "'MyNode' object has no attribute 'bar'"): n.bar = 4
def test_findall_by_attr(): f = Node("f") b = Node("b", parent=f) Node("a", parent=b) d = Node("d", parent=b) Node("c", parent=d) Node("e", parent=d) eq_(findall_by_attr(f, "d"), (d, )) with assert_raises(CountError, ("Expecting at least 1 elements, but found 0.")): findall_by_attr(f, "z", mincount=1)
def test_get(): """Get.""" top = MyNode("top", parent=None) sub0 = MyNode("sub0", parent=top) sub0sub0 = MyNode("sub0sub0", parent=sub0) sub0sub1 = MyNode("sub0sub1", parent=sub0) sub1 = MyNode("sub1", parent=top) r = at.Resolver('name') eq_(r.get(top, "sub0|sub0sub0"), sub0sub0) eq_(r.get(sub1, ".."), top) eq_(r.get(sub1, "..|sub0|sub0sub1"), sub0sub1) eq_(r.get(sub1, "."), sub1) eq_(r.get(sub1, ""), sub1) with assert_raises(at.ChildResolverError, "MyNode('|top') has no child sub2. Children are: 'sub0', 'sub1'."): r.get(top, "sub2") eq_(r.get(sub0sub0, "|top"), top) eq_(r.get(sub0sub0, "|top|sub0"), sub0) with assert_raises(at.ResolverError, "root node missing. root is '|top'."): r.get(sub0sub0, "|") with assert_raises(at.ResolverError, "unknown root node '|bar'. root is '|top'."): r.get(sub0sub0, "|bar")
def test_iadd(): """iadd operator.""" a = defaultlist() b = [1, 2] a += a eq_(a, []) a += b eq_(a, [1, 2]) a[5] = 7 eq_(b, [1, 2]) eq_(a, [1, 2, None, None, None, 7]) with assert_raises(TypeError, "'int' object is not iterable"): a += 4
def test_add(): a = defaultlist() b = [1, 2] a_a = a + a eq_(a_a, []) a_b = a + b eq_(a_b, [1, 2]) a_b[5] = 7 eq_(a, []) eq_(b, [1, 2]) eq_(a_b, [1, 2, None, None, None, 7]) with assert_raises(TypeError, 'can only concatenate list (not "int") to list'): a + 4
def test_find(): f = Node("f") b = Node("b", parent=f) Node("a", parent=b) d = Node("d", parent=b) Node("c", parent=d) Node("e", parent=d) g = Node("g", parent=f) i = Node("i", parent=g) Node("h", parent=i) eq_(find(f, lambda n: n.name == "d"), d) eq_(find(f, lambda n: n.name == "z"), None) with assert_raises(CountError, ( "Expecting 1 elements at maximum, but found 5. " "(Node('/f/b'), Node('/f/b/a'), Node('/f/b/d'), Node('/f/b/d/c'), Node('/f/b/d/e'))")): find(f, lambda n: b in n.path)
def test_glob(): """Wildcard.""" top = MyNode("top", parent=None) sub0 = MyNode("sub0", parent=top) sub0sub0 = MyNode("sub0", parent=sub0) sub0sub1 = MyNode("sub1", parent=sub0) sub0sub1sub0 = MyNode("sub0", parent=sub0sub1) MyNode("sub1", parent=sub0sub1) sub1 = MyNode("sub1", parent=top) sub1sub0 = MyNode("sub0", parent=sub1) r = at.Resolver() eq_(r.glob(top, "*|*|sub0"), [sub0sub1sub0]) eq_(r.glob(top, "sub0|sub?"), [sub0sub0, sub0sub1]) eq_(r.glob(sub1, "..|.|*"), [sub0, sub1]) eq_(r.glob(top, "*|*"), [sub0sub0, sub0sub1, sub1sub0]) eq_(r.glob(top, "*|sub0"), [sub0sub0, sub1sub0]) with assert_raises(at.ChildResolverError, "MyNode('|top|sub1') has no child sub1. Children are: 'sub0'."): r.glob(top, "sub1|sub1")
def test_children_setter_large(): root = Node("root") s0 = Node("sub0") s0b = Node("sub0B") s0a = Node("sub0A") s1 = Node("sub1") s1a = Node("sub1A") s1b = Node("sub1B") s1c = Node("sub1C") s1ca = Node("sub1Ca") root.children = [s0, s1] eq_(root.descendants, (s0, s1)) s0.children = [s0a, s0b] eq_(root.descendants, (s0, s0a, s0b, s1)) s1.children = [s1a, s1b, s1c] eq_(root.descendants, (s0, s0a, s0b, s1, s1a, s1b, s1c)) with assert_raises(TypeError, "'Node' object is not iterable"): s1.children = s1ca eq_(root.descendants, (s0, s0a, s0b, s1, s1a, s1b, s1c))
def test_glob(): """Wildcard.""" top = at.Node("top", parent=None) sub0 = at.Node("sub0", parent=top) sub0sub0 = at.Node("sub0", parent=sub0) sub0sub1 = at.Node("sub1", parent=sub0) sub0sub1sub0 = at.Node("sub0", parent=sub0sub1) at.Node("sub1", parent=sub0sub1) sub1 = at.Node("sub1", parent=top) sub1sub0 = at.Node("sub0", parent=sub1) r = at.Resolver() eq_(r.glob(top, "*/*/sub0"), [sub0sub1sub0]) eq_(r.glob(top, "sub0/sub?"), [sub0sub0, sub0sub1]) eq_(r.glob(sub1, ".././*"), [sub0, sub1]) eq_(r.glob(top, "*/*"), [sub0sub0, sub0sub1, sub1sub0]) eq_(r.glob(top, "*/sub0"), [sub0sub0, sub1sub0]) with assert_raises( at.ChildResolverError, "Node('/top/sub1') has no child sub1. Children are: 'sub0'."): r.glob(top, "sub1/sub1")
def test_walker(): """walk test.""" f = Node("f") b = Node("b", parent=f) a = Node("a", parent=b) d = Node("d", parent=b) c = Node("c", parent=d) e = Node("e", parent=d) g = Node("g", parent=f) i = Node("i", parent=g) h = Node("h", parent=i) w = Walker() eq_(w.walk(f, f), ((), f, ())) eq_(w.walk(f, b), ((), f, (b, ))) eq_(w.walk(b, f), ((b, ), f, ())) eq_(w.walk(a, f), ((a, b), f, ())) eq_(w.walk(h, e), ((h, i, g), f, (b, d, e))) eq_(w.walk(d, e), ((), d, (e, ))) with assert_raises( WalkError, "Node('/a') and Node('/b') are not part of the same tree."): w.walk(Node("a"), Node("b"))
def test_type_assertion(): root = Node("root") with assert_raises(AssertionError, "Cannot add non-node object 'string'."): root.children = ["string"]
def test_any_node_parent_error(): """Any Node Parent Error.""" with assert_raises(TreeError, "Parent node 'r' is not of type 'NodeMixin'."): AnyNode("r")
def test_node_parent_error(): """Node Parent Error.""" with assert_raises(TreeError, "Parent node 'parent' is not of type 'NodeMixin'."): Node("root", "parent")
def test_tuple(): """Tuple as parent.""" with assert_raises(TreeError, "Parent node (1, 0, 3) is not of type 'NodeMixin'."): Node((0, 1, 2), parent=(1, 0, 3))