def test_topological_sort_2(self): """ Does another basic topological sort work? """ pairs = [(1, 2), (1, 3), (2, 4), (3, 4), (5, 6), (4, 5)] result, has_cycles = topological_sort(pairs) self.assertTrue(not has_cycles) self.assertEqual(result, [1, 2, 3, 4, 5, 6])
def test_topological_sort_2(self): """ Does another basic topological sort work? """ pairs = [ (1,2), (1,3), (2,4), (3,4), (5,6), (4,5) ] result, has_cycles = topological_sort(pairs) self.assert_(not has_cycles) self.assertEquals(result, [1, 2, 3, 4, 5, 6])
def test_topological_sort_1(self): """ Does a basic topological sort work? """ pairs = [(1, 2), (3, 5), (4, 6), (1, 3), (1, 4), (1, 6), (2, 4)] result, has_cycles = topological_sort(pairs) self.assert_(not has_cycles) self.assertEquals(result, [1, 2, 3, 4, 5, 6])
def before_after_wildcard_sort(items): """ Sort a sequence of items with 'before', 'after', and 'id' attributes. The sort is topological. If an item does not specify a 'before' or 'after', it is placed after the preceding item. Simple wildcards are allowed in the 'before' or 'after' attributes. The asterisk must be the last character in the string, so the form "text*" will match any id that starts with "text". If a cycle is found in the dependencies, a warning is logged and the order of the items is undefined. """ # Handle a degenerate case for which the logic below will fail (because # prev_item will not be set). if len(items) < 2: return items # Build a set of pairs representing the graph. item_map = dict((item.id, item) for item in items if item.id) pairs = [] prev_item = None for item in items: # Attempt to use 'before' and 'after' to make pairs. new_pairs = [] if hasattr(item, 'before') and item.before: if item.before.endswith("*"): for child in find_wildcard_matches(item_map, item.before): # print "%s should be before %s" % (item.id, child.id) new_pairs.append((item, child)) else: child = item_map.get(item.before) if child: new_pairs.append((item, child)) if hasattr(item, 'after') and item.after: if item.after.endswith("*"): for parent in find_wildcard_matches(item_map, item.after): # print "%s should be after %s" % (item.id, parent.id) new_pairs.append((parent, item)) else: parent = item_map.get(item.after) if parent: new_pairs.append((parent, item)) # If we have any pairs, use them. Otherwise, use the previous unmatched # item as a parent, if possible. if new_pairs: pairs.extend(new_pairs) else: if prev_item: pairs.append((prev_item, item)) prev_item = item # Now perform the actual sort. result, has_cycle = topological_sort(pairs) if has_cycle: logger.warning('Cycle in before/after sort for items %r', items) return result
def test_topological_sort_3(self): """ Does cycle detection work? """ pairs = [(1, 2), (2, 3), (3, 1)] result, has_cycles = topological_sort(pairs) self.assertTrue(has_cycles)
def test_topological_sort_3(self): """ Does cycle detection work? """ pairs = [ (1,2), (2,3), (3,1) ] result, has_cycles = topological_sort(pairs) self.assert_(has_cycles)