From 9756c334294ad573d887b449e2fe1cc87387af40 Mon Sep 17 00:00:00 2001 From: wtkm11 Date: Sat, 25 Apr 2020 14:54:20 -0400 Subject: [PATCH] Fixed #31504 -- Allowed calling makemigrations without an active database connection. --- .../core/management/commands/makemigrations.py | 14 +++++++++++--- docs/ref/django-admin.txt | 6 ++++++ docs/releases/3.2.txt | 4 ++++ tests/migrations/test_commands.py | 16 +++++++++++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py index 7cee2c120e3..709abaa8d6b 100644 --- a/django/core/management/commands/makemigrations.py +++ b/django/core/management/commands/makemigrations.py @@ -1,5 +1,6 @@ import os import sys +import warnings from itertools import takewhile from django.apps import apps @@ -7,7 +8,7 @@ from django.conf import settings from django.core.management.base import ( BaseCommand, CommandError, no_translations, ) -from django.db import DEFAULT_DB_ALIAS, connections, router +from django.db import DEFAULT_DB_ALIAS, OperationalError, connections, router from django.db.migrations import Migration from django.db.migrations.autodetector import MigrationAutodetector from django.db.migrations.loader import MigrationLoader @@ -98,8 +99,15 @@ class Command(BaseCommand): for app_label in consistency_check_labels for model in apps.get_app_config(app_label).get_models() )): - loader.check_consistent_history(connection) - + try: + loader.check_consistent_history(connection) + except OperationalError as error: + warnings.warn( + "Got an error checking a consistent migration history " + "performed for database connection '%s': %s." + % (alias, error), + RuntimeWarning, + ) # Before anything else, see if there's conflicting apps and drop out # hard if there are any and they don't want to merge conflicts = loader.detect_conflicts() diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 4cd477b7a85..46e048e6485 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -824,6 +824,12 @@ Generate migration files without Django version and timestamp header. Makes ``makemigrations`` exit with a non-zero status when model changes without migrations are detected. +.. versionchanged:: 3.2 + + Support for calling ``makemigrations`` without an active database + connection was added. In that case, check for a consistent migration + history is skipped. + ``migrate`` ----------- diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt index b1a0e19edb2..1603f8f1b30 100644 --- a/docs/releases/3.2.txt +++ b/docs/releases/3.2.txt @@ -157,6 +157,10 @@ Management Commands * :djadmin:`loaddata` now supports fixtures stored in XZ archives (``.xz``) and LZMA archives (``.lzma``). +* :djadmin:`makemigrations` can now be called without an active database + connection. In that case, check for a consistent migration history is + skipped. + Migrations ~~~~~~~~~~ diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index a0b33ca6f5f..69fdf287476 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -8,7 +8,8 @@ from unittest import mock from django.apps import apps from django.core.management import CommandError, call_command from django.db import ( - ConnectionHandler, DatabaseError, connection, connections, models, + ConnectionHandler, DatabaseError, OperationalError, connection, + connections, models, ) from django.db.backends.base.schema import BaseDatabaseSchemaEditor from django.db.backends.utils import truncate_name @@ -1555,6 +1556,19 @@ class MakeMigrationsTests(MigrationTestBase): with self.assertRaisesMessage(InconsistentMigrationHistory, msg): call_command("makemigrations") + def test_makemigrations_inconsistent_history_db_failure(self): + msg = ( + "Got an error checking a consistent migration history performed " + "for database connection 'default': could not connect to server" + ) + with mock.patch( + 'django.db.migrations.loader.MigrationLoader.check_consistent_history', + side_effect=OperationalError('could not connect to server'), + ): + with self.temporary_migration_module(): + with self.assertWarnsMessage(RuntimeWarning, msg): + call_command('makemigrations', verbosity=0) + @mock.patch('builtins.input', return_value='1') @mock.patch('django.db.migrations.questioner.sys.stdin', mock.MagicMock(encoding=sys.getdefaultencoding())) def test_makemigrations_auto_now_add_interactive(self, *args):