From: Mike Bayer Date: Sun, 4 Apr 2010 14:38:29 +0000 (-0400) Subject: merge default branch X-Git-Tag: rel_0_6_0~64 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f05b5b0bda7b21a585f3252016d2e74c361b6233;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git merge default branch --- f05b5b0bda7b21a585f3252016d2e74c361b6233 diff --cc lib/sqlalchemy/orm/mapper.py index ac35ce49b7,56cb1ef4d5..fbb66a7dd2 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@@ -1354,18 -1313,29 +1347,29 @@@ class Mapper(object) "New instance %s with identity key %s conflicts " "with persistent instance %s" % (state_str(state), instance_key, state_str(existing))) - + self._log_debug( - "detected row switch for identity %s. will update %s, remove %s from " - "transaction", instance_key, state_str(state), state_str(existing)) - + "detected row switch for identity %s. " + "will update %s, remove %s from " + "transaction", instance_key, + state_str(state), state_str(existing)) + # remove the "delete" flag from the existing element - uowtransaction.set_row_switch(existing) + uowtransaction.remove_state_actions(existing) - row_switches[state] = existing - + row_switch = existing + + tups.append( + (state, + mapper, + conn, + has_identity, + instance_key, + row_switch) + ) + table_to_mapper = self._sorted_tables - for table in table_to_mapper.iterkeys(): + for table in table_to_mapper: insert = [] update = [] diff --cc lib/sqlalchemy/topological.py index 8886bcbf7c,d061aec043..5fc982ae0d --- a/lib/sqlalchemy/topological.py +++ b/lib/sqlalchemy/topological.py @@@ -103,33 -215,82 +103,32 @@@ 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.append(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, [], parent) +def find_cycles(tuples, allitems): + # straight from gvr with some mods + todo = set(allitems) + edges = _EdgeCollection() - unique_cycles = set(tuple(s) for s in cycles.values()) + for t in tuples: + todo.update(t) + edges.add(t) - for cycle in unique_cycles: - edgecollection = [edge for edge in edges - if edge[0] in cycle and edge[1] in cycle] - yield edgecollection + output = set() + + while todo: + node = todo.pop() + stack = [node] + while stack: + top = stack[-1] + for node in edges.outgoing(top): + if node in stack: + cyc = stack[stack.index(node):] + todo.difference_update(cyc) + output.update(cyc) + + if node in todo: + stack.append(node) + todo.remove(node) + break + else: + node = stack.pop() + return output -