From: Jason Kirtland Date: Wed, 14 Nov 2007 01:26:50 +0000 (+0000) Subject: Removed some distractions, ala r3770. X-Git-Tag: rel_0_4_1~25 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=7f0b5edc9258364b9bb954bd4e3b18d88d63edf4;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Removed some distractions, ala r3770. --- diff --git a/examples/adjacencytree/byroot_tree.py b/examples/adjacencytree/byroot_tree.py index 76039526b3..a67eeb7714 100644 --- a/examples/adjacencytree/byroot_tree.py +++ b/examples/adjacencytree/byroot_tree.py @@ -1,40 +1,48 @@ -"""a more advanced example of basic_tree.py. treenodes can now reference their "root" node, and -introduces a new selection method which selects an entire tree of nodes at once, taking -advantage of a custom MapperExtension to assemble incoming nodes into their correct structure.""" - -from sqlalchemy import * -from sqlalchemy.orm import * +"""A more advanced example of basic_tree.py. + +Treenodes can now reference their "root" node, and introduces a new +selection method which selects an entire tree of nodes at once, taking +advantage of a custom MapperExtension to assemble incoming nodes into their +correct structure. +""" + +from sqlalchemy import MetaData, Table, Column, Sequence, ForeignKey +from sqlalchemy import Integer, String +from sqlalchemy.orm import create_session, mapper, relation, backref +from sqlalchemy.orm import MapperExtension from sqlalchemy.orm.collections import attribute_mapped_collection -engine = create_engine('sqlite:///:memory:', echo=True) -metadata = MetaData(engine) +metadata = MetaData('sqlite:///') +metadata.bind.echo = True -"""create the treenodes table. This is a basic adjacency list model table. -One additional column, "root_node_id", references a "root node" row and is used -in the 'byroot_tree' example.""" +# Create the `treenodes` table, a basic adjacency list model table. +# One additional column, "root_id", references a "root node" row and is used +# in the 'byroot_tree' example. trees = Table('treenodes', metadata, - Column('node_id', Integer, Sequence('treenode_id_seq',optional=False), primary_key=True), - Column('parent_node_id', Integer, ForeignKey('treenodes.node_id'), nullable=True), - Column('root_node_id', Integer, ForeignKey('treenodes.node_id'), nullable=True), - Column('node_name', String(50), nullable=False), - Column('data_ident', Integer, ForeignKey('treedata.data_id')) - ) + Column('id', Integer, Sequence('treenode_id_seq', optional=True), + primary_key=True), + Column('parent_id', Integer, ForeignKey('treenodes.id'), nullable=True), + Column('root_id', Integer, ForeignKey('treenodes.id'), nullable=True), + Column('name', String(50), nullable=False), + Column('data_id', Integer, ForeignKey('treedata.data_id'))) treedata = Table( - "treedata", metadata, + "treedata", metadata, Column('data_id', Integer, primary_key=True), - Column('value', String(100), nullable=False) -) + Column('value', String(100), nullable=False)) class TreeNode(object): - """a hierarchical Tree class, which adds the concept of a "root node". The root is - the topmost node in a tree, or in other words a node whose parent ID is NULL. - All child nodes that are decendents of a particular root, as well as a root node itself, - reference this root node. """ - + """A hierarchical Tree class, + + Adds the concept of a "root node". The root is the topmost node in a + tree, or in other words a node whose parent ID is NULL. All child nodes + that are decendents of a particular root, as well as a root node itself, + reference this root node. + """ + def __init__(self, name): self.name = name self.root = self @@ -57,42 +65,55 @@ class TreeNode(object): return self._getstring(0, False) def _getstring(self, level, expand = False): - s = (' ' * level) + "%s (%s,%s,%s, %d): %s" % (self.name, self.id,self.parent_id,self.root_id, id(self), repr(self.data)) + '\n' + s = "%s%s (%s,%s,%s, %d): %s\n" % ( + (' ' * level), self.name, self.id,self.parent_id, + self.root_id, id(self), repr(self.data)) if expand: - s += ''.join([n._getstring(level+1, True) for n in self.children.values()]) + s += ''.join([n._getstring(level+1, True) + for n in self.children.values()]) return s def print_nodes(self): return self._getstring(0, True) - + class TreeLoader(MapperExtension): def after_insert(self, mapper, connection, instance): - """runs after the insert of a new TreeNode row. The primary key of the row is not determined - until the insert is complete, since most DB's use autoincrementing columns. If this node is - the root node, we will take the new primary key and update it as the value of the node's - "root ID" as well, since its root node is itself.""" + """ + Runs after the insert of a new TreeNode row. The primary key of the + row is not determined until the insert is complete, since most DB's + use autoincrementing columns. If this node is the root node, we + will take the new primary key and update it as the value of the + node's "root ID" as well, since its root node is itself. + """ if instance.root is instance: - connection.execute(mapper.mapped_table.update(TreeNode.c.id==instance.id, values=dict(root_node_id=instance.id))) + connection.execute(mapper.mapped_table.update( + TreeNode.c.id==instance.id, values=dict(root_id=instance.id))) instance.root_id = instance.id def append_result(self, mapper, selectcontext, row, instance, result, **flags): - """runs as results from a SELECT statement are processed, and newly created or already-existing - instances that correspond to each row are appended to result lists. This method will only - append root nodes to the result list, and will attach child nodes to their appropriate parent - node as they arrive from the select results. This allows a SELECT statement which returns - both root and child nodes in one query to return a list of "roots".""" + """ + Runs as results from a SELECT statement are processed, and newly + created or already-existing instances that correspond to each row + are appended to result lists. This method will only append root + nodes to the result list, and will attach child nodes to their + appropriate parent node as they arrive from the select results. + This allows a SELECT statement which returns both root and child + nodes in one query to return a list of "roots". + """ + isnew = flags.get('isnew', False) if instance.parent_id is None: result.append(instance) else: if isnew or selectcontext.populate_existing: - parentnode = selectcontext.identity_map[mapper.identity_key_from_primary_key(instance.parent_id)] + key = mapper.identity_key_from_primary_key(instance.parent_id) + parentnode = selectcontext.identity_map[key] parentnode.children.set(instance) return False - + class TreeData(object): def __init__(self, value=None): self.id = None @@ -108,30 +129,29 @@ print "----------------------------" metadata.create_all() mapper(TreeNode, trees, properties=dict( - id=trees.c.node_id, - name=trees.c.node_name, - parent_id=trees.c.parent_node_id, - root_id=trees.c.root_node_id, - - # 'root' attribute. has a load-only backref '_descendants' that loads all nodes with the same root ID eagerly, - # which are intercepted by the TreeLoader extension and populated into the "children" collection. - root=relation(TreeNode, primaryjoin=trees.c.root_node_id==trees.c.node_id, remote_side=trees.c.node_id, lazy=None, - backref=backref('_descendants', lazy=False, join_depth=1, primaryjoin=trees.c.root_node_id==trees.c.node_id,viewonly=True)), - - # 'children' attribute. collection of immediate child nodes. this is a non-loading relation - # which is populated by the TreeLoader extension. - children=relation(TreeNode, - primaryjoin=trees.c.parent_node_id==trees.c.node_id, - lazy=None, - cascade="all", + # 'root' attribute. has a load-only backref '_descendants' that loads + # all nodes with the same root ID eagerly, which are intercepted by the + # TreeLoader extension and populated into the "children" collection. + root=relation(TreeNode, primaryjoin=trees.c.root_id==trees.c.id, + remote_side=trees.c.id, lazy=None, + backref=backref('_descendants', lazy=False, join_depth=1, + primaryjoin=trees.c.root_id==trees.c.id,viewonly=True)), + + # 'children' attribute. collection of immediate child nodes. this is a + # non-loading relation which is populated by the TreeLoader extension. + children=relation(TreeNode, primaryjoin=trees.c.parent_id==trees.c.id, + lazy=None, cascade="all", collection_class=attribute_mapped_collection('name'), - backref=backref('parent', primaryjoin=trees.c.parent_node_id==trees.c.node_id, remote_side=trees.c.node_id) + backref=backref('parent', + primaryjoin=trees.c.parent_id==trees.c.id, + remote_side=trees.c.id) ), - - # 'data' attribute. A collection of secondary objects which also loads eagerly. + + # 'data' attribute. A collection of secondary objects which also loads + # eagerly. data=relation(TreeData, cascade="all, delete-orphan", lazy=False) - -), extension = TreeLoader()) + +), extension=TreeLoader()) mapper(TreeData, treedata, properties={'id':treedata.c.data_id}) @@ -200,9 +220,12 @@ print "----------------------------" session.clear() -# load some nodes. we do this based on "root id" which will load an entire sub-tree in one pass. -# the MapperExtension will assemble the incoming nodes into a tree structure. -t = session.query(TreeNode).filter(TreeNode.c.root_id==nodeid).order_by([TreeNode.c.id])[0] +# load some nodes. we do this based on "root id" which will load an entire +# sub-tree in one pass. the MapperExtension will assemble the incoming +# nodes into a tree structure. +t = (session.query(TreeNode). + filter(TreeNode.c.root_id==nodeid). + order_by([TreeNode.c.id]))[0] print "\n\n\n----------------------------" print "Full Tree:"