summaryrefslogtreecommitdiff
path: root/examples/adjacencytree/basic_tree.py
blob: c544ce662f1134032aaa73f71758e6df7e32ddc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from sqlalchemy.mapper import *
from sqlalchemy.schema import *
from sqlalchemy.sql import *
import sqlalchemy.util as util
import tables
import string, sys

"""a basic Adjacency List model tree."""

class NodeList(util.OrderedDict):
    """extends an Ordered Dictionary, which is just a dictionary that returns its keys and values
    in order upon iteration.  Adds functionality to automatically associate 
    the parent of a TreeNode with itself, upon append to the parent's list of child nodes."""
    def __init__(self, parent):
        util.OrderedDict.__init__(self)
        self.parent = parent
    def append(self, node):
        node.parent = self.parent
        self[node.name] = node
    def __iter__(self):
        return iter(self.values())

class TreeNode(object):
    """a rich Tree class which includes path-based operations"""
    def __init__(self, name=None):
        self.children = NodeList(self)
        self.name = name
        self.parent = None
        self.id = None
        self.parent_id = None
    def get_child_by_path(self, path):
        node = self
        try:
            for token in path.split('/'):
                node = node.children[token]
            else:
                return node
        except KeyError:
            return None
    def append(self, node):
        if isinstance(node, str):
            self.children.append(TreeNode(node))
        else:
            self.children.append(node)
    def _get_path(self):
        if self.parent is None:
            return '/'
        else:
            return self.parent._get_path() + self.name + '/'
    path = property(lambda s: s._path())
    def __str__(self):
        return self._getstring(0, False)
    def _getstring(self, level, expand = False):
        s = ('  ' * level) + "%s (%s,%s)" % (self.name, self.id,self.parent_id) + '\n'
        if expand:
            s += string.join([n._getstring(level+1, True) for n in self.children.values()], '')
        return s
    def print_nodes(self):
        return self._getstring(0, True)
        
# define the mapper.  we will make "convenient" property
# names vs. the more verbose names in the table definition

TreeNode.mapper=assignmapper(tables.trees, class_ = TreeNode, properties=dict(
    id=tables.trees.c.node_id,
    name=tables.trees.c.node_name,
    parent_id=tables.trees.c.parent_node_id,
    root_id=tables.trees.c.root_node_id,
    children=relation(TreeNode, primaryjoin=tables.trees.c.parent_node_id==tables.trees.c.node_id, thiscol=tables.trees.c.node_id, lazy=True, uselist=True, private=True),
))


node2 = TreeNode('node2')
node2.append('subnode1')
node = TreeNode('rootnode')
node.append('node1')
node.append(node2)
node.append('node3')
node.children['node2'].append('subnode2')
print node.print_nodes()

objectstore.commit()

node.append('node4')
node.children['node4'].append('subnode3')
node.children['node4'].append('subnode4')
node.children['node4'].children['subnode3'].append('subsubnode1')
del node.children['node1']

print node.print_nodes()

objectstore.commit()

id = node.id

objectstore.clear()
print "\n\n\n"

t = TreeNode.mapper.select(TreeNode.c.id == id)[0]

print t.print_nodes()
objectstore.delete(t)
objectstore.commit()