diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py index 4aaa91ef33..7b779819e9 100644 --- a/django/db/migrations/executor.py +++ b/django/db/migrations/executor.py @@ -25,9 +25,9 @@ class MigrationExecutor: """ plan = [] if clean_start: - applied = set() + applied = {} else: - applied = set(self.loader.applied_migrations) + applied = dict(self.loader.applied_migrations) for target in targets: # If the target is (app_label, None), that means unmigrate everything if target[1] is None: @@ -36,7 +36,7 @@ class MigrationExecutor: for migration in self.loader.graph.backwards_plan(root): if migration in applied: plan.append((self.loader.graph.nodes[migration], True)) - applied.remove(migration) + applied.pop(migration) # If the migration is already applied, do backwards mode, # otherwise do forwards mode. elif target in applied: @@ -53,12 +53,12 @@ class MigrationExecutor: for migration in self.loader.graph.backwards_plan(node): if migration in applied: plan.append((self.loader.graph.nodes[migration], True)) - applied.remove(migration) + applied.pop(migration) else: for migration in self.loader.graph.forwards_plan(target): if migration not in applied: plan.append((self.loader.graph.nodes[migration], False)) - applied.add(migration) + applied[migration] = self.loader.graph.nodes[migration] return plan def _create_project_state(self, with_applied_migrations=False): diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index 54e1cefb00..8c308621d2 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -206,7 +206,7 @@ class MigrationLoader: self.load_disk() # Load database data if self.connection is None: - self.applied_migrations = set() + self.applied_migrations = {} else: recorder = MigrationRecorder(self.connection) self.applied_migrations = recorder.applied_migrations() @@ -232,9 +232,9 @@ class MigrationLoader: # Ensure the replacing migration is only marked as applied if all of # its replacement targets are. if all(applied_statuses): - self.applied_migrations.add(key) + self.applied_migrations[key] = migration else: - self.applied_migrations.discard(key) + self.applied_migrations.pop(key, None) # A replacing migration can be used if either all or none of its # replacement targets have been applied. if all(applied_statuses) or (not any(applied_statuses)): diff --git a/django/db/migrations/recorder.py b/django/db/migrations/recorder.py index ad5435d906..c3ed4148e7 100644 --- a/django/db/migrations/recorder.py +++ b/django/db/migrations/recorder.py @@ -69,13 +69,16 @@ class MigrationRecorder: raise MigrationSchemaMissing("Unable to create the django_migrations table (%s)" % exc) def applied_migrations(self): - """Return a set of (app, name) of applied migrations.""" + """ + Return a dict mapping (app_name, migration_name) to Migration instances + for all applied migrations. + """ if self.has_table(): - return {tuple(x) for x in self.migration_qs.values_list('app', 'name')} + return {(migration.app, migration.name): migration for migration in self.migration_qs} else: # If the django_migrations table doesn't exist, then no migrations # are applied. - return set() + return {} def record_applied(self, app, name): """Record that a migration was applied.""" diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py index 8bb4f83c5f..ddba8d12e8 100644 --- a/tests/migrations/test_executor.py +++ b/tests/migrations/test_executor.py @@ -711,7 +711,11 @@ class ExecutorUnitTests(SimpleTestCase): graph.add_dependency(None, a2, a1) executor = MigrationExecutor(None) - executor.loader = FakeLoader(graph, {a1, b1, a2}) + executor.loader = FakeLoader(graph, { + a1: a1_impl, + b1: b1_impl, + a2: a2_impl, + }) plan = executor.migration_plan({a1}) @@ -754,7 +758,14 @@ class ExecutorUnitTests(SimpleTestCase): graph.add_dependency(None, b2, a2) executor = MigrationExecutor(None) - executor.loader = FakeLoader(graph, {a1, b1, a2, b2, a3, a4}) + executor.loader = FakeLoader(graph, { + a1: a1_impl, + b1: b1_impl, + a2: a2_impl, + b2: b2_impl, + a3: a3_impl, + a4: a4_impl, + }) plan = executor.migration_plan({a1}) @@ -791,7 +802,10 @@ class ExecutorUnitTests(SimpleTestCase): graph.add_dependency(None, c1, a1) executor = MigrationExecutor(None) - executor.loader = FakeLoader(graph, {a1, b1}) + executor.loader = FakeLoader(graph, { + a1: a1_impl, + b1: b1_impl, + }) plan = executor.migration_plan({a1}) diff --git a/tests/migrations/test_loader.py b/tests/migrations/test_loader.py index e3a635dc63..0f0a590e7c 100644 --- a/tests/migrations/test_loader.py +++ b/tests/migrations/test_loader.py @@ -265,7 +265,7 @@ class LoaderTests(TestCase): def num_nodes(): plan = set(loader.graph.forwards_plan(('migrations', '7_auto'))) - return len(plan - loader.applied_migrations) + return len(plan - loader.applied_migrations.keys()) # Empty database: use squashed migration loader.build_graph() @@ -339,7 +339,7 @@ class LoaderTests(TestCase): loader.build_graph() plan = set(loader.graph.forwards_plan(('app1', '4_auto'))) - plan = plan - loader.applied_migrations + plan = plan - loader.applied_migrations.keys() expected_plan = { ('app2', '1_squashed_2'), ('app1', '3_auto'), @@ -358,7 +358,7 @@ class LoaderTests(TestCase): def num_nodes(): plan = set(loader.graph.forwards_plan(('migrations', '7_auto'))) - return len(plan - loader.applied_migrations) + return len(plan - loader.applied_migrations.keys()) # Empty database: use squashed migration loader.build_graph() @@ -466,7 +466,7 @@ class LoaderTests(TestCase): # Load with nothing applied: both migrations squashed. loader.build_graph() plan = set(loader.graph.forwards_plan(('app1', '4_auto'))) - plan = plan - loader.applied_migrations + plan = plan - loader.applied_migrations.keys() expected_plan = { ('app1', '1_auto'), ('app2', '1_squashed_2'), @@ -480,7 +480,7 @@ class LoaderTests(TestCase): recorder.record_applied('app1', '2_auto') loader.build_graph() plan = set(loader.graph.forwards_plan(('app1', '4_auto'))) - plan = plan - loader.applied_migrations + plan = plan - loader.applied_migrations.keys() expected_plan = { ('app2', '1_squashed_2'), ('app1', '3_auto'), @@ -492,7 +492,7 @@ class LoaderTests(TestCase): recorder.record_applied('app2', '1_auto') loader.build_graph() plan = set(loader.graph.forwards_plan(('app1', '4_auto'))) - plan = plan - loader.applied_migrations + plan = plan - loader.applied_migrations.keys() expected_plan = { ('app2', '2_auto'), ('app1', '3_auto'),