diff options
Diffstat (limited to 'django/db/migrations/loader.py')
| -rw-r--r-- | django/db/migrations/loader.py | 91 |
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: |
