]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- CircularDependencyError now has .cycles and .edges
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 29 Sep 2010 06:11:38 +0000 (02:11 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 29 Sep 2010 06:11:38 +0000 (02:11 -0400)
members, which are the set of elements involved in
one or more cycles, and the set of edges as 2-tuples.
[ticket:1890]

CHANGES
lib/sqlalchemy/exc.py
lib/sqlalchemy/topological.py
test/base/test_dependency.py

diff --git a/CHANGES b/CHANGES
index 38fd7443bf4f0eb80f3e78459b9bbe7413b00d71..150cfbfa4f66a06ff28df49aa29452b06ddcce91 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -162,6 +162,12 @@ CHANGES
    - the logging message emitted by the engine when
      a connection is first used is now "BEGIN (implicit)" 
      to emphasize that DBAPI has no explicit begin().
+
+- misc
+   - CircularDependencyError now has .cycles and .edges
+     members, which are the set of elements involved in
+     one or more cycles, and the set of edges as 2-tuples.  
+     [ticket:1890]
      
 0.6.4
 =====
index 003969f56ce50168b76d8158da862a81021c01dd..a9bcb7a7ef6b6780df4d34d1b0ed949ce1d8ff2e 100644 (file)
@@ -26,7 +26,11 @@ class ArgumentError(SQLAlchemyError):
 
 class CircularDependencyError(SQLAlchemyError):
     """Raised by topological sorts when a circular dependency is detected"""
-
+    def __init__(self, message, cycles, edges):
+        message += ": cycles: %r all edges: %r" % (cycles, edges)
+        super(CircularDependencyError, self).__init__(message)
+        self.cycles = cycles
+        self.edges = edges
 
 class CompileError(SQLAlchemyError):
     """Raised when an error occurs during SQL compilation"""
index 6c3e90d981ffd58a9c0c91398554c363062d14e1..9386f73354a304e5fa842cc6c4e4b776430b1a2f 100644 (file)
@@ -8,6 +8,7 @@
 
 from sqlalchemy.exc import CircularDependencyError
 from sqlalchemy import util
+import itertools
 
 __all__ = ['sort', 'sort_as_subsets', 'find_cycles']
 
@@ -27,8 +28,10 @@ def sort_as_subsets(tuples, allitems):
 
         if not output:
             raise CircularDependencyError(
-                    "Circular dependency detected: cycles: %r all edges: %s" % 
-                    (find_cycles(tuples, allitems), _dump_edges(edges, True)))
+                    "Circular dependency detected",
+                    find_cycles(tuples, allitems), 
+                    _gen_edges(edges)
+                )
 
         todo.difference_update(output)
         yield output
@@ -72,14 +75,11 @@ def find_cycles(tuples, allitems):
                 node = stack.pop()
     return output
 
-def _dump_edges(edges, reverse):
-    l = []
-    for left in edges:
-        for right in edges[left]:
-            if reverse:
-                l.append((right, left))
-            else:
-                l.append((left, right))
-    return repr(l)
-
-
+def _gen_edges(edges):
+    return set(itertools.chain(
+                *[
+                    [
+                        (right, left) for right in edges[left]
+                    ] for left in edges
+                ]
+            ))
index aa4410576bacb4b0b83fe4d39bd192703b3b72c6..9fddfc47ffedeef31ff4b1d21d80a0a4daac7fa9 100644 (file)
@@ -84,10 +84,16 @@ class DependencySortTest(TestBase):
             (node4, node1),
             ]
         allitems = self._nodes_from_tuples(tuples)
-        assert_raises(exc.CircularDependencyError, list,
-                      topological.sort(tuples, allitems))
 
-        # TODO: test find_cycles
+        try:
+            list(topological.sort(tuples, allitems))
+            assert False
+        except exc.CircularDependencyError, err:
+            eq_(err.cycles, set(['node1', 'node3', 'node2', 'node5',
+                'node4']))
+            eq_(err.edges, set([('node3', 'node1'), ('node4', 'node1'),
+                ('node2', 'node3'), ('node1', 'node2'), 
+                ('node4','node5'), ('node5', 'node4')]))
 
     def test_raise_on_cycle_two(self):
 
@@ -101,10 +107,15 @@ class DependencySortTest(TestBase):
         tuples = [(node1, node2), (node3, node1), (node2, node4),
                   (node3, node2), (node2, node3)]
         allitems = self._nodes_from_tuples(tuples)
-        assert_raises(exc.CircularDependencyError, list,
-                      topological.sort(tuples, allitems))
 
-        # TODO: test find_cycles
+        try:
+            list(topological.sort(tuples, allitems))
+            assert False
+        except exc.CircularDependencyError, err:
+            eq_(err.cycles, set(['node1', 'node3', 'node2']))
+            eq_(err.edges, set([('node3', 'node1'), ('node2', 'node3'),
+                ('node3', 'node2'), ('node1', 'node2'), 
+                ('node2','node4')]))
 
     def test_raise_on_cycle_three(self):
         question, issue, providerservice, answer, provider = \