attribute, provided the name is the same as that
of the entity mapped column.
+ - Fixed bug in unit of work whereby detection of
+ "cycles" among classes in highly interlinked patterns
+ would not produce a deterministic
+ result; thereby sometimes missing some nodes that
+ should be considered cycles and causing further
+ issues down the road. Note this bug is in 0.6
+ also; not backported at the moment.
+ [ticket:2282]
+
- Fixed a variety of synonym()-related regressions
from 0.6:
- making a synonym against a synonym now works.
def find_cycles(tuples, allitems):
# straight from gvr with some mods
- todo = set(allitems)
edges = util.defaultdict(set)
for parent, child in tuples:
edges[parent].add(child)
+ nodes_to_test = set(edges)
output = set()
- while todo:
- node = todo.pop()
+ # we'd like to find all nodes that are
+ # involved in cycles, so we do the full
+ # pass through the whole thing for each
+ # node in the original list.
+
+ # we can go just through parent edge nodes.
+ # if a node is only a child and never a parent,
+ # by definition it can't be part of a cycle. same
+ # if it's not in the edges at all.
+ for node in nodes_to_test:
stack = [node]
+ todo = nodes_to_test.difference(stack)
while stack:
top = stack[-1]
for node in edges[top]:
node5,
node6,
])
- eq_(topological.find_cycles(tuples, allnodes), set(['node1',
- 'node2', 'node4']))
+ # node6 only became present here once [ticket:2282] was addressed.
+ eq_(
+ topological.find_cycles(tuples, allnodes),
+ set(['node1','node2', 'node4', 'node6'])
+ )
def test_find_multiple_cycles_three(self):
node1 = 'node1'
node6,
])
eq_(topological.find_cycles(tuples, allnodes), allnodes)
+
+ def test_find_multiple_cycles_four(self):
+ tuples = [
+ ('node6', 'node2'),
+ ('node15', 'node19'),
+ ('node19', 'node2'), ('node4', 'node10'),
+ ('node15', 'node13'),
+ ('node17', 'node11'), ('node1', 'node19'), ('node15', 'node8'),
+ ('node6', 'node20'), ('node14', 'node11'), ('node6', 'node14'),
+ ('node11', 'node2'), ('node10', 'node20'), ('node1', 'node11'),
+ ('node20', 'node19'), ('node4', 'node20'), ('node15', 'node20'),
+ ('node9', 'node19'), ('node11', 'node10'), ('node11', 'node19'),
+ ('node13', 'node6'), ('node3', 'node15'), ('node9', 'node11'),
+ ('node4', 'node17'), ('node2', 'node20'), ('node19', 'node10'),
+ ('node8', 'node4'), ('node11', 'node3'), ('node6', 'node1')
+ ]
+ allnodes = ['node%d' % i for i in xrange(1, 21)]
+ eq_(
+ topological.find_cycles(tuples, allnodes),
+ set(['node11', 'node10', 'node13', 'node15', 'node14', 'node17',
+ 'node19', 'node20', 'node8', 'node1', 'node3',
+ 'node2', 'node4', 'node6'])
+ )