summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Walker <brad@bradmwalker.com>2014-11-12 16:06:12 -0700
committerTim Graham <timograham@gmail.com>2014-11-20 14:33:30 -0500
commit54d3dcbc51819ea0e36bb4dbe7de1a1e33f62c4d (patch)
tree34e33572ca362dcb4cc6bc78f62eb9ac345531f7
parentcfa26f29bdd9b0f82211e6f5ff7f4cd63bd66150 (diff)
Removed reduce() usage in makemigrations; refs #23796.
A lambda all_items_equal() replaced a reduce() that was broken for potential 3+-way merges. A reduce(operator.eq, ...) accumulates bools and can't generically check equality of all items in a sequence: >>> bool(reduce(operator.eq, [('migrations', '0001_initial')] * 3)) False The code now counts the number of common ancestors to calculate slice offsets for the branches. Each branch shares the same number of common ancestors. The common_ancestor for loop statement had incomplete branch coverage.
-rw-r--r--django/core/management/commands/makemigrations.py28
1 files changed, 11 insertions, 17 deletions
diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py
index 0740d55f5a..bc684f42b7 100644
--- a/django/core/management/commands/makemigrations.py
+++ b/django/core/management/commands/makemigrations.py
@@ -1,6 +1,6 @@
+from itertools import takewhile
import sys
import os
-import operator
from django.apps import apps
from django.core.management.base import BaseCommand, CommandError
@@ -11,7 +11,7 @@ from django.db.migrations.questioner import MigrationQuestioner, InteractiveMigr
from django.db.migrations.state import ProjectState
from django.db.migrations.writer import MigrationWriter
from django.utils.six import iteritems
-from django.utils.six.moves import reduce
+from django.utils.six.moves import zip
class Command(BaseCommand):
@@ -187,24 +187,18 @@ class Command(BaseCommand):
migration = loader.get_migration(app_label, migration_name)
migration.ancestry = loader.graph.forwards_plan((app_label, migration_name))
merge_migrations.append(migration)
- common_ancestor = None
- for level in zip(*[m.ancestry for m in merge_migrations]):
- if reduce(operator.eq, level):
- common_ancestor = level[0]
- else:
- break
- if common_ancestor is None:
+ all_items_equal = lambda seq: all(item == seq[0] for item in seq[1:])
+ merge_migrations_generations = zip(*[m.ancestry for m in merge_migrations])
+ common_ancestor_count = sum(1 for common_ancestor_generation
+ in takewhile(all_items_equal, merge_migrations_generations))
+ if not common_ancestor_count:
raise ValueError("Could not find common ancestor of %s" % migration_names)
# Now work out the operations along each divergent branch
for migration in merge_migrations:
- migration.branch = migration.ancestry[
- (migration.ancestry.index(common_ancestor) + 1):
- ]
- migration.merged_operations = []
- for node_app, node_name in migration.branch:
- migration.merged_operations.extend(
- loader.get_migration(node_app, node_name).operations
- )
+ migration.branch = migration.ancestry[common_ancestor_count:]
+ migrations_ops = (loader.get_migration(node_app, node_name).operations
+ for node_app, node_name in migration.branch)
+ migration.merged_operations = sum(migrations_ops, [])
# In future, this could use some of the Optimizer code
# (can_optimize_through) to automatically see if they're
# mergeable. For now, we always just prompt the user.