]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
merge trunk. Re-instating topological._find_cycles for the moment
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 30 Mar 2010 22:15:02 +0000 (18:15 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 30 Mar 2010 22:15:02 +0000 (18:15 -0400)
1  2 
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/topological.py

Simple merge
Simple merge
index 3f2ff6399cae7cefaf126e3ac4921337f5ef2d44,d35213f6b5afc58e6243c30dc8cdb3b2a1bdf56f..324995889fffddd573d931bd4e4628afe795973c
@@@ -141,3 -216,82 +141,36 @@@ def sort(tuples, allitems)
              queue.append(childnode)
      return output
  
 -def _organize_as_tree(nodes):
 -    """Given a list of nodes from a topological sort, organize the
 -    nodes into a tree structure, with as many non-dependent nodes
 -    set as siblings to each other as possible.
 -    
 -    returns nodes as 3-tuples (item, cycles, children).
 -    """
 -
 -    if not nodes:
 -        return None
 -    # a list of all currently independent subtrees as a tuple of
 -    # (root_node, set_of_all_tree_nodes, set_of_all_cycle_nodes_in_tree)
 -    # order of the list has no semantics for the algorithmic
 -    independents = []
 -    # in reverse topological order
 -    for node in reversed(nodes):
 -        # nodes subtree and cycles contain the node itself
 -        subtree = set([node])
 -        if node.cycles is not None:
 -            cycles = set(node.cycles)
 -        else:
 -            cycles = set()
 -        # get a set of dependent nodes of node and its cycles
 -        nodealldeps = node.all_deps()
 -        if nodealldeps:
 -            # iterate over independent node indexes in reverse order so we can efficiently remove them
 -            for index in xrange(len(independents) - 1, -1, -1):
 -                child, childsubtree, childcycles = independents[index]
 -                # if there is a dependency between this node and an independent node
 -                if (childsubtree.intersection(nodealldeps) or childcycles.intersection(node.dependencies)):
 -                    # prepend child to nodes children
 -                    # (append should be fine, but previous implemetation used prepend)
 -                    node.children[0:0] = [(child.item, [n.item for n in child.cycles or []], child.children)]
 -                    # merge childs subtree and cycles
 -                    subtree.update(childsubtree)
 -                    cycles.update(childcycles)
 -                    # remove the child from list of independent subtrees
 -                    independents[index:index+1] = []
 -        # add node as a new independent subtree
 -        independents.append((node, subtree, cycles))
 -    # choose an arbitrary node from list of all independent subtrees
 -    head = independents.pop()[0]
 -    # add all other independent subtrees as a child of the chosen root
 -    # used prepend [0:0] instead of extend to maintain exact behaviour of previous implementation
 -    head.children[0:0] = [(i[0].item, [n.item for n in i[0].cycles or []], i[0].children) for i in independents]
 -    return (head.item, [n.item for n in head.cycles or []], head.children)
+ def _find_cycles(edges):
+     cycles = {}
+     def traverse(node, cycle, goal):
+         for (n, key) in edges.edges_by_parent(node):
+             if key in cycle:
+                 continue
+             cycle.add(key)
+             if key is goal:
+                 cycset = set(cycle)
+                 for x in cycle:
+                     if x in cycles:
+                         existing_set = cycles[x]
+                         existing_set.update(cycset)
+                         for y in existing_set:
+                             cycles[y] = existing_set
+                         cycset = existing_set
+                     else:
+                         cycles[x] = cycset
+             else:
+                 traverse(key, cycle, goal)
+             cycle.pop()
+     for parent in edges.get_parents():
+         traverse(parent, set(), parent)
+     unique_cycles = set(tuple(s) for s in cycles.values())
+     
+     for cycle in unique_cycles:
+         edgecollection = [edge for edge in edges
+                           if edge[0] in cycle and edge[1] in cycle]
+         yield edgecollection