From: Mike Bayer Date: Thu, 13 Oct 2005 00:24:09 +0000 (+0000) Subject: new examples X-Git-Tag: rel_0_1_0~565 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=606ca937628fdb765c8efce91c2763d33a8bf746;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git new examples --- diff --git a/examples/adjacencytree/basic_tree.py b/examples/adjacencytree/basic_tree.py new file mode 100644 index 0000000000..c544ce662f --- /dev/null +++ b/examples/adjacencytree/basic_tree.py @@ -0,0 +1,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() + + + + diff --git a/examples/adjacencytree/byroot_tree.py b/examples/adjacencytree/byroot_tree.py new file mode 100644 index 0000000000..116305164a --- /dev/null +++ b/examples/adjacencytree/byroot_tree.py @@ -0,0 +1,127 @@ +from sqlalchemy.mapper import * +from sqlalchemy.schema import * +from sqlalchemy.sql import * +import sqlalchemy.util as util +import tables +import string, sys + +"""a more advanced example of basic_tree.py. illustrates MapperExtension objects which +add application-specific functionality to a Mapper object.""" + +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 + node._set_root(self.parent.root) + 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): + self.children = NodeList(self) + self.name = name + self.root = self + self.parent = None + self.id = None + self.parent_id = None + self.root_id=None + def _set_root(self, root): + self.root = root + for c in self.children: + c._set_root(root) + 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,%s)" % (self.name, self.id,self.parent_id,self.root_id) + '\n' + if expand: + s += string.join([n._getstring(level+1, True) for n in self.children.values()], '') + return s + +class TreeLoader(MapperExtension): + def create_instance(self, mapper, row, imap, class_): + return TreeNode(row[mapper.c.name.label]) + def after_insert(self, mapper, instance): + if instance.root is instance: + mapper.primarytable.update(TreeNode.c.id==instance.id, values=dict(root_node_id=instance.id)).execute() + instance.root_id = instance.id + def append_result(self, mapper, row, imap, result, instance, populate_existing=False): + if instance.parent_id is None: + result.append(instance) + else: + parentnode = imap[mapper.identity_key(instance.parent_id)] + parentnode.children.append_nohistory(instance) + return False + +# define the mapper. we will make "convenient" property +# names vs. the more verbose names in the table definition + +TreeNode.mapper=assignmapper(tables.trees, 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, + root=relation(TreeNode, primaryjoin=tables.trees.c.root_node_id==tables.trees.c.node_id, thiscol=tables.trees.c.root_node_id, lazy=None, uselist=False), + children=relation(TreeNode, primaryjoin=tables.trees.c.parent_node_id==tables.trees.c.node_id, thiscol=tables.trees.c.node_id, lazy=None, uselist=True, private=True), +), extension = TreeLoader()) +TreeNode.mapper + +node2 = TreeNode('node2') +node2.append('subnode1') +node = TreeNode('rootnode') +#node.root = node +node.append('node1') +node.append(node2) +node.append('node3') +node.children['node2'].append('subnode2') +print node._getstring(0, True) +objectstore.commit() +#raise "hi" +node.append('node4') +node.children['node4'].append('subnode3') +node.children['node4'].append('subnode4') +node.children['node4'].children['subnode3'].append('subsubnode1') +print node._getstring(0, True) +#raise "hi" +del node.children['node1'] +objectstore.commit() + +id = node.id + +objectstore.clear() +print "\n\n\n" +t = TreeNode.mapper.select(TreeNode.c.root_id==id, order_by=[TreeNode.c.id])[0] + +print t._getstring(0, True) +objectstore.delete(t) +objectstore.commit() + + + + diff --git a/examples/adjacencytree/tables.py b/examples/adjacencytree/tables.py index 3cfe1e9314..d721d9330a 100644 --- a/examples/adjacencytree/tables.py +++ b/examples/adjacencytree/tables.py @@ -3,6 +3,10 @@ import sqlalchemy.engine engine = sqlalchemy.engine.create_engine('sqlite', ':memory:', {}, echo = True) +"""create the treenodes table. This is ia basic adjacency list model table. +One additional column, "root_node_id", references a "root node" row and is used +in the 'byroot_tree' example.""" + trees = Table('treenodes', engine, Column('node_id', Integer, primary_key=True), Column('parent_node_id', Integer, ForeignKey('treenodes.node_id'), nullable=True),