MCPcopy
hub / github.com/django/django / MigrationGraph

Class MigrationGraph

django/db/migrations/graph.py:64–336  ·  view source on GitHub ↗

Represent the digraph of all migrations in a project. Each migration is a node, and each dependency is an edge. There are no implicit dependencies between numbered migrations - the numbering is merely a convention to aid file listing. Every new numbered migration has a declared

Source from the content-addressed store, hash-verified

62
63
64class MigrationGraph:
65 """
66 Represent the digraph of all migrations in a project.
67
68 Each migration is a node, and each dependency is an edge. There are
69 no implicit dependencies between numbered migrations - the numbering is
70 merely a convention to aid file listing. Every new numbered migration
71 has a declared dependency to the previous number, meaning that VCS
72 branch merges can be detected and resolved.
73
74 Migrations files can be marked as replacing another set of migrations -
75 this is to support the "squash" feature. The graph handler isn't
76 responsible for these; instead, the code to load them in here should
77 examine the migration files and if the replaced migrations are all either
78 unapplied or not present, it should ignore the replaced ones, load in just
79 the replacing migration, and repoint any dependencies that pointed to the
80 replaced migrations to point to the replacing one.
81
82 A node should be a tuple: (app_path, migration_name). The tree
83 special-cases things within an app - namely, root nodes and leaf nodes
84 ignore dependencies to other apps.
85 """
86
87 def __init__(self):
88 self.node_map = {}
89 self.nodes = {}
90
91 def add_node(self, key, migration):
92 assert key not in self.node_map
93 node = Node(key)
94 self.node_map[key] = node
95 self.nodes[key] = migration
96
97 def add_dummy_node(self, key, origin, error_message):
98 node = DummyNode(key, origin, error_message)
99 self.node_map[key] = node
100 self.nodes[key] = None
101
102 def add_dependency(self, migration, child, parent, skip_validation=False):
103 """
104 This may create dummy nodes if they don't yet exist. If
105 `skip_validation=True`, validate_consistency() should be called
106 afterward.
107 """
108 if child not in self.nodes:
109 error_message = (
110 "Migration %s dependencies reference nonexistent"
111 " child node %r" % (migration, child)
112 )
113 self.add_dummy_node(child, migration, error_message)
114 if parent not in self.nodes:
115 error_message = (
116 "Migration %s dependencies reference nonexistent"
117 " parent node %r" % (migration, parent)
118 )
119 self.add_dummy_node(parent, migration, error_message)
120 self.node_map[child].add_parent(self.node_map[parent])
121 self.node_map[parent].add_child(self.node_map[child])

Calls

no outgoing calls