コード例 #1
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_coerce_classmethod():
    t1 = Type.dispatch(CT1)
    assert t1.coerce(1) == CT1(1)
    assert t1.coerce({'a': 1}) == CT1(1)
    assert t1.coerce({'a': 1.2}) == CT1(1)
    assert_raises(TypeError, t1.coerce, [1, 2])

    t2 = Type.dispatch(CT2)
    assert t2.coerce(dict(a=1, b=2)) == CT2(a=1, b=CT1(2))
    assert t2.coerce(dict(a=1, b=CT1(2))) == CT2(a=1, b=CT1(2))
    assert_raises(TypeError, t2.coerce, dict(a=1, b=2.3))
    assert t2.coerce(dict(a=1, b=dict(a=2.3))) == CT2(a=1, b=CT1(2))

    t3 = Type.dispatch(CT3)
    assert t3.coerce(dict(a=1, b=dict(a=2, b=3), c=4)) == \
        CT3(a=1, b=CT2(a=2, b=CT1(3)), c=CT1(4))
    assert t3.coerce(dict(a=1, b=dict(a=2, b=CT1(3)), c=4)) == \
        CT3(a=1, b=CT2(a=2, b=CT1(3)), c=CT1(4))
    assert_raises(TypeError, t3.coerce, dict(a=1, b=dict(a=2, b=3.1), c=4))
    assert t3.coerce(dict(a=1, b=dict(a=2, b=dict(a=3.1)), c=4)) == \
        CT3(a=1, b=CT2(a=2, b=CT1(3)), c=CT1(4))

    obj = t3.coerce(dict(a=1, b=dict(a=2, b=3), c=4))
    check_idempotence(obj)

    t4 = Type.dispatch(CT4)
    assert t4.coerce(dict(a=1)) == CT4(a=2)

    t5 = Type.dispatch(CT5)
    assert t5.coerce(dict(a=1)) == CT5(a=4)

    t6 = Type.dispatch(CT6)
    assert t6.coerce(dict(a=1)) == CT6(a=5)
コード例 #2
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_coerce_classmethod():
    t1 = Type.dispatch(CT1)
    assert t1.coerce(1) == CT1(1)
    assert t1.coerce({'a': 1}) == CT1(1)
    assert t1.coerce({'a': 1.2}) == CT1(1)
    assert_raises(TypeError, t1.coerce, [1, 2])

    t2 = Type.dispatch(CT2)
    assert t2.coerce(dict(a=1, b=2)) == CT2(a=1, b=CT1(2))
    assert t2.coerce(dict(a=1, b=CT1(2))) == CT2(a=1, b=CT1(2))
    assert_raises(TypeError, t2.coerce, dict(a=1, b=2.3))
    assert t2.coerce(dict(a=1, b=dict(a=2.3))) == CT2(a=1, b=CT1(2))

    t3 = Type.dispatch(CT3)
    assert t3.coerce(dict(a=1, b=dict(a=2, b=3), c=4)) == \
        CT3(a=1, b=CT2(a=2, b=CT1(3)), c=CT1(4))
    assert t3.coerce(dict(a=1, b=dict(a=2, b=CT1(3)), c=4)) == \
        CT3(a=1, b=CT2(a=2, b=CT1(3)), c=CT1(4))
    assert_raises(TypeError, t3.coerce, dict(a=1, b=dict(a=2, b=3.1), c=4))
    assert t3.coerce(dict(a=1, b=dict(a=2, b=dict(a=3.1)), c=4)) == \
        CT3(a=1, b=CT2(a=2, b=CT1(3)), c=CT1(4))

    obj = t3.coerce(dict(a=1, b=dict(a=2, b=3), c=4))
    check_idempotence(obj)

    t4 = Type.dispatch(CT4)
    assert t4.coerce(dict(a = 1)) == CT4(a = 2)

    t5 = Type.dispatch(CT5)
    assert t5.coerce(dict(a = 1)) == CT5(a = 4)

    t6 = Type.dispatch(CT6)
    assert t6.coerce(dict(a = 1)) == CT6(a = 5)
コード例 #3
0
ファイル: test_tree.py プロジェクト: mbodenhamer/syn
def tree_tst_2(treecls):
    from syn.base_utils import seq_list_nested

    b = 3
    d = 4 # 121 nodes
    # d = 6 # 1093 nodes
    # d = 7 # 3280 nodes
    # d = 8 # Almost 10,000 nodes

    lst, N = seq_list_nested(b, d, top_level=False)

    root = tree_node_from_nested_list(lst[0], lst[1])
    assert isinstance(root, Node)

    tree1 = treecls(root)
    base_id = 0

    check_idempotence(tree1)

    assert len(tree1.nodes) == N
    assert tree1.node_types == ['Tst1',]
    assert sorted(tree1.id_dict.keys()) == list(range(base_id,base_id + N))
    assert list(tree1.type_dict.keys()) == ['Tst1']
    assert sorted(tree1.type_dict['Tst1'], key=attrgetter('_id')) == \
        sorted(tree1.nodes, key=attrgetter('_id'))

    accum = []
    def collect(node):
        accum.append(node.value)
    tree1.depth_first(collect)
    assert sum(accum) == sum(range(1, N+1))

    while tree1.root._children:
        tree1.remove_node(tree1.root._children[0])

    assert tree1.nodes == [tree1.root]
    assert tree1.root._children == []

    mod = 4
    base_id = 0
    sproot = tree_node_from_nested_list_types(lst[0], lst[1], mod)
    tree2 = Tree(sproot)
    
    assert len(tree2.nodes) == N
    assert tree2.node_types == ['Tst1', 'Tst2']
    assert sorted(tree2.id_dict.keys()) == list(range(base_id,base_id+N))
    assert sorted(tree2.type_dict.keys()) == sorted(['Tst1', 'Tst2'])
    assert sorted(tree2.type_dict['Tst1'] + 
                  tree2.type_dict['Tst2'], key=attrgetter('_id')) == \
        sorted(tree2.nodes, key=attrgetter('_id'))

    accum = []
    tree2.depth_first(collect)
    assert sum(accum) == sum(range(1, N+1))
    
    accum = []
    tree2.depth_first(Tst2 = collect)
    if N % mod != 0:
        assert sum(accum) == sum(range(mod, N, mod))
コード例 #4
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_call():
    obj = E(1, 2.1)

    assert obj.to_dict() == dict(a=1, b=2.1, d=[])

    assert E(1, 2.1, d=(1, 2)).to_dict() == dict(a=1, b=2.1, d=[1, 2])

    check_idempotence(obj)
コード例 #5
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_optional_none():
    obj = D(5, 3.4)

    assert obj.a == 5
    assert obj.b == 3.4
    assert obj.c is None
    obj.validate()

    check_idempotence(obj)
コード例 #6
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_optional_none():
    obj = D(5, 3.4)

    assert obj.a == 5
    assert obj.b == 3.4
    assert obj.c is None
    obj.validate()

    check_idempotence(obj)
コード例 #7
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_getstate_exclude():
    obj = GSEx(1)
    assert obj.a == 1
    assert obj.b == 2
    assert_raises(AssertionError, check_idempotence, obj)

    obj = GSEx2(1)
    assert obj.a == 1
    assert obj.b == 2
    check_idempotence(obj)
コード例 #8
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_getstate_exclude():
    obj = GSEx(1)
    assert obj.a == 1
    assert obj.b == 2
    assert_raises(AssertionError, check_idempotence, obj)

    obj = GSEx2(1)
    assert obj.a == 1
    assert obj.b == 2
    check_idempotence(obj)
コード例 #9
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_arg_coercion():
    obj = C(5.1, 3)

    assert obj.a == 5
    assert obj.b == 3.0

    assert isinstance(obj.a, int)
    assert isinstance(obj.b, float)

    check_idempotence(obj)
コード例 #10
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_arg_coercion():
    obj = C(5.1, 3)
    
    assert obj.a == 5
    assert obj.b == 3.0

    assert isinstance(obj.a, int)
    assert isinstance(obj.b, float)

    check_idempotence(obj)
コード例 #11
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_call():
    obj = E(1, 2.1)
    
    assert obj.to_dict() == dict(a = 1,
                                 b = 2.1,
                                 d = [])

    assert E(1, 2.1, d=(1, 2)).to_dict() == dict(a = 1,
                                                 b = 2.1,
                                                 d = [1, 2])
    
    check_idempotence(obj)
コード例 #12
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_positional_args():
    obj = B(5, 3.4, c=u'abc')

    assert obj.a == 5
    assert obj.b == 3.4
    assert obj.c == u'abc'

    assert B(5).to_dict() == dict(a=5, b=1.2)

    assert_raises(TypeError, B, 1, 2, 3)
    assert_raises(TypeError, B, 1, 2, a=1)

    check_idempotence(obj)
コード例 #13
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_positional_args():
    obj = B(5, 3.4, c=u'abc')

    assert obj.a == 5
    assert obj.b == 3.4
    assert obj.c == u'abc'

    assert B(5).to_dict() == dict(a=5, b=1.2)

    assert_raises(TypeError, B, 1, 2, 3)
    assert_raises(TypeError, B, 1, 2, a=1)

    check_idempotence(obj)
コード例 #14
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_base():
    kwargs = dict(a=5, b=3.4, c=u'abc')
    obj = A(**kwargs)

    assert obj.a == 5
    assert obj.b == 3.4
    assert obj.c == u'abc'

    assert obj.to_dict() == kwargs
    assert obj.to_tuple() == (5, 3.4, u'abc')
    assert not is_hashable(obj)

    assert obj != 5
    assert_equivalent(obj, A(**kwargs))
    assert_inequivalent(obj, A(a=6, b=3.4, c=u'abc'))

    assert A(a=5, b=3.4).to_dict() == dict(a=5, b=3.4)

    check_idempotence(obj)

    assert_raises(TypeError, A, a=5.1, b=3.4)
    assert_raises(AttributeError, A, a=5)

    assert_equivalent(A(**kwargs), A(**kwargs))
    assert_inequivalent(A2(**kwargs), A2(**kwargs))
    assert_raises(AssertionError, assert_pickle_idempotent, A2(**kwargs))

    obj2 = A2(**kwargs)
    assert_type_equivalent(obj2.to_dict(), dict(a=5, b=3.4, c=u'abc'))
    assert obj2.to_dict(include=['getstate_exclude']) == dict(b=3.4)

    obj3 = A3(**kwargs)
    assert obj3.to_tuple() == (5, 3.4, u'abc')
    assert is_hashable(obj3)

    obj4 = A4(a=[1, 2, 3], b=3.4, c='abc')
    assert is_hashable(obj4)
コード例 #15
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_base():
    kwargs = dict(a=5, b=3.4, c=u'abc')
    obj = A(**kwargs)

    assert obj.a == 5
    assert obj.b == 3.4
    assert obj.c == u'abc'
    
    assert obj.to_dict() == kwargs
    assert obj.to_tuple() == (5, 3.4, u'abc')
    assert not is_hashable(obj)

    assert obj != 5
    assert_equivalent(obj, A(**kwargs))
    assert_inequivalent(obj, A(a=6, b=3.4, c=u'abc'))

    assert A(a=5, b=3.4).to_dict() == dict(a=5, b=3.4)
    
    check_idempotence(obj)

    assert_raises(TypeError, A, a=5.1, b=3.4)
    assert_raises(AttributeError, A, a=5)

    assert_equivalent(A(**kwargs), A(**kwargs))
    assert_inequivalent(A2(**kwargs), A2(**kwargs))
    assert_raises(AssertionError, assert_pickle_idempotent, A2(**kwargs))

    obj2 = A2(**kwargs)
    assert_type_equivalent(obj2.to_dict(), dict(a=5, b=3.4, c=u'abc'))
    assert obj2.to_dict(include=['getstate_exclude']) == dict(b=3.4)

    obj3 = A3(**kwargs)
    assert obj3.to_tuple() == (5, 3.4, u'abc')
    assert is_hashable(obj3)

    obj4 = A4(a=[1, 2, 3], b=3.4, c='abc')
    assert is_hashable(obj4)
コード例 #16
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_init():
    obj = F(5, 3.4)
    assert obj.d == 8.4
    assert obj.e == 13.4

    check_idempotence(obj)

    obj = G(5, 3.4)
    assert obj.d == 8.4
    assert obj.e == 13.4
    assert obj.f == 10.0

    check_idempotence(obj)

    obj = F(5, 3.4, d=2.0)
    assert obj.d == 2.0
    assert obj.e == 7.0

    check_idempotence(obj)
コード例 #17
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_init():
    obj = F(5, 3.4)
    assert obj.d == 8.4
    assert obj.e == 13.4

    check_idempotence(obj)

    obj = G(5, 3.4)
    assert obj.d == 8.4
    assert obj.e == 13.4
    assert obj.f == 10.0

    check_idempotence(obj)

    obj = F(5, 3.4, d=2.0)
    assert obj.d == 2.0
    assert obj.e == 7.0

    check_idempotence(obj)
コード例 #18
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_init_setstate_hooks():
    obj = I(5, 2.5)
    assert obj.d == 12.5
    assert obj.e == 14.5

    check_idempotence(obj)

    obj = I2(5, 2.5)
    assert obj.d == 12.5
    assert obj.e == 14.5
    assert obj.f == 27.0

    check_idempotence(obj)

    # Inheriting without overriding preserves the init hook
    obj = I2a(5, 2.5)
    assert obj.d == 12.5
    assert obj.e == 14.5
    assert obj.f == 27.0

    check_idempotence(obj)

    # Because we overrode _baz without specifying init_hook again
    assert_raises(AttributeError, I2b, 5, 2.5)

    obj = I3(5, 2.5)
    assert obj.f == 27.0
    obj2 = pickle.loads(pickle.dumps(obj))
    assert obj2.f == 28.0

    obj = I4(5, 2.5)
    assert obj.f == 5
    obj2 = pickle.loads(pickle.dumps(obj))
    assert obj2.f == 6

    assert_raises(TypeError, I, 5.2, 2) # Sanity check for init_validate
コード例 #19
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_init_setstate_hooks():
    obj = I(5, 2.5)
    assert obj.d == 12.5
    assert obj.e == 14.5

    check_idempotence(obj)

    obj = I2(5, 2.5)
    assert obj.d == 12.5
    assert obj.e == 14.5
    assert obj.f == 27.0

    check_idempotence(obj)

    # Inheriting without overriding preserves the init hook
    obj = I2a(5, 2.5)
    assert obj.d == 12.5
    assert obj.e == 14.5
    assert obj.f == 27.0

    check_idempotence(obj)

    # Because we overrode _baz without specifying init_hook again
    assert_raises(AttributeError, I2b, 5, 2.5)

    obj = I3(5, 2.5)
    assert obj.f == 27.0
    obj2 = pickle.loads(pickle.dumps(obj))
    assert obj2.f == 28.0

    obj = I4(5, 2.5)
    assert obj.f == 5
    obj2 = pickle.loads(pickle.dumps(obj))
    assert obj2.f == 6

    assert_raises(TypeError, I, 5.2, 2)  # Sanity check for init_validate
コード例 #20
0
ファイル: test_base.py プロジェクト: pombredanne/syn-1
def test_repr():
    obj = H(a=1, b=2)
    assert repr(obj) == "<{}.H {{'a': 1}}>".format(get_mod(H))

    check_idempotence(obj)
コード例 #21
0
ファイル: test_base.py プロジェクト: mbodenhamer/syn
def test_repr():
    obj = H(a = 1, b = 2)
    assert repr(obj) == "<{}.H {{'a': 1}}>".format(get_mod(H))

    check_idempotence(obj)
コード例 #22
0
def tree_tst_1(treecls):
    cls = treecls._attrs.types['root'].type
    clsname = get_typename(cls)
    n1 = cls(_name='n1', _id=0)
    n2 = cls(_name='n2', _id=1)
    n3 = cls(_name='n3', _id=2)
    n4 = cls(_name='n4', _id=3)
    n5 = cls(_name='n5', _id=4)
    n6 = cls(_name='n6', _id=5)

    n1.add_child(n2)
    n1.add_child(n3)

    assert list(n1.siblings()) == []
    assert list(n2.siblings()) == [n3]
    assert list(n3.siblings()) == [n2]

    obj = treecls(n1)
    check_idempotence(obj)

    assert obj.nodes == [n1, n2, n3]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 1: n2, 2: n3}
    assert obj.type_dict == {clsname: [n1, n2, n3]}

    assert_raises(TreeError, obj.add_node, n3)
    assert_raises(TreeError, obj.add_node, n4, parent=n5)
    obj.add_node(n4, parent=n3)

    assert n4 in obj.nodes
    assert n4 in n3._children
    assert n4._parent is n3

    assert_raises(TreeError, obj.add_node, n5, parent_id=100)
    obj.add_node(n5, parent_id=1)

    assert n5 in obj.nodes
    assert n5 in n2._children
    assert n5._parent is n2

    obj.add_node(n6)
    assert n6 in obj.nodes
    assert n6 in n5._children
    assert n6._parent is n5

    assert obj.nodes == [n1, n2, n3, n4, n5, n6]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 1: n2, 2: n3, 3: n4, 4: n5, 5: n6}
    assert obj.type_dict == {clsname: [n1, n2, n3, n4, n5, n6]}

    for _id, node in enumerate([n1, n2, n3, n4, n5, n6]):
        assert obj.get_node_by_id(_id) == obj._get_node_by_id(_id)
        assert obj.get_node_by_id(_id) == node
    assert obj.get_node_by_id(100) is None
    assert obj.get_node_by_id(-1) is None

    assert_raises(TypeError, obj.depth_first, FooType=do_nothing)
    assert_raises(TypeError, obj._check_search_kwarg_types, {Tst2: do_nothing})
    assert_raises(TypeError, obj._check_search_kwarg_types, {0: do_nothing})

    assert list(n1.descendants()) == [n2, n5, n6, n3, n4]

    accum = []

    def collect(node):
        accum.append(node._id)

    obj.depth_first(collect)
    assert accum == [0, 1, 4, 5, 2, 3]

    accum = []
    obj.depth_first(**{clsname: collect})
    assert accum == [0, 1, 4, 5, 2, 3]

    accum = []
    obj.search_rootward(collect)
    assert accum == [0]

    accum = []
    obj.search_rootward(**{'current_node': n5, clsname: collect})
    assert accum == [4, 1, 0]

    def stop(node):
        return node._id == 3

    def get(node):
        return node._name

    assert obj.depth_first(stop_test=stop, _return=get) == 'n4'
    assert obj.search_rootward(stop_test=stop, _return=get) is None
    assert obj.search_rootward(current_node=n4, stop_test=stop,
                               _return=get) == 'n4'
    assert obj.search_rootward(current_node=n6, stop_test=stop,
                               _return=get) is None

    n7 = cls(_name='n7', _id=6)
    n8 = cls(_name='n8', _id=7)

    n7.add_child(n8)
    obj.replace_node(n5, n7)

    assert n2._children == [n7]
    assert n7._parent is n2
    assert n7._children == [n8]
    assert n8._parent is n7

    assert n5._children == [n6]
    assert n6._parent is n5
    assert n5._parent is None

    assert obj.nodes == [n1, n2, n3, n4, n7, n8]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 1: n2, 2: n3, 3: n4, 6: n7, 7: n8}
    assert obj.type_dict == {clsname: [n1, n2, n3, n4, n7, n8]}

    assert_raises(TreeError, obj.remove_node, n5)
    assert_raises(TreeError, obj.replace_node, n5, n7)

    obj.remove_node(n2)
    assert n1._children == [n3]
    assert n2._parent is None
    assert n2._children == [n7]
    assert n7._parent is n2

    assert obj.nodes == [n1, n3, n4]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 2: n3, 3: n4}
    assert obj.type_dict == {clsname: [n1, n3, n4]}

    assert_raises(TreeError, obj.replace_node, n1, n7)
    assert_raises(TreeError, obj.replace_node, n3, n7)

    obj.replace_node(n1, n2)
    assert n1._children == [n3]
    assert n3._parent is n1

    assert obj.root is n2
    assert obj.nodes == [n2, n7, n8]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {1: n2, 6: n7, 7: n8}
    assert obj.type_dict == {clsname: [n2, n7, n8]}

    obj.rebuild()
    assert obj.root is n2
    assert obj.nodes == [n2, n7, n8]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {1: n2, 6: n7, 7: n8}
    assert obj.type_dict == {clsname: [n2, n7, n8]}

    obj.remove_node(n2)
    assert obj.root is None
    assert obj.nodes == []
    assert obj.node_types == []
    assert obj.id_dict == {}
    assert obj.type_dict == {}
コード例 #23
0
def tree_tst_2(treecls):
    from syn.base_utils import seq_list_nested

    b = 3
    d = 4  # 121 nodes
    # d = 6 # 1093 nodes
    # d = 7 # 3280 nodes
    # d = 8 # Almost 10,000 nodes

    lst, N = seq_list_nested(b, d, top_level=False)

    root = tree_node_from_nested_list(lst[0], lst[1])
    assert isinstance(root, Node)

    tree1 = treecls(root)
    base_id = 0

    check_idempotence(tree1)

    assert len(tree1.nodes) == N
    assert tree1.node_types == [
        'Tst1',
    ]
    assert sorted(tree1.id_dict.keys()) == list(range(base_id, base_id + N))
    assert list(tree1.type_dict.keys()) == ['Tst1']
    assert sorted(tree1.type_dict['Tst1'], key=attrgetter('_id')) == \
        sorted(tree1.nodes, key=attrgetter('_id'))

    accum = []

    def collect(node):
        accum.append(node.value)

    tree1.depth_first(collect)
    assert sum(accum) == sum(range(1, N + 1))

    while tree1.root._children:
        tree1.remove_node(tree1.root._children[0])

    assert tree1.nodes == [tree1.root]
    assert tree1.root._children == []

    mod = 4
    base_id = 0
    sproot = tree_node_from_nested_list_types(lst[0], lst[1], mod)
    tree2 = Tree(sproot)

    assert len(tree2.nodes) == N
    assert tree2.node_types == ['Tst1', 'Tst2']
    assert sorted(tree2.id_dict.keys()) == list(range(base_id, base_id + N))
    assert sorted(tree2.type_dict.keys()) == sorted(['Tst1', 'Tst2'])
    assert sorted(tree2.type_dict['Tst1'] +
                  tree2.type_dict['Tst2'], key=attrgetter('_id')) == \
        sorted(tree2.nodes, key=attrgetter('_id'))

    accum = []
    tree2.depth_first(collect)
    assert sum(accum) == sum(range(1, N + 1))

    accum = []
    tree2.depth_first(Tst2=collect)
    if N % mod != 0:
        assert sum(accum) == sum(range(mod, N, mod))
コード例 #24
0
ファイル: test_tree.py プロジェクト: mbodenhamer/syn
def tree_tst_1(treecls):
    cls = treecls._attrs.types['root'].type
    clsname = get_typename(cls)
    n1 = cls(_name='n1', _id=0)
    n2 = cls(_name='n2', _id=1)
    n3 = cls(_name='n3', _id=2)
    n4 = cls(_name='n4', _id=3)
    n5 = cls(_name='n5', _id=4)
    n6 = cls(_name='n6', _id=5)

    n1.add_child(n2)
    n1.add_child(n3)

    assert list(n1.siblings()) == []
    assert list(n2.siblings()) == [n3]
    assert list(n3.siblings()) == [n2]

    obj = treecls(n1)
    check_idempotence(obj)

    assert obj.nodes == [n1, n2, n3]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 1: n2, 2: n3}
    assert obj.type_dict == {clsname: [n1, n2, n3]}

    assert_raises(TreeError, obj.add_node, n3)
    assert_raises(TreeError, obj.add_node, n4, parent=n5)
    obj.add_node(n4, parent=n3)
    
    assert n4 in obj.nodes
    assert n4 in n3._children
    assert n4._parent is n3

    assert_raises(TreeError, obj.add_node, n5, parent_id=100)
    obj.add_node(n5, parent_id=1)

    assert n5 in obj.nodes
    assert n5 in n2._children
    assert n5._parent is n2

    obj.add_node(n6)
    assert n6 in obj.nodes
    assert n6 in n5._children
    assert n6._parent is n5

    assert obj.nodes == [n1, n2, n3, n4, n5, n6]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 1: n2, 2: n3, 3:n4, 4:n5, 5:n6}
    assert obj.type_dict == {clsname: [n1, n2, n3, n4, n5, n6]}
    
    
    for _id,node in enumerate([n1, n2, n3, n4, n5, n6]):
        assert obj.get_node_by_id(_id) == obj._get_node_by_id(_id)
        assert obj.get_node_by_id(_id) == node
    assert obj.get_node_by_id(100) is None    
    assert obj.get_node_by_id(-1) is None    
    

    assert_raises(TypeError, obj.depth_first, FooType = do_nothing)
    assert_raises(TypeError, obj._check_search_kwarg_types, 
                  {Tst2: do_nothing})
    assert_raises(TypeError, obj._check_search_kwarg_types, {0: do_nothing})

    assert list(n1.descendants()) == [n2, n5, n6, n3, n4]

    accum = []
    def collect(node):
        accum.append(node._id)
    
    obj.depth_first(collect)
    assert accum == [0, 1, 4, 5, 2, 3]

    accum = []
    obj.depth_first(**{clsname: collect})
    assert accum == [0, 1, 4, 5, 2, 3]

    accum = []
    obj.search_rootward(collect)
    assert accum == [0]

    accum = []
    obj.search_rootward(**{'current_node': n5, 
                           clsname: collect})
    assert accum == [4, 1, 0]

    def stop(node):
        return node._id == 3
    def get(node):
        return node._name

    assert obj.depth_first(stop_test = stop, _return = get) == 'n4'
    assert obj.search_rootward(stop_test = stop, _return = get) is None
    assert obj.search_rootward(current_node = n4, stop_test = stop, 
                               _return = get) == 'n4'
    assert obj.search_rootward(current_node = n6, stop_test = stop,
                               _return = get) is None


    n7 = cls(_name='n7', _id=6)
    n8 = cls(_name='n8', _id=7)

    n7.add_child(n8)
    obj.replace_node(n5, n7)

    assert n2._children == [n7]
    assert n7._parent is n2
    assert n7._children == [n8]
    assert n8._parent is n7

    assert n5._children == [n6]
    assert n6._parent is n5
    assert n5._parent is None

    assert obj.nodes == [n1, n2, n3, n4, n7, n8]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 1: n2, 2: n3, 3:n4, 6:n7, 7:n8}
    assert obj.type_dict == {clsname: [n1, n2, n3, n4, n7, n8]}


    assert_raises(TreeError, obj.remove_node, n5)
    assert_raises(TreeError, obj.replace_node, n5, n7)

    obj.remove_node(n2)
    assert n1._children == [n3]
    assert n2._parent is None
    assert n2._children == [n7]
    assert n7._parent is n2

    assert obj.nodes == [n1, n3, n4]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {0: n1, 2: n3, 3:n4}
    assert obj.type_dict == {clsname: [n1, n3, n4]}


    assert_raises(TreeError, obj.replace_node, n1, n7)
    assert_raises(TreeError, obj.replace_node, n3, n7)

    obj.replace_node(n1, n2)
    assert n1._children == [n3]
    assert n3._parent is n1

    assert obj.root is n2
    assert obj.nodes == [n2, n7, n8]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {1: n2, 6: n7, 7:n8}
    assert obj.type_dict == {clsname: [n2, n7, n8]}
    

    obj.rebuild()
    assert obj.root is n2
    assert obj.nodes == [n2, n7, n8]
    assert obj.node_types == [clsname]
    assert obj.id_dict == {1: n2, 6: n7, 7:n8}
    assert obj.type_dict == {clsname: [n2, n7, n8]}


    obj.remove_node(n2)
    assert obj.root is None
    assert obj.nodes == []
    assert obj.node_types == []
    assert obj.id_dict == {}
    assert obj.type_dict == {}