Fixed #29470 -- Logged makemigrations automatic decisions in non-interactive mode.

This commit is contained in:
Jacob Walls 2021-08-06 09:17:13 -04:00 committed by Mariusz Felisiak
parent 241ba23870
commit 32f1fe5f89
4 changed files with 62 additions and 6 deletions

View File

@ -146,7 +146,12 @@ class Command(BaseCommand):
if self.interactive: if self.interactive:
questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run) questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
else: else:
questioner = NonInteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run) questioner = NonInteractiveMigrationQuestioner(
specified_apps=app_labels,
dry_run=self.dry_run,
verbosity=self.verbosity,
log=self.log,
)
# Set up autodetector # Set up autodetector
autodetector = MigrationAutodetector( autodetector = MigrationAutodetector(
loader.project_state(), loader.project_state(),

View File

@ -258,15 +258,47 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
class NonInteractiveMigrationQuestioner(MigrationQuestioner): class NonInteractiveMigrationQuestioner(MigrationQuestioner):
def __init__(
self, defaults=None, specified_apps=None, dry_run=None, verbosity=1,
log=None,
):
self.verbosity = verbosity
self.log = log
super().__init__(
defaults=defaults, specified_apps=specified_apps, dry_run=dry_run,
)
def log_lack_of_migration(self, field_name, model_name, reason):
if self.verbosity > 0:
self.log(
f"Field '{field_name}' on model '{model_name}' not migrated: "
f"{reason}."
)
def ask_not_null_addition(self, field_name, model_name): def ask_not_null_addition(self, field_name, model_name):
# We can't ask the user, so act like the user aborted. # We can't ask the user, so act like the user aborted.
self.log_lack_of_migration(
field_name,
model_name,
'it is impossible to add a non-nullable field without specifying '
'a default',
)
sys.exit(3) sys.exit(3)
def ask_not_null_alteration(self, field_name, model_name): def ask_not_null_alteration(self, field_name, model_name):
# We can't ask the user, so set as not provided. # We can't ask the user, so set as not provided.
self.log(
f"Field '{field_name}' on model '{model_name}' given a default of "
f"NOT PROVIDED and must be corrected."
)
return NOT_PROVIDED return NOT_PROVIDED
def ask_auto_now_add_addition(self, field_name, model_name): def ask_auto_now_add_addition(self, field_name, model_name):
# We can't ask the user, so act like the user aborted. # We can't ask the user, so act like the user aborted.
self.log_lack_of_migration(
field_name,
model_name,
"it is impossible to add a field with 'auto_now_add=True' without "
"specifying a default",
)
sys.exit(3) sys.exit(3)

View File

@ -163,7 +163,8 @@ Logging
Management Commands Management Commands
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
* ... * :option:`makemigrations --no-input` now logs default answers and reasons why
migrations cannot be created.
Migrations Migrations
~~~~~~~~~~ ~~~~~~~~~~

View File

@ -1361,7 +1361,14 @@ class MakeMigrationsTests(MigrationTestBase):
with self.assertRaises(SystemExit): with self.assertRaises(SystemExit):
with self.temporary_migration_module(module="migrations.test_migrations_no_default"): with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
call_command("makemigrations", "migrations", interactive=False) with captured_stdout() as out:
call_command('makemigrations', 'migrations', interactive=False)
self.assertIn(
"Field 'silly_int' on model 'sillymodel' not migrated: it is "
"impossible to add a non-nullable field without specifying a "
"default.",
out.getvalue(),
)
def test_makemigrations_interactive_not_null_addition(self): def test_makemigrations_interactive_not_null_addition(self):
""" """
@ -1417,10 +1424,15 @@ class MakeMigrationsTests(MigrationTestBase):
class Meta: class Meta:
app_label = "migrations" app_label = "migrations"
out = io.StringIO()
with self.temporary_migration_module(module="migrations.test_migrations"): with self.temporary_migration_module(module="migrations.test_migrations"):
call_command("makemigrations", "migrations", interactive=False, stdout=out) with captured_stdout() as out:
call_command('makemigrations', 'migrations', interactive=False)
self.assertIn("Alter field slug on author", out.getvalue()) self.assertIn("Alter field slug on author", out.getvalue())
self.assertIn(
"Field 'slug' on model 'author' given a default of NOT PROVIDED "
"and must be corrected.",
out.getvalue(),
)
def test_makemigrations_interactive_not_null_alteration(self): def test_makemigrations_interactive_not_null_alteration(self):
""" """
@ -1884,8 +1896,14 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = 'migrations' app_label = 'migrations'
with self.temporary_migration_module(module='migrations.test_auto_now_add'): with self.temporary_migration_module(module='migrations.test_auto_now_add'):
with self.assertRaises(SystemExit): with self.assertRaises(SystemExit), captured_stdout() as out:
call_command('makemigrations', 'migrations', interactive=False) call_command('makemigrations', 'migrations', interactive=False)
self.assertIn(
"Field 'creation_date' on model 'entry' not migrated: it is "
"impossible to add a field with 'auto_now_add=True' without "
"specifying a default.",
out.getvalue(),
)
def test_makemigrations_interactive_unique_callable_default_addition(self): def test_makemigrations_interactive_unique_callable_default_addition(self):
""" """