summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/migrations/autodetector.py3
-rw-r--r--django/utils/topological_sort.py (renamed from django/db/migrations/topological_sort.py)6
-rw-r--r--tests/utils_tests/test_topological_sort.py24
3 files changed, 30 insertions, 3 deletions
diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py
index 3d3eeb9230..0dc1c77c53 100644
--- a/django/db/migrations/autodetector.py
+++ b/django/db/migrations/autodetector.py
@@ -12,8 +12,7 @@ from django.db.migrations.questioner import MigrationQuestioner
from django.db.migrations.utils import (
COMPILED_REGEX_TYPE, RegexObject, get_migration_name_timestamp,
)
-
-from .topological_sort import stable_topological_sort
+from django.utils.topological_sort import stable_topological_sort
class MigrationAutodetector:
diff --git a/django/db/migrations/topological_sort.py b/django/utils/topological_sort.py
index e0a22c9236..3f8ea0f2e4 100644
--- a/django/db/migrations/topological_sort.py
+++ b/django/utils/topological_sort.py
@@ -1,3 +1,7 @@
+class CyclicDependencyError(ValueError):
+ pass
+
+
def topological_sort_as_sets(dependency_graph):
"""
Variation of Kahn's algorithm (1962) that returns sets.
@@ -13,7 +17,7 @@ def topological_sort_as_sets(dependency_graph):
current = {node for node, deps in todo.items() if not deps}
if not current:
- raise ValueError('Cyclic dependency in graph: {}'.format(
+ raise CyclicDependencyError('Cyclic dependency in graph: {}'.format(
', '.join(repr(x) for x in todo.items())))
yield current
diff --git a/tests/utils_tests/test_topological_sort.py b/tests/utils_tests/test_topological_sort.py
new file mode 100644
index 0000000000..ed8f9fd5a6
--- /dev/null
+++ b/tests/utils_tests/test_topological_sort.py
@@ -0,0 +1,24 @@
+from django.test import SimpleTestCase
+from django.utils.topological_sort import (
+ CyclicDependencyError, stable_topological_sort, topological_sort_as_sets,
+)
+
+
+class TopologicalSortTests(SimpleTestCase):
+
+ def test_basic(self):
+ dependency_graph = {
+ 1: {2, 3},
+ 2: set(),
+ 3: set(),
+ 4: {5, 6},
+ 5: set(),
+ 6: {5},
+ }
+ self.assertEqual(list(topological_sort_as_sets(dependency_graph)), [{2, 3, 5}, {1, 6}, {4}])
+ self.assertEqual(stable_topological_sort([1, 2, 3, 4, 5, 6], dependency_graph), [2, 3, 5, 1, 6, 4])
+
+ def test_cyclic_dependency(self):
+ msg = 'Cyclic dependency in graph: '
+ with self.assertRaisesMessage(CyclicDependencyError, msg):
+ list(topological_sort_as_sets({1: {2}, 2: {1}}))