summaryrefslogtreecommitdiff
path: root/django/db/migrations/loader.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/migrations/loader.py')
-rw-r--r--django/db/migrations/loader.py91
1 files changed, 60 insertions, 31 deletions
diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py
index 93fb2c3bd5..81dcd06e04 100644
--- a/django/db/migrations/loader.py
+++ b/django/db/migrations/loader.py
@@ -8,11 +8,13 @@ from django.db.migrations.graph import MigrationGraph
from django.db.migrations.recorder import MigrationRecorder
from .exceptions import (
- AmbiguityError, BadMigrationError, InconsistentMigrationHistory,
+ AmbiguityError,
+ BadMigrationError,
+ InconsistentMigrationHistory,
NodeNotFoundError,
)
-MIGRATIONS_MODULE_NAME = 'migrations'
+MIGRATIONS_MODULE_NAME = "migrations"
class MigrationLoader:
@@ -41,7 +43,10 @@ class MigrationLoader:
"""
def __init__(
- self, connection, load=True, ignore_no_migrations=False,
+ self,
+ connection,
+ load=True,
+ ignore_no_migrations=False,
replace_migrations=True,
):
self.connection = connection
@@ -63,7 +68,7 @@ class MigrationLoader:
return settings.MIGRATION_MODULES[app_label], True
else:
app_package_name = apps.get_app_config(app_label).name
- return '%s.%s' % (app_package_name, MIGRATIONS_MODULE_NAME), False
+ return "%s.%s" % (app_package_name, MIGRATIONS_MODULE_NAME), False
def load_disk(self):
"""Load the migrations from all INSTALLED_APPS from disk."""
@@ -80,24 +85,22 @@ class MigrationLoader:
try:
module = import_module(module_name)
except ModuleNotFoundError as e:
- if (
- (explicit and self.ignore_no_migrations) or
- (not explicit and MIGRATIONS_MODULE_NAME in e.name.split('.'))
+ if (explicit and self.ignore_no_migrations) or (
+ not explicit and MIGRATIONS_MODULE_NAME in e.name.split(".")
):
self.unmigrated_apps.add(app_config.label)
continue
raise
else:
# Module is not a package (e.g. migrations.py).
- if not hasattr(module, '__path__'):
+ if not hasattr(module, "__path__"):
self.unmigrated_apps.add(app_config.label)
continue
# Empty directories are namespaces. Namespace packages have no
# __file__ and don't use a list for __path__. See
# https://docs.python.org/3/reference/import.html#namespace-packages
- if (
- getattr(module, '__file__', None) is None and
- not isinstance(module.__path__, list)
+ if getattr(module, "__file__", None) is None and not isinstance(
+ module.__path__, list
):
self.unmigrated_apps.add(app_config.label)
continue
@@ -106,16 +109,17 @@ class MigrationLoader:
reload(module)
self.migrated_apps.add(app_config.label)
migration_names = {
- name for _, name, is_pkg in pkgutil.iter_modules(module.__path__)
- if not is_pkg and name[0] not in '_~'
+ name
+ for _, name, is_pkg in pkgutil.iter_modules(module.__path__)
+ if not is_pkg and name[0] not in "_~"
}
# Load migrations
for migration_name in migration_names:
- migration_path = '%s.%s' % (module_name, migration_name)
+ migration_path = "%s.%s" % (module_name, migration_name)
try:
migration_module = import_module(migration_path)
except ImportError as e:
- if 'bad magic number' in str(e):
+ if "bad magic number" in str(e):
raise ImportError(
"Couldn't import %r as it appears to be a stale "
".pyc file." % migration_path
@@ -124,9 +128,12 @@ class MigrationLoader:
raise
if not hasattr(migration_module, "Migration"):
raise BadMigrationError(
- "Migration %s in app %s has no Migration class" % (migration_name, app_config.label)
+ "Migration %s in app %s has no Migration class"
+ % (migration_name, app_config.label)
)
- self.disk_migrations[app_config.label, migration_name] = migration_module.Migration(
+ self.disk_migrations[
+ app_config.label, migration_name
+ ] = migration_module.Migration(
migration_name,
app_config.label,
)
@@ -142,11 +149,14 @@ class MigrationLoader:
# Do the search
results = []
for migration_app_label, migration_name in self.disk_migrations:
- if migration_app_label == app_label and migration_name.startswith(name_prefix):
+ if migration_app_label == app_label and migration_name.startswith(
+ name_prefix
+ ):
results.append((migration_app_label, migration_name))
if len(results) > 1:
raise AmbiguityError(
- "There is more than one migration for '%s' with the prefix '%s'" % (app_label, name_prefix)
+ "There is more than one migration for '%s' with the prefix '%s'"
+ % (app_label, name_prefix)
)
elif not results:
raise KeyError(
@@ -181,7 +191,9 @@ class MigrationLoader:
if self.ignore_no_migrations:
return None
else:
- raise ValueError("Dependency on app with no migrations: %s" % key[0])
+ raise ValueError(
+ "Dependency on app with no migrations: %s" % key[0]
+ )
raise ValueError("Dependency on unknown app: %s" % key[0])
def add_internal_dependencies(self, key, migration):
@@ -191,7 +203,7 @@ class MigrationLoader:
"""
for parent in migration.dependencies:
# Ignore __first__ references to the same app.
- if parent[0] == key[0] and parent[1] != '__first__':
+ if parent[0] == key[0] and parent[1] != "__first__":
self.graph.add_dependency(migration, key, parent, skip_validation=True)
def add_external_dependencies(self, key, migration):
@@ -241,7 +253,9 @@ class MigrationLoader:
for key, migration in self.replacements.items():
# Get applied status of each of this migration's replacement
# targets.
- applied_statuses = [(target in self.applied_migrations) for target in migration.replaces]
+ applied_statuses = [
+ (target in self.applied_migrations) for target in migration.replaces
+ ]
# The replacing migration is only marked as applied if all of
# its replacement targets are.
if all(applied_statuses):
@@ -273,9 +287,11 @@ class MigrationLoader:
# Try to reraise exception with more detail.
if exc.node in reverse_replacements:
candidates = reverse_replacements.get(exc.node, set())
- is_replaced = any(candidate in self.graph.nodes for candidate in candidates)
+ is_replaced = any(
+ candidate in self.graph.nodes for candidate in candidates
+ )
if not is_replaced:
- tries = ', '.join('%s.%s' % c for c in candidates)
+ tries = ", ".join("%s.%s" % c for c in candidates)
raise NodeNotFoundError(
"Migration {0} depends on nonexistent node ('{1}', '{2}'). "
"Django tried to replace migration {1}.{2} with any of [{3}] "
@@ -283,7 +299,7 @@ class MigrationLoader:
"are already applied.".format(
exc.origin, exc.node[0], exc.node[1], tries
),
- exc.node
+ exc.node,
) from exc
raise
self.graph.ensure_not_cyclic()
@@ -304,12 +320,17 @@ class MigrationLoader:
# Skip unapplied squashed migrations that have all of their
# `replaces` applied.
if parent in self.replacements:
- if all(m in applied for m in self.replacements[parent].replaces):
+ if all(
+ m in applied for m in self.replacements[parent].replaces
+ ):
continue
raise InconsistentMigrationHistory(
"Migration {}.{} is applied before its dependency "
"{}.{} on database '{}'.".format(
- migration[0], migration[1], parent[0], parent[1],
+ migration[0],
+ migration[1],
+ parent[0],
+ parent[1],
connection.alias,
)
)
@@ -326,7 +347,9 @@ class MigrationLoader:
if app_label in seen_apps:
conflicting_apps.add(app_label)
seen_apps.setdefault(app_label, set()).add(migration_name)
- return {app_label: sorted(seen_apps[app_label]) for app_label in conflicting_apps}
+ return {
+ app_label: sorted(seen_apps[app_label]) for app_label in conflicting_apps
+ }
def project_state(self, nodes=None, at_end=True):
"""
@@ -335,7 +358,9 @@ class MigrationLoader:
See graph.make_state() for the meaning of "nodes" and "at_end".
"""
- return self.graph.make_state(nodes=nodes, at_end=at_end, real_apps=self.unmigrated_apps)
+ return self.graph.make_state(
+ nodes=nodes, at_end=at_end, real_apps=self.unmigrated_apps
+ )
def collect_sql(self, plan):
"""
@@ -345,9 +370,13 @@ class MigrationLoader:
statements = []
state = None
for migration, backwards in plan:
- with self.connection.schema_editor(collect_sql=True, atomic=migration.atomic) as schema_editor:
+ with self.connection.schema_editor(
+ collect_sql=True, atomic=migration.atomic
+ ) as schema_editor:
if state is None:
- state = self.project_state((migration.app_label, migration.name), at_end=False)
+ state = self.project_state(
+ (migration.app_label, migration.name), at_end=False
+ )
if not backwards:
state = migration.apply(state, schema_editor, collect_sql=True)
else: